mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-05 00:20:32 +00:00
Merge branch 'akpm' (patches from Andrew Morton) into next
Merge more updates from Andrew Morton: - Most of the rest of MM. This includes "mark remap_file_pages syscall as deprecated" but the actual "replace remap_file_pages syscall with emulation" is held back. I guess we'll need to work out when to pull the trigger on that one. - various minor cleanups to obscure filesystems - the drivers/rtc queue - hfsplus updates - ufs, hpfs, fatfs, affs, reiserfs - Documentation/ - signals - procfs - cpu hotplug - lib/idr.c - rapidio - sysctl - ipc updates * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (171 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
This commit is contained in:
commit
57d326169e
198 changed files with 4204 additions and 1799 deletions
|
@ -132,6 +132,20 @@ Example:
|
||||||
platform_set_drvdata(), but left the variable "dev" unused,
|
platform_set_drvdata(), but left the variable "dev" unused,
|
||||||
delete it.
|
delete it.
|
||||||
|
|
||||||
|
If your patch fixes a bug in a specific commit, e.g. you found an issue using
|
||||||
|
git-bisect, please use the 'Fixes:' tag with the first 12 characters of the
|
||||||
|
SHA-1 ID, and the one line summary.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Fixes: e21d2170f366 ("video: remove unnecessary platform_set_drvdata()")
|
||||||
|
|
||||||
|
The following git-config settings can be used to add a pretty format for
|
||||||
|
outputting the above style in the git log or git show commands
|
||||||
|
|
||||||
|
[core]
|
||||||
|
abbrev = 12
|
||||||
|
[pretty]
|
||||||
|
fixes = Fixes: %h (\"%s\")
|
||||||
|
|
||||||
3) Separate your changes.
|
3) Separate your changes.
|
||||||
|
|
||||||
|
@ -443,7 +457,7 @@ person it names. This tag documents that potentially interested parties
|
||||||
have been included in the discussion
|
have been included in the discussion
|
||||||
|
|
||||||
|
|
||||||
14) Using Reported-by:, Tested-by:, Reviewed-by: and Suggested-by:
|
14) Using Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: and Fixes:
|
||||||
|
|
||||||
If this patch fixes a problem reported by somebody else, consider adding a
|
If this patch fixes a problem reported by somebody else, consider adding a
|
||||||
Reported-by: tag to credit the reporter for their contribution. Please
|
Reported-by: tag to credit the reporter for their contribution. Please
|
||||||
|
@ -498,6 +512,12 @@ idea was not posted in a public forum. That said, if we diligently credit our
|
||||||
idea reporters, they will, hopefully, be inspired to help us again in the
|
idea reporters, they will, hopefully, be inspired to help us again in the
|
||||||
future.
|
future.
|
||||||
|
|
||||||
|
A Fixes: tag indicates that the patch fixes an issue in a previous commit. It
|
||||||
|
is used to make it easy to determine where a bug originated, which can help
|
||||||
|
review a bug fix. This tag also assists the stable kernel team in determining
|
||||||
|
which stable kernel versions should receive your fix. This is the preferred
|
||||||
|
method for indicating a bug fixed by the patch. See #2 above for more details.
|
||||||
|
|
||||||
|
|
||||||
15) The canonical patch format
|
15) The canonical patch format
|
||||||
|
|
||||||
|
|
|
@ -540,14 +540,13 @@ Note:
|
||||||
|
|
||||||
5.3 swappiness
|
5.3 swappiness
|
||||||
|
|
||||||
Similar to /proc/sys/vm/swappiness, but only affecting reclaim that is
|
Overrides /proc/sys/vm/swappiness for the particular group. The tunable
|
||||||
triggered by this cgroup's hard limit. The tunable in the root cgroup
|
in the root cgroup corresponds to the global swappiness setting.
|
||||||
corresponds to the global swappiness setting.
|
|
||||||
|
|
||||||
Please note that unlike the global swappiness, memcg knob set to 0
|
Please note that unlike during the global reclaim, limit reclaim
|
||||||
really prevents from any swapping even if there is a swap storage
|
enforces that 0 swappiness really prevents from any swapping even if
|
||||||
available. This might lead to memcg OOM killer if there are no file
|
there is a swap storage available. This might lead to memcg OOM killer
|
||||||
pages to reclaim.
|
if there are no file pages to reclaim.
|
||||||
|
|
||||||
5.4 failcnt
|
5.4 failcnt
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@ Required properties:
|
||||||
- interrupts: rtc alarm/event interrupt
|
- interrupts: rtc alarm/event interrupt
|
||||||
- #clock-cells: the value should be 0
|
- #clock-cells: the value should be 0
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- clock-output-names: From common clock binding
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
hym8563: hym8563@51 {
|
hym8563: hym8563@51 {
|
||||||
|
|
28
Documentation/devicetree/bindings/rtc/xgene-rtc.txt
Normal file
28
Documentation/devicetree/bindings/rtc/xgene-rtc.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
* APM X-Gene Real Time Clock
|
||||||
|
|
||||||
|
RTC controller for the APM X-Gene Real Time Clock
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : Should be "apm,xgene-rtc"
|
||||||
|
- reg: physical base address of the controller and length of memory mapped
|
||||||
|
region.
|
||||||
|
- interrupts: IRQ line for the RTC.
|
||||||
|
- #clock-cells: Should be 1.
|
||||||
|
- clocks: Reference to the clock entry.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
rtcclk: rtcclk {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clock-frequency = <100000000>;
|
||||||
|
clock-output-names = "rtcclk";
|
||||||
|
};
|
||||||
|
|
||||||
|
rtc: rtc@10510000 {
|
||||||
|
compatible = "apm,xgene-rtc";
|
||||||
|
reg = <0x0 0x10510000 0x0 0x400>;
|
||||||
|
interrupts = <0x0 0x46 0x4>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clocks = <&rtcclk 0>;
|
||||||
|
};
|
|
@ -54,6 +54,15 @@ how the mechanism works without getting lost in other details. (Those
|
||||||
wanting to see the full source for this module can find it at
|
wanting to see the full source for this module can find it at
|
||||||
http://lwn.net/Articles/22359/).
|
http://lwn.net/Articles/22359/).
|
||||||
|
|
||||||
|
Deprecated create_proc_entry
|
||||||
|
|
||||||
|
Note that the above article uses create_proc_entry which was removed in
|
||||||
|
kernel 3.10. Current versions require the following update
|
||||||
|
|
||||||
|
- entry = create_proc_entry("sequence", 0, NULL);
|
||||||
|
- if (entry)
|
||||||
|
- entry->proc_fops = &ct_file_ops;
|
||||||
|
+ entry = proc_create("sequence", 0, NULL, &ct_file_ops);
|
||||||
|
|
||||||
The iterator interface
|
The iterator interface
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,11 @@ nfs=stale_rw|nostale_ro
|
||||||
To maintain backward compatibility, '-o nfs' is also accepted,
|
To maintain backward compatibility, '-o nfs' is also accepted,
|
||||||
defaulting to stale_rw
|
defaulting to stale_rw
|
||||||
|
|
||||||
|
dos1xfloppy -- If set, use a fallback default BIOS Parameter Block
|
||||||
|
configuration, determined by backing device size. These static
|
||||||
|
parameters match defaults assumed by DOS 1.x for 160 kiB,
|
||||||
|
180 kiB, 320 kiB, and 360 kiB floppies and floppy images.
|
||||||
|
|
||||||
|
|
||||||
<bool>: 0,1,yes,no,true,false
|
<bool>: 0,1,yes,no,true,false
|
||||||
|
|
||||||
|
|
|
@ -2361,6 +2361,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||||
timeout < 0: reboot immediately
|
timeout < 0: reboot immediately
|
||||||
Format: <timeout>
|
Format: <timeout>
|
||||||
|
|
||||||
|
crash_kexec_post_notifiers
|
||||||
|
Run kdump after running panic-notifiers and dumping
|
||||||
|
kmsg. This only for the users who doubt kdump always
|
||||||
|
succeeds in any situation.
|
||||||
|
Note that this also increases risks of kdump failure,
|
||||||
|
because some panic notifiers can make the crashed
|
||||||
|
kernel more unstable.
|
||||||
|
|
||||||
parkbd.port= [HW] Parallel port number the keyboard adapter is
|
parkbd.port= [HW] Parallel port number the keyboard adapter is
|
||||||
connected to, default is 0.
|
connected to, default is 0.
|
||||||
Format: <parport#>
|
Format: <parport#>
|
||||||
|
|
|
@ -142,6 +142,7 @@ kmemleak_alloc_percpu - notify of a percpu memory block allocation
|
||||||
kmemleak_free - notify of a memory block freeing
|
kmemleak_free - notify of a memory block freeing
|
||||||
kmemleak_free_part - notify of a partial memory block freeing
|
kmemleak_free_part - notify of a partial memory block freeing
|
||||||
kmemleak_free_percpu - notify of a percpu memory block freeing
|
kmemleak_free_percpu - notify of a percpu memory block freeing
|
||||||
|
kmemleak_update_trace - update object allocation stack trace
|
||||||
kmemleak_not_leak - mark an object as not a leak
|
kmemleak_not_leak - mark an object as not a leak
|
||||||
kmemleak_ignore - do not scan or report an object as leak
|
kmemleak_ignore - do not scan or report an object as leak
|
||||||
kmemleak_scan_area - add scan areas inside a memory block
|
kmemleak_scan_area - add scan areas inside a memory block
|
||||||
|
|
|
@ -115,8 +115,8 @@ For example, consider the following sequence of events:
|
||||||
CPU 1 CPU 2
|
CPU 1 CPU 2
|
||||||
=============== ===============
|
=============== ===============
|
||||||
{ A == 1; B == 2 }
|
{ A == 1; B == 2 }
|
||||||
A = 3; x = A;
|
A = 3; x = B;
|
||||||
B = 4; y = B;
|
B = 4; y = A;
|
||||||
|
|
||||||
The set of accesses as seen by the memory system in the middle can be arranged
|
The set of accesses as seen by the memory system in the middle can be arranged
|
||||||
in 24 different combinations:
|
in 24 different combinations:
|
||||||
|
|
|
@ -77,6 +77,7 @@ show up in /proc/sys/kernel:
|
||||||
- shmmni
|
- shmmni
|
||||||
- stop-a [ SPARC only ]
|
- stop-a [ SPARC only ]
|
||||||
- sysrq ==> Documentation/sysrq.txt
|
- sysrq ==> Documentation/sysrq.txt
|
||||||
|
- sysctl_writes_strict
|
||||||
- tainted
|
- tainted
|
||||||
- threads-max
|
- threads-max
|
||||||
- unknown_nmi_panic
|
- unknown_nmi_panic
|
||||||
|
@ -762,6 +763,26 @@ without users and with a dead originative process will be destroyed.
|
||||||
|
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
|
sysctl_writes_strict:
|
||||||
|
|
||||||
|
Control how file position affects the behavior of updating sysctl values
|
||||||
|
via the /proc/sys interface:
|
||||||
|
|
||||||
|
-1 - Legacy per-write sysctl value handling, with no printk warnings.
|
||||||
|
Each write syscall must fully contain the sysctl value to be
|
||||||
|
written, and multiple writes on the same sysctl file descriptor
|
||||||
|
will rewrite the sysctl value, regardless of file position.
|
||||||
|
0 - (default) Same behavior as above, but warn about processes that
|
||||||
|
perform writes to a sysctl file descriptor when the file position
|
||||||
|
is not 0.
|
||||||
|
1 - Respect file position when writing sysctl strings. Multiple writes
|
||||||
|
will append to the sysctl value buffer. Anything past the max length
|
||||||
|
of the sysctl value buffer will be ignored. Writes to numeric sysctl
|
||||||
|
entries must always be at file position 0 and the value must be
|
||||||
|
fully contained in the buffer sent in the write syscall.
|
||||||
|
|
||||||
|
==============================================================
|
||||||
|
|
||||||
tainted:
|
tainted:
|
||||||
|
|
||||||
Non-zero if the kernel has been tainted. Numeric values, which
|
Non-zero if the kernel has been tainted. Numeric values, which
|
||||||
|
|
28
Documentation/vm/remap_file_pages.txt
Normal file
28
Documentation/vm/remap_file_pages.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
The remap_file_pages() system call is used to create a nonlinear mapping,
|
||||||
|
that is, a mapping in which the pages of the file are mapped into a
|
||||||
|
nonsequential order in memory. The advantage of using remap_file_pages()
|
||||||
|
over using repeated calls to mmap(2) is that the former approach does not
|
||||||
|
require the kernel to create additional VMA (Virtual Memory Area) data
|
||||||
|
structures.
|
||||||
|
|
||||||
|
Supporting of nonlinear mapping requires significant amount of non-trivial
|
||||||
|
code in kernel virtual memory subsystem including hot paths. Also to get
|
||||||
|
nonlinear mapping work kernel need a way to distinguish normal page table
|
||||||
|
entries from entries with file offset (pte_file). Kernel reserves flag in
|
||||||
|
PTE for this purpose. PTE flags are scarce resource especially on some CPU
|
||||||
|
architectures. It would be nice to free up the flag for other usage.
|
||||||
|
|
||||||
|
Fortunately, there are not many users of remap_file_pages() in the wild.
|
||||||
|
It's only known that one enterprise RDBMS implementation uses the syscall
|
||||||
|
on 32-bit systems to map files bigger than can linearly fit into 32-bit
|
||||||
|
virtual address space. This use-case is not critical anymore since 64-bit
|
||||||
|
systems are widely available.
|
||||||
|
|
||||||
|
The plan is to deprecate the syscall and replace it with an emulation.
|
||||||
|
The emulation will create new VMAs instead of nonlinear mappings. It's
|
||||||
|
going to work slower for rare users of remap_file_pages() but ABI is
|
||||||
|
preserved.
|
||||||
|
|
||||||
|
One side effect of emulation (apart from performance) is that user can hit
|
||||||
|
vm.max_map_count limit more easily due to additional VMAs. See comment for
|
||||||
|
DEFAULT_MAX_MAP_COUNT for more details on the limit.
|
25
MAINTAINERS
25
MAINTAINERS
|
@ -210,6 +210,13 @@ S: Supported
|
||||||
F: Documentation/scsi/aacraid.txt
|
F: Documentation/scsi/aacraid.txt
|
||||||
F: drivers/scsi/aacraid/
|
F: drivers/scsi/aacraid/
|
||||||
|
|
||||||
|
ABI/API
|
||||||
|
L: linux-api@vger.kernel.org
|
||||||
|
F: Documentation/ABI/
|
||||||
|
F: include/linux/syscalls.h
|
||||||
|
F: include/uapi/
|
||||||
|
F: kernel/sys_ni.c
|
||||||
|
|
||||||
ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
|
ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
|
||||||
M: Hans de Goede <hdegoede@redhat.com>
|
M: Hans de Goede <hdegoede@redhat.com>
|
||||||
L: lm-sensors@lm-sensors.org
|
L: lm-sensors@lm-sensors.org
|
||||||
|
@ -647,7 +654,7 @@ F: sound/soc/codecs/ssm*
|
||||||
F: sound/soc/codecs/sigmadsp.*
|
F: sound/soc/codecs/sigmadsp.*
|
||||||
|
|
||||||
ANALOG DEVICES INC ASOC DRIVERS
|
ANALOG DEVICES INC ASOC DRIVERS
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org/
|
W: http://blackfin.uclinux.org/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
@ -1758,54 +1765,54 @@ F: include/uapi/linux/bfs_fs.h
|
||||||
|
|
||||||
BLACKFIN ARCHITECTURE
|
BLACKFIN ARCHITECTURE
|
||||||
M: Steven Miao <realmz6@gmail.com>
|
M: Steven Miao <realmz6@gmail.com>
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
T: git git://git.code.sf.net/p/adi-linux/code
|
T: git git://git.code.sf.net/p/adi-linux/code
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: arch/blackfin/
|
F: arch/blackfin/
|
||||||
|
|
||||||
BLACKFIN EMAC DRIVER
|
BLACKFIN EMAC DRIVER
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/net/ethernet/adi/
|
F: drivers/net/ethernet/adi/
|
||||||
|
|
||||||
BLACKFIN RTC DRIVER
|
BLACKFIN RTC DRIVER
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/rtc/rtc-bfin.c
|
F: drivers/rtc/rtc-bfin.c
|
||||||
|
|
||||||
BLACKFIN SDH DRIVER
|
BLACKFIN SDH DRIVER
|
||||||
M: Sonic Zhang <sonic.zhang@analog.com>
|
M: Sonic Zhang <sonic.zhang@analog.com>
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/mmc/host/bfin_sdh.c
|
F: drivers/mmc/host/bfin_sdh.c
|
||||||
|
|
||||||
BLACKFIN SERIAL DRIVER
|
BLACKFIN SERIAL DRIVER
|
||||||
M: Sonic Zhang <sonic.zhang@analog.com>
|
M: Sonic Zhang <sonic.zhang@analog.com>
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/tty/serial/bfin_uart.c
|
F: drivers/tty/serial/bfin_uart.c
|
||||||
|
|
||||||
BLACKFIN WATCHDOG DRIVER
|
BLACKFIN WATCHDOG DRIVER
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org
|
W: http://blackfin.uclinux.org
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/watchdog/bfin_wdt.c
|
F: drivers/watchdog/bfin_wdt.c
|
||||||
|
|
||||||
BLACKFIN I2C TWI DRIVER
|
BLACKFIN I2C TWI DRIVER
|
||||||
M: Sonic Zhang <sonic.zhang@analog.com>
|
M: Sonic Zhang <sonic.zhang@analog.com>
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org/
|
W: http://blackfin.uclinux.org/
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/i2c/busses/i2c-bfin-twi.c
|
F: drivers/i2c/busses/i2c-bfin-twi.c
|
||||||
|
|
||||||
BLACKFIN MEDIA DRIVER
|
BLACKFIN MEDIA DRIVER
|
||||||
M: Scott Jiang <scott.jiang.linux@gmail.com>
|
M: Scott Jiang <scott.jiang.linux@gmail.com>
|
||||||
L: adi-buildroot-devel@lists.sourceforge.net
|
L: adi-buildroot-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||||
W: http://blackfin.uclinux.org/
|
W: http://blackfin.uclinux.org/
|
||||||
S: Supported
|
S: Supported
|
||||||
F: drivers/media/platform/blackfin/
|
F: drivers/media/platform/blackfin/
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
static unsigned int isa_membase, isa_portbase, isa_portshift;
|
static unsigned int isa_membase, isa_portbase, isa_portshift;
|
||||||
|
|
||||||
static ctl_table ctl_isa_vars[4] = {
|
static struct ctl_table ctl_isa_vars[4] = {
|
||||||
{
|
{
|
||||||
.procname = "membase",
|
.procname = "membase",
|
||||||
.data = &isa_membase,
|
.data = &isa_membase,
|
||||||
|
@ -44,7 +44,7 @@ static ctl_table ctl_isa_vars[4] = {
|
||||||
|
|
||||||
static struct ctl_table_header *isa_sysctl_header;
|
static struct ctl_table_header *isa_sysctl_header;
|
||||||
|
|
||||||
static ctl_table ctl_isa[2] = {
|
static struct ctl_table ctl_isa[2] = {
|
||||||
{
|
{
|
||||||
.procname = "isa",
|
.procname = "isa",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
@ -52,7 +52,7 @@ static ctl_table ctl_isa[2] = {
|
||||||
}, {}
|
}, {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table ctl_bus[2] = {
|
static struct ctl_table ctl_bus[2] = {
|
||||||
{
|
{
|
||||||
.procname = "bus",
|
.procname = "bus",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -25,24 +25,28 @@
|
||||||
|
|
||||||
#include "generic.h"
|
#include "generic.h"
|
||||||
|
|
||||||
#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */
|
#define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */
|
||||||
#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */
|
#define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */
|
||||||
|
#define AT91_RTC_IRQ_MASK 0x1f /* Available IRQs mask */
|
||||||
|
|
||||||
void __init at91_sysirq_mask_rtc(u32 rtc_base)
|
void __init at91_sysirq_mask_rtc(u32 rtc_base)
|
||||||
{
|
{
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
u32 mask;
|
|
||||||
|
|
||||||
base = ioremap(rtc_base, 64);
|
base = ioremap(rtc_base, 64);
|
||||||
if (!base)
|
if (!base)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mask = readl_relaxed(base + AT91_RTC_IMR);
|
/*
|
||||||
if (mask) {
|
* sam9x5 SoCs have the following errata:
|
||||||
pr_info("AT91: Disabling rtc irq\n");
|
* "RTC: Interrupt Mask Register cannot be used
|
||||||
writel_relaxed(mask, base + AT91_RTC_IDR);
|
* Interrupt Mask Register read always returns 0."
|
||||||
(void)readl_relaxed(base + AT91_RTC_IMR); /* flush */
|
*
|
||||||
}
|
* Hence we're not relying on IMR values to disable
|
||||||
|
* interrupts.
|
||||||
|
*/
|
||||||
|
writel_relaxed(AT91_RTC_IRQ_MASK, base + AT91_RTC_IDR);
|
||||||
|
(void)readl_relaxed(base + AT91_RTC_IMR); /* flush */
|
||||||
|
|
||||||
iounmap(base);
|
iounmap(base);
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,6 +257,19 @@ sata45clk: sata45clk@1f23c000 {
|
||||||
enable-offset = <0x0>;
|
enable-offset = <0x0>;
|
||||||
enable-mask = <0x39>;
|
enable-mask = <0x39>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rtcclk: rtcclk@17000000 {
|
||||||
|
compatible = "apm,xgene-device-clock";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clocks = <&socplldiv2 0>;
|
||||||
|
reg = <0x0 0x17000000 0x0 0x2000>;
|
||||||
|
reg-names = "csr-reg";
|
||||||
|
csr-offset = <0xc>;
|
||||||
|
csr-mask = <0x2>;
|
||||||
|
enable-offset = <0x10>;
|
||||||
|
enable-mask = <0x2>;
|
||||||
|
clock-output-names = "rtcclk";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
serial0: serial@1c020000 {
|
serial0: serial@1c020000 {
|
||||||
|
@ -342,5 +355,13 @@ sata3: sata@1a800000 {
|
||||||
phys = <&phy3 0>;
|
phys = <&phy3 0>;
|
||||||
phy-names = "sata-phy";
|
phy-names = "sata-phy";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rtc: rtc@10510000 {
|
||||||
|
compatible = "apm,xgene-rtc";
|
||||||
|
reg = <0x0 0x10510000 0x0 0x400>;
|
||||||
|
interrupts = <0x0 0x46 0x4>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
clocks = <&rtcclk 0>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,6 +117,7 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data)
|
||||||
int
|
int
|
||||||
is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
|
is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len)
|
||||||
{
|
{
|
||||||
|
bool valid;
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
struct sram_list_struct *sraml;
|
struct sram_list_struct *sraml;
|
||||||
|
|
||||||
|
@ -124,9 +125,12 @@ is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long
|
||||||
if (start + len < start)
|
if (start + len < start)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
down_read(&child->mm->mmap_sem);
|
||||||
vma = find_vma(child->mm, start);
|
vma = find_vma(child->mm, start);
|
||||||
if (vma && start >= vma->vm_start && start + len <= vma->vm_end)
|
valid = vma && start >= vma->vm_start && start + len <= vma->vm_end;
|
||||||
return 0;
|
up_read(&child->mm->mmap_sem);
|
||||||
|
if (valid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
|
for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
|
||||||
if (start >= (unsigned long)sraml->addr
|
if (start >= (unsigned long)sraml->addr
|
||||||
|
|
|
@ -833,8 +833,8 @@ static int __init gpio_init(void)
|
||||||
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001-2008 "
|
printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001-2008 "
|
||||||
"Axis Communications AB\n");
|
"Axis Communications AB\n");
|
||||||
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
||||||
* from cpu_idle() in kernel/process.c
|
* from default_idle() in kernel/process.c
|
||||||
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
|
* The check in default_idle() reduces latency from ~15 ms to ~6 ms
|
||||||
* in some tests.
|
* in some tests.
|
||||||
*/
|
*/
|
||||||
res = request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
|
res = request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt,
|
||||||
|
|
|
@ -958,11 +958,7 @@ gpio_init(void)
|
||||||
|
|
||||||
printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 "
|
printk(KERN_INFO "ETRAX FS GPIO driver v2.5, (c) 2003-2007 "
|
||||||
"Axis Communications AB\n");
|
"Axis Communications AB\n");
|
||||||
/* We call etrax_gpio_wake_up_check() from timer interrupt and
|
/* We call etrax_gpio_wake_up_check() from timer interrupt */
|
||||||
* from cpu_idle() in kernel/process.c
|
|
||||||
* The check in cpu_idle() reduces latency from ~15 ms to ~6 ms
|
|
||||||
* in some tests.
|
|
||||||
*/
|
|
||||||
if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
|
if (request_irq(TIMER0_INTR_VECT, gpio_poll_timer_interrupt,
|
||||||
IRQF_SHARED, "gpio poll", &alarmlist))
|
IRQF_SHARED, "gpio poll", &alarmlist))
|
||||||
printk(KERN_ERR "timer0 irq for gpio\n");
|
printk(KERN_ERR "timer0 irq for gpio\n");
|
||||||
|
|
|
@ -237,7 +237,7 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
static ctl_table kdump_ctl_table[] = {
|
static struct ctl_table kdump_ctl_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "kdump_on_init",
|
.procname = "kdump_on_init",
|
||||||
.data = &kdump_on_init,
|
.data = &kdump_on_init,
|
||||||
|
@ -255,7 +255,7 @@ static ctl_table kdump_ctl_table[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table sys_table[] = {
|
static struct ctl_table sys_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "kernel",
|
.procname = "kernel",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -521,7 +521,7 @@ static pmu_config_t *pmu_conf;
|
||||||
pfm_sysctl_t pfm_sysctl;
|
pfm_sysctl_t pfm_sysctl;
|
||||||
EXPORT_SYMBOL(pfm_sysctl);
|
EXPORT_SYMBOL(pfm_sysctl);
|
||||||
|
|
||||||
static ctl_table pfm_ctl_table[]={
|
static struct ctl_table pfm_ctl_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "debug",
|
.procname = "debug",
|
||||||
.data = &pfm_sysctl.debug,
|
.data = &pfm_sysctl.debug,
|
||||||
|
@ -552,7 +552,7 @@ static ctl_table pfm_ctl_table[]={
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static ctl_table pfm_sysctl_dir[] = {
|
static struct ctl_table pfm_sysctl_dir[] = {
|
||||||
{
|
{
|
||||||
.procname = "perfmon",
|
.procname = "perfmon",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
@ -560,7 +560,7 @@ static ctl_table pfm_sysctl_dir[] = {
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
static ctl_table pfm_sysctl_root[] = {
|
static struct ctl_table pfm_sysctl_root[] = {
|
||||||
{
|
{
|
||||||
.procname = "kernel",
|
.procname = "kernel",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -60,15 +60,6 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
|
||||||
__const_sigismember(set,sig) : \
|
__const_sigismember(set,sig) : \
|
||||||
__gen_sigismember(set,sig))
|
__gen_sigismember(set,sig))
|
||||||
|
|
||||||
static inline int sigfindinword(unsigned long word)
|
|
||||||
{
|
|
||||||
asm ("bfffo %1{#0,#0},%0"
|
|
||||||
: "=d" (word)
|
|
||||||
: "d" (word & -word)
|
|
||||||
: "cc");
|
|
||||||
return word ^ 31;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
|
#endif /* !CONFIG_CPU_HAS_NO_BITFIELDS */
|
||||||
|
|
||||||
#ifndef __uClinux__
|
#ifndef __uClinux__
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
|
obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
|
||||||
kn02-irq.o kn02xa-berr.o reset.o setup.o time.o
|
kn02-irq.o kn02xa-berr.o platform.o reset.o setup.o time.o
|
||||||
|
|
||||||
obj-$(CONFIG_TC) += tc.o
|
obj-$(CONFIG_TC) += tc.o
|
||||||
obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
|
obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
|
||||||
|
|
44
arch/mips/dec/platform.c
Normal file
44
arch/mips/dec/platform.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* DEC platform devices.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Maciej W. Rozycki
|
||||||
|
*
|
||||||
|
* 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/ioport.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mc146818rtc.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
static struct resource dec_rtc_resources[] = {
|
||||||
|
{
|
||||||
|
.name = "rtc",
|
||||||
|
.flags = IORESOURCE_MEM,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cmos_rtc_board_info dec_rtc_info = {
|
||||||
|
.flags = CMOS_RTC_FLAGS_NOFREQ,
|
||||||
|
.address_space = 64,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_device dec_rtc_device = {
|
||||||
|
.name = "rtc_cmos",
|
||||||
|
.id = PLATFORM_DEVID_NONE,
|
||||||
|
.dev.platform_data = &dec_rtc_info,
|
||||||
|
.resource = dec_rtc_resources,
|
||||||
|
.num_resources = ARRAY_SIZE(dec_rtc_resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init dec_add_devices(void)
|
||||||
|
{
|
||||||
|
dec_rtc_resources[0].start = RTC_PORT(0);
|
||||||
|
dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
|
||||||
|
return platform_device_register(&dec_rtc_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
device_initcall(dec_add_devices);
|
|
@ -304,7 +304,7 @@ void notrace restore_interrupts(void)
|
||||||
* being re-enabled and generally sanitized the lazy irq state,
|
* being re-enabled and generally sanitized the lazy irq state,
|
||||||
* and in the latter case it will leave with interrupts hard
|
* and in the latter case it will leave with interrupts hard
|
||||||
* disabled and marked as such, so the local_irq_enable() call
|
* disabled and marked as such, so the local_irq_enable() call
|
||||||
* in cpu_idle() will properly re-enable everything.
|
* in arch_cpu_idle() will properly re-enable everything.
|
||||||
*/
|
*/
|
||||||
bool prep_irq_for_idle(void)
|
bool prep_irq_for_idle(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -113,7 +113,7 @@ arch_initcall(proc_tile_init);
|
||||||
* Support /proc/sys/tile directory
|
* Support /proc/sys/tile directory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static ctl_table unaligned_subtable[] = {
|
static struct ctl_table unaligned_subtable[] = {
|
||||||
{
|
{
|
||||||
.procname = "enabled",
|
.procname = "enabled",
|
||||||
.data = &unaligned_fixup,
|
.data = &unaligned_fixup,
|
||||||
|
@ -138,7 +138,7 @@ static ctl_table unaligned_subtable[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table unaligned_table[] = {
|
static struct ctl_table unaligned_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "unaligned_fixup",
|
.procname = "unaligned_fixup",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -92,12 +92,6 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
|
||||||
? __const_sigismember((set), (sig)) \
|
? __const_sigismember((set), (sig)) \
|
||||||
: __gen_sigismember((set), (sig)))
|
: __gen_sigismember((set), (sig)))
|
||||||
|
|
||||||
static inline int sigfindinword(unsigned long word)
|
|
||||||
{
|
|
||||||
asm("bsfl %1,%0" : "=r"(word) : "rm"(word) : "cc");
|
|
||||||
return word;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct pt_regs;
|
struct pt_regs;
|
||||||
|
|
||||||
#else /* __i386__ */
|
#else /* __i386__ */
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
* - Split from highmem.c
|
* - Split from highmem.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
|
@ -15,6 +17,7 @@
|
||||||
#include <linux/hash.h>
|
#include <linux/hash.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
|
|
||||||
#include <trace/events/block.h>
|
#include <trace/events/block.h>
|
||||||
|
@ -34,7 +37,7 @@ static __init int init_emergency_pool(void)
|
||||||
|
|
||||||
page_pool = mempool_create_page_pool(POOL_SIZE, 0);
|
page_pool = mempool_create_page_pool(POOL_SIZE, 0);
|
||||||
BUG_ON(!page_pool);
|
BUG_ON(!page_pool);
|
||||||
printk("bounce pool size: %d pages\n", POOL_SIZE);
|
pr_info("pool size: %d pages\n", POOL_SIZE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +89,7 @@ int init_emergency_isa_pool(void)
|
||||||
mempool_free_pages, (void *) 0);
|
mempool_free_pages, (void *) 0);
|
||||||
BUG_ON(!isa_page_pool);
|
BUG_ON(!isa_page_pool);
|
||||||
|
|
||||||
printk("isa bounce pool size: %d pages\n", ISA_POOL_SIZE);
|
pr_info("isa pool size: %d pages\n", ISA_POOL_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,14 +243,11 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req)
|
||||||
struct nbd_request request;
|
struct nbd_request request;
|
||||||
unsigned long size = blk_rq_bytes(req);
|
unsigned long size = blk_rq_bytes(req);
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(request));
|
||||||
request.magic = htonl(NBD_REQUEST_MAGIC);
|
request.magic = htonl(NBD_REQUEST_MAGIC);
|
||||||
request.type = htonl(nbd_cmd(req));
|
request.type = htonl(nbd_cmd(req));
|
||||||
|
|
||||||
if (nbd_cmd(req) == NBD_CMD_FLUSH) {
|
if (nbd_cmd(req) != NBD_CMD_FLUSH && nbd_cmd(req) != NBD_CMD_DISC) {
|
||||||
/* Other values are reserved for FLUSH requests. */
|
|
||||||
request.from = 0;
|
|
||||||
request.len = 0;
|
|
||||||
} else {
|
|
||||||
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
|
request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9);
|
||||||
request.len = htonl(size);
|
request.len = htonl(size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3470,7 +3470,7 @@ static int cdrom_print_info(const char *header, int val, char *info,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cdrom_sysctl_info(ctl_table *ctl, int write,
|
static int cdrom_sysctl_info(struct ctl_table *ctl, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
|
@ -3583,7 +3583,7 @@ static void cdrom_update_settings(void)
|
||||||
mutex_unlock(&cdrom_mutex);
|
mutex_unlock(&cdrom_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cdrom_sysctl_handler(ctl_table *ctl, int write,
|
static int cdrom_sysctl_handler(struct ctl_table *ctl, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -3609,7 +3609,7 @@ static int cdrom_sysctl_handler(ctl_table *ctl, int write,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place files in /proc/sys/dev/cdrom */
|
/* Place files in /proc/sys/dev/cdrom */
|
||||||
static ctl_table cdrom_table[] = {
|
static struct ctl_table cdrom_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "info",
|
.procname = "info",
|
||||||
.data = &cdrom_sysctl_settings.info,
|
.data = &cdrom_sysctl_settings.info,
|
||||||
|
@ -3655,7 +3655,7 @@ static ctl_table cdrom_table[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table cdrom_cdrom_table[] = {
|
static struct ctl_table cdrom_cdrom_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "cdrom",
|
.procname = "cdrom",
|
||||||
.maxlen = 0,
|
.maxlen = 0,
|
||||||
|
@ -3666,7 +3666,7 @@ static ctl_table cdrom_cdrom_table[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Make sure that /proc/sys/dev is there */
|
/* Make sure that /proc/sys/dev is there */
|
||||||
static ctl_table cdrom_root_table[] = {
|
static struct ctl_table cdrom_root_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "dev",
|
.procname = "dev",
|
||||||
.maxlen = 0,
|
.maxlen = 0,
|
||||||
|
|
|
@ -1582,10 +1582,10 @@ static int proc_do_uuid(struct ctl_table *table, int write,
|
||||||
/*
|
/*
|
||||||
* Return entropy available scaled to integral bits
|
* Return entropy available scaled to integral bits
|
||||||
*/
|
*/
|
||||||
static int proc_do_entropy(ctl_table *table, int write,
|
static int proc_do_entropy(struct ctl_table *table, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
ctl_table fake_table;
|
struct ctl_table fake_table;
|
||||||
int entropy_count;
|
int entropy_count;
|
||||||
|
|
||||||
entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
|
entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#define PARPORT_MIN_SPINTIME_VALUE 1
|
#define PARPORT_MIN_SPINTIME_VALUE 1
|
||||||
#define PARPORT_MAX_SPINTIME_VALUE 1000
|
#define PARPORT_MAX_SPINTIME_VALUE 1000
|
||||||
|
|
||||||
static int do_active_device(ctl_table *table, int write,
|
static int do_active_device(struct ctl_table *table, int write,
|
||||||
void __user *result, size_t *lenp, loff_t *ppos)
|
void __user *result, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport *port = (struct parport *)table->extra1;
|
struct parport *port = (struct parport *)table->extra1;
|
||||||
|
@ -68,7 +68,7 @@ static int do_active_device(ctl_table *table, int write,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PARPORT_1284
|
#ifdef CONFIG_PARPORT_1284
|
||||||
static int do_autoprobe(ctl_table *table, int write,
|
static int do_autoprobe(struct ctl_table *table, int write,
|
||||||
void __user *result, size_t *lenp, loff_t *ppos)
|
void __user *result, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport_device_info *info = table->extra2;
|
struct parport_device_info *info = table->extra2;
|
||||||
|
@ -110,9 +110,9 @@ static int do_autoprobe(ctl_table *table, int write,
|
||||||
}
|
}
|
||||||
#endif /* IEEE1284.3 support. */
|
#endif /* IEEE1284.3 support. */
|
||||||
|
|
||||||
static int do_hardware_base_addr (ctl_table *table, int write,
|
static int do_hardware_base_addr(struct ctl_table *table, int write,
|
||||||
void __user *result,
|
void __user *result,
|
||||||
size_t *lenp, loff_t *ppos)
|
size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport *port = (struct parport *)table->extra1;
|
struct parport *port = (struct parport *)table->extra1;
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
@ -138,9 +138,9 @@ static int do_hardware_base_addr (ctl_table *table, int write,
|
||||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_hardware_irq (ctl_table *table, int write,
|
static int do_hardware_irq(struct ctl_table *table, int write,
|
||||||
void __user *result,
|
void __user *result,
|
||||||
size_t *lenp, loff_t *ppos)
|
size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport *port = (struct parport *)table->extra1;
|
struct parport *port = (struct parport *)table->extra1;
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
@ -166,9 +166,9 @@ static int do_hardware_irq (ctl_table *table, int write,
|
||||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_hardware_dma (ctl_table *table, int write,
|
static int do_hardware_dma(struct ctl_table *table, int write,
|
||||||
void __user *result,
|
void __user *result,
|
||||||
size_t *lenp, loff_t *ppos)
|
size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport *port = (struct parport *)table->extra1;
|
struct parport *port = (struct parport *)table->extra1;
|
||||||
char buffer[20];
|
char buffer[20];
|
||||||
|
@ -194,9 +194,9 @@ static int do_hardware_dma (ctl_table *table, int write,
|
||||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_hardware_modes (ctl_table *table, int write,
|
static int do_hardware_modes(struct ctl_table *table, int write,
|
||||||
void __user *result,
|
void __user *result,
|
||||||
size_t *lenp, loff_t *ppos)
|
size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct parport *port = (struct parport *)table->extra1;
|
struct parport *port = (struct parport *)table->extra1;
|
||||||
char buffer[40];
|
char buffer[40];
|
||||||
|
@ -255,11 +255,11 @@ PARPORT_MAX_SPINTIME_VALUE;
|
||||||
|
|
||||||
struct parport_sysctl_table {
|
struct parport_sysctl_table {
|
||||||
struct ctl_table_header *sysctl_header;
|
struct ctl_table_header *sysctl_header;
|
||||||
ctl_table vars[12];
|
struct ctl_table vars[12];
|
||||||
ctl_table device_dir[2];
|
struct ctl_table device_dir[2];
|
||||||
ctl_table port_dir[2];
|
struct ctl_table port_dir[2];
|
||||||
ctl_table parport_dir[2];
|
struct ctl_table parport_dir[2];
|
||||||
ctl_table dev_dir[2];
|
struct ctl_table dev_dir[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct parport_sysctl_table parport_sysctl_template = {
|
static const struct parport_sysctl_table parport_sysctl_template = {
|
||||||
|
@ -369,12 +369,12 @@ static const struct parport_sysctl_table parport_sysctl_template = {
|
||||||
struct parport_device_sysctl_table
|
struct parport_device_sysctl_table
|
||||||
{
|
{
|
||||||
struct ctl_table_header *sysctl_header;
|
struct ctl_table_header *sysctl_header;
|
||||||
ctl_table vars[2];
|
struct ctl_table vars[2];
|
||||||
ctl_table device_dir[2];
|
struct ctl_table device_dir[2];
|
||||||
ctl_table devices_root_dir[2];
|
struct ctl_table devices_root_dir[2];
|
||||||
ctl_table port_dir[2];
|
struct ctl_table port_dir[2];
|
||||||
ctl_table parport_dir[2];
|
struct ctl_table parport_dir[2];
|
||||||
ctl_table dev_dir[2];
|
struct ctl_table dev_dir[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct parport_device_sysctl_table
|
static const struct parport_device_sysctl_table
|
||||||
|
@ -422,10 +422,10 @@ parport_device_sysctl_template = {
|
||||||
struct parport_default_sysctl_table
|
struct parport_default_sysctl_table
|
||||||
{
|
{
|
||||||
struct ctl_table_header *sysctl_header;
|
struct ctl_table_header *sysctl_header;
|
||||||
ctl_table vars[3];
|
struct ctl_table vars[3];
|
||||||
ctl_table default_dir[2];
|
struct ctl_table default_dir[2];
|
||||||
ctl_table parport_dir[2];
|
struct ctl_table parport_dir[2];
|
||||||
ctl_table dev_dir[2];
|
struct ctl_table dev_dir[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct parport_default_sysctl_table
|
static struct parport_default_sysctl_table
|
||||||
|
|
|
@ -768,15 +768,10 @@ static int tsi721_enable_msix(struct tsi721_device *priv)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_RAPIDIO_DMA_ENGINE */
|
#endif /* CONFIG_RAPIDIO_DMA_ENGINE */
|
||||||
|
|
||||||
err = pci_enable_msix(priv->pdev, entries, ARRAY_SIZE(entries));
|
err = pci_enable_msix_exact(priv->pdev, entries, ARRAY_SIZE(entries));
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err > 0)
|
dev_err(&priv->pdev->dev,
|
||||||
dev_info(&priv->pdev->dev,
|
"Failed to enable MSI-X (err=%d)\n", err);
|
||||||
"Only %d MSI-X vectors available, "
|
|
||||||
"not using MSI-X\n", err);
|
|
||||||
else
|
|
||||||
dev_err(&priv->pdev->dev,
|
|
||||||
"Failed to enable MSI-X (err=%d)\n", err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -386,12 +386,12 @@ config RTC_DRV_PCF8583
|
||||||
will be called rtc-pcf8583.
|
will be called rtc-pcf8583.
|
||||||
|
|
||||||
config RTC_DRV_M41T80
|
config RTC_DRV_M41T80
|
||||||
tristate "ST M41T62/65/M41T80/81/82/83/84/85/87"
|
tristate "ST M41T62/65/M41T80/81/82/83/84/85/87 and compatible"
|
||||||
help
|
help
|
||||||
If you say Y here you will get support for the ST M41T60
|
If you say Y here you will get support for the ST M41T60
|
||||||
and M41T80 RTC chips series. Currently, the following chips are
|
and M41T80 RTC chips series. Currently, the following chips are
|
||||||
supported: M41T62, M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84,
|
supported: M41T62, M41T65, M41T80, M41T81, M41T82, M41T83, M41ST84,
|
||||||
M41ST85, and M41ST87.
|
M41ST85, M41ST87, and MicroCrystal RV4162.
|
||||||
|
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-m41t80.
|
will be called rtc-m41t80.
|
||||||
|
@ -573,6 +573,17 @@ config RTC_DRV_DS1305
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-ds1305.
|
will be called rtc-ds1305.
|
||||||
|
|
||||||
|
config RTC_DRV_DS1343
|
||||||
|
select REGMAP_SPI
|
||||||
|
tristate "Dallas/Maxim DS1343/DS1344"
|
||||||
|
help
|
||||||
|
If you say yes here you get support for the
|
||||||
|
Dallas/Maxim DS1343 and DS1344 real time clock chips.
|
||||||
|
Support for trickle charger, alarm is provided.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called rtc-ds1343.
|
||||||
|
|
||||||
config RTC_DRV_DS1347
|
config RTC_DRV_DS1347
|
||||||
tristate "Dallas/Maxim DS1347"
|
tristate "Dallas/Maxim DS1347"
|
||||||
help
|
help
|
||||||
|
@ -650,6 +661,14 @@ config RTC_DRV_RX4581
|
||||||
This driver can also be built as a module. If so the module
|
This driver can also be built as a module. If so the module
|
||||||
will be called rtc-rx4581.
|
will be called rtc-rx4581.
|
||||||
|
|
||||||
|
config RTC_DRV_MCP795
|
||||||
|
tristate "Microchip MCP795"
|
||||||
|
help
|
||||||
|
If you say yes here you will get support for the Microchip MCP795.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so the module
|
||||||
|
will be called rtc-mcp795.
|
||||||
|
|
||||||
endif # SPI_MASTER
|
endif # SPI_MASTER
|
||||||
|
|
||||||
comment "Platform RTC drivers"
|
comment "Platform RTC drivers"
|
||||||
|
@ -758,6 +777,16 @@ config RTC_DRV_DA9055
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-da9055
|
will be called rtc-da9055
|
||||||
|
|
||||||
|
config RTC_DRV_DA9063
|
||||||
|
tristate "Dialog Semiconductor DA9063 RTC"
|
||||||
|
depends on MFD_DA9063
|
||||||
|
help
|
||||||
|
If you say yes here you will get support for the RTC subsystem
|
||||||
|
of the Dialog Semiconductor DA9063.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called "rtc-da9063".
|
||||||
|
|
||||||
config RTC_DRV_EFI
|
config RTC_DRV_EFI
|
||||||
tristate "EFI RTC"
|
tristate "EFI RTC"
|
||||||
depends on IA64
|
depends on IA64
|
||||||
|
@ -1327,6 +1356,15 @@ config RTC_DRV_MOXART
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-moxart
|
will be called rtc-moxart
|
||||||
|
|
||||||
|
config RTC_DRV_XGENE
|
||||||
|
tristate "APM X-Gene RTC"
|
||||||
|
help
|
||||||
|
If you say yes here you get support for the APM X-Gene SoC real time
|
||||||
|
clock.
|
||||||
|
|
||||||
|
This driver can also be built as a module, if so, the module
|
||||||
|
will be called "rtc-xgene".
|
||||||
|
|
||||||
comment "HID Sensor RTC drivers"
|
comment "HID Sensor RTC drivers"
|
||||||
|
|
||||||
config RTC_DRV_HID_SENSOR_TIME
|
config RTC_DRV_HID_SENSOR_TIME
|
||||||
|
|
|
@ -32,6 +32,7 @@ obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o
|
||||||
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
|
obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o
|
||||||
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
|
obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o
|
||||||
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
|
obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_DA9063) += rtc-da9063.o
|
||||||
obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o
|
obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o
|
||||||
obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
|
obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o
|
||||||
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
|
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
|
||||||
|
@ -40,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
|
obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
|
obj-$(CONFIG_RTC_DRV_DS1305) += rtc-ds1305.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
|
obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_DS1343) += rtc-ds1343.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1347) += rtc-ds1347.o
|
obj-$(CONFIG_RTC_DRV_DS1347) += rtc-ds1347.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
|
obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o
|
||||||
obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o
|
obj-$(CONFIG_RTC_DRV_DS1390) += rtc-ds1390.o
|
||||||
|
@ -80,6 +82,7 @@ obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
|
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
|
||||||
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
|
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
|
||||||
obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.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
|
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
|
||||||
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
|
obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
|
||||||
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
|
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
|
||||||
|
@ -135,5 +138,6 @@ obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
|
||||||
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
|
obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
|
||||||
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
|
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
|
||||||
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
|
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
|
||||||
|
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
|
||||||
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
|
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
|
||||||
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
|
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
|
||||||
|
|
|
@ -292,7 +292,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
||||||
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
|
dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
|
||||||
do {
|
do {
|
||||||
alarm->time.tm_year++;
|
alarm->time.tm_year++;
|
||||||
} while (rtc_valid_tm(&alarm->time) != 0);
|
} while (!is_leap_year(alarm->time.tm_year + 1900)
|
||||||
|
&& rtc_valid_tm(&alarm->time) != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -300,7 +301,16 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return 0;
|
err = rtc_valid_tm(&alarm->time);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
dev_warn(&rtc->dev, "invalid alarm value: %d-%d-%d %d:%d:%d\n",
|
||||||
|
alarm->time.tm_year + 1900, alarm->time.tm_mon + 1,
|
||||||
|
alarm->time.tm_mday, alarm->time.tm_hour, alarm->time.tm_min,
|
||||||
|
alarm->time.tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
||||||
|
|
|
@ -293,7 +293,7 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev,
|
||||||
int ret;
|
int ret;
|
||||||
if (!np)
|
if (!np)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
np = of_find_node_by_name(np, "rtc");
|
np = of_get_child_by_name(np, "rtc");
|
||||||
if (!np) {
|
if (!np) {
|
||||||
dev_err(&pdev->dev, "failed to find rtc node\n");
|
dev_err(&pdev->dev, "failed to find rtc node\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -301,6 +301,7 @@ static int pm860x_rtc_dt_init(struct platform_device *pdev,
|
||||||
ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc);
|
ret = of_property_read_u32(np, "marvell,88pm860x-vrtc", &info->vrtc);
|
||||||
if (ret)
|
if (ret)
|
||||||
info->vrtc = 0;
|
info->vrtc = 0;
|
||||||
|
of_node_put(np);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct at91_rtc_config {
|
||||||
|
|
||||||
static const struct at91_rtc_config *at91_rtc_config;
|
static const struct at91_rtc_config *at91_rtc_config;
|
||||||
static DECLARE_COMPLETION(at91_rtc_updated);
|
static DECLARE_COMPLETION(at91_rtc_updated);
|
||||||
|
static DECLARE_COMPLETION(at91_rtc_upd_rdy);
|
||||||
static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
|
static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
|
||||||
static void __iomem *at91_rtc_regs;
|
static void __iomem *at91_rtc_regs;
|
||||||
static int irq;
|
static int irq;
|
||||||
|
@ -161,6 +162,8 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
|
||||||
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
|
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
|
||||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||||
|
|
||||||
|
wait_for_completion(&at91_rtc_upd_rdy);
|
||||||
|
|
||||||
/* Stop Time/Calendar from counting */
|
/* Stop Time/Calendar from counting */
|
||||||
cr = at91_rtc_read(AT91_RTC_CR);
|
cr = at91_rtc_read(AT91_RTC_CR);
|
||||||
at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
|
at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
|
||||||
|
@ -183,7 +186,9 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
|
||||||
|
|
||||||
/* Restart Time/Calendar */
|
/* Restart Time/Calendar */
|
||||||
cr = at91_rtc_read(AT91_RTC_CR);
|
cr = at91_rtc_read(AT91_RTC_CR);
|
||||||
|
at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
|
||||||
at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
|
at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
|
||||||
|
at91_rtc_write_ier(AT91_RTC_SECEV);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -290,8 +295,10 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
|
||||||
if (rtsr) { /* this interrupt is shared! Is it ours? */
|
if (rtsr) { /* this interrupt is shared! Is it ours? */
|
||||||
if (rtsr & AT91_RTC_ALARM)
|
if (rtsr & AT91_RTC_ALARM)
|
||||||
events |= (RTC_AF | RTC_IRQF);
|
events |= (RTC_AF | RTC_IRQF);
|
||||||
if (rtsr & AT91_RTC_SECEV)
|
if (rtsr & AT91_RTC_SECEV) {
|
||||||
events |= (RTC_UF | RTC_IRQF);
|
complete(&at91_rtc_upd_rdy);
|
||||||
|
at91_rtc_write_idr(AT91_RTC_SECEV);
|
||||||
|
}
|
||||||
if (rtsr & AT91_RTC_ACKUPD)
|
if (rtsr & AT91_RTC_ACKUPD)
|
||||||
complete(&at91_rtc_updated);
|
complete(&at91_rtc_updated);
|
||||||
|
|
||||||
|
@ -413,6 +420,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(rtc);
|
return PTR_ERR(rtc);
|
||||||
platform_set_drvdata(pdev, rtc);
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
|
/* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy
|
||||||
|
* completion.
|
||||||
|
*/
|
||||||
|
at91_rtc_write_ier(AT91_RTC_SECEV);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
|
dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -346,7 +346,7 @@ static int bfin_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct bfin_rtc *rtc;
|
struct bfin_rtc *rtc;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
int ret = 0;
|
int ret;
|
||||||
unsigned long timeout = jiffies + HZ;
|
unsigned long timeout = jiffies + HZ;
|
||||||
|
|
||||||
dev_dbg_stamp(dev);
|
dev_dbg_stamp(dev);
|
||||||
|
@ -361,16 +361,17 @@ static int bfin_rtc_probe(struct platform_device *pdev)
|
||||||
/* Register our RTC with the RTC framework */
|
/* Register our RTC with the RTC framework */
|
||||||
rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops,
|
rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops,
|
||||||
THIS_MODULE);
|
THIS_MODULE);
|
||||||
if (unlikely(IS_ERR(rtc->rtc_dev))) {
|
if (unlikely(IS_ERR(rtc->rtc_dev)))
|
||||||
ret = PTR_ERR(rtc->rtc_dev);
|
return PTR_ERR(rtc->rtc_dev);
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Grab the IRQ and init the hardware */
|
/* Grab the IRQ and init the hardware */
|
||||||
ret = devm_request_irq(dev, IRQ_RTC, bfin_rtc_interrupt, 0,
|
ret = devm_request_irq(dev, IRQ_RTC, bfin_rtc_interrupt, 0,
|
||||||
pdev->name, dev);
|
pdev->name, dev);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
goto err;
|
dev_err(&pdev->dev,
|
||||||
|
"unable to request IRQ; alarm won't work, "
|
||||||
|
"and writes will be delayed\n");
|
||||||
|
|
||||||
/* sometimes the bootloader touched things, but the write complete was not
|
/* sometimes the bootloader touched things, but the write complete was not
|
||||||
* enabled, so let's just do a quick timeout here since the IRQ will not fire ...
|
* enabled, so let's just do a quick timeout here since the IRQ will not fire ...
|
||||||
*/
|
*/
|
||||||
|
@ -381,9 +382,6 @@ static int bfin_rtc_probe(struct platform_device *pdev)
|
||||||
bfin_write_RTC_SWCNT(0);
|
bfin_write_RTC_SWCNT(0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bfin_rtc_remove(struct platform_device *pdev)
|
static int bfin_rtc_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -647,6 +647,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
unsigned char rtc_control;
|
unsigned char rtc_control;
|
||||||
unsigned address_space;
|
unsigned address_space;
|
||||||
|
u32 flags = 0;
|
||||||
|
|
||||||
/* there can be only one ... */
|
/* there can be only one ... */
|
||||||
if (cmos_rtc.dev)
|
if (cmos_rtc.dev)
|
||||||
|
@ -660,9 +661,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||||
* REVISIT non-x86 systems may instead use memory space resources
|
* REVISIT non-x86 systems may instead use memory space resources
|
||||||
* (needing ioremap etc), not i/o space resources like this ...
|
* (needing ioremap etc), not i/o space resources like this ...
|
||||||
*/
|
*/
|
||||||
ports = request_region(ports->start,
|
if (RTC_IOMAPPED)
|
||||||
resource_size(ports),
|
ports = request_region(ports->start, resource_size(ports),
|
||||||
driver_name);
|
driver_name);
|
||||||
|
else
|
||||||
|
ports = request_mem_region(ports->start, resource_size(ports),
|
||||||
|
driver_name);
|
||||||
if (!ports) {
|
if (!ports) {
|
||||||
dev_dbg(dev, "i/o registers already in use\n");
|
dev_dbg(dev, "i/o registers already in use\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -699,6 +703,11 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||||
* expect CMOS_READ and friends to handle.
|
* expect CMOS_READ and friends to handle.
|
||||||
*/
|
*/
|
||||||
if (info) {
|
if (info) {
|
||||||
|
if (info->flags)
|
||||||
|
flags = info->flags;
|
||||||
|
if (info->address_space)
|
||||||
|
address_space = info->address_space;
|
||||||
|
|
||||||
if (info->rtc_day_alarm && info->rtc_day_alarm < 128)
|
if (info->rtc_day_alarm && info->rtc_day_alarm < 128)
|
||||||
cmos_rtc.day_alrm = info->rtc_day_alarm;
|
cmos_rtc.day_alrm = info->rtc_day_alarm;
|
||||||
if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128)
|
if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128)
|
||||||
|
@ -726,18 +735,21 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||||
|
|
||||||
spin_lock_irq(&rtc_lock);
|
spin_lock_irq(&rtc_lock);
|
||||||
|
|
||||||
/* force periodic irq to CMOS reset default of 1024Hz;
|
if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
|
||||||
*
|
/* force periodic irq to CMOS reset default of 1024Hz;
|
||||||
* REVISIT it's been reported that at least one x86_64 ALI mobo
|
*
|
||||||
* doesn't use 32KHz here ... for portability we might need to
|
* REVISIT it's been reported that at least one x86_64 ALI
|
||||||
* do something about other clock frequencies.
|
* mobo doesn't use 32KHz here ... for portability we might
|
||||||
*/
|
* need to do something about other clock frequencies.
|
||||||
cmos_rtc.rtc->irq_freq = 1024;
|
*/
|
||||||
hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
cmos_rtc.rtc->irq_freq = 1024;
|
||||||
CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
||||||
|
CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
/* disable irqs */
|
/* disable irqs */
|
||||||
cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
|
if (is_valid_irq(rtc_irq))
|
||||||
|
cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
|
||||||
|
|
||||||
rtc_control = CMOS_READ(RTC_CONTROL);
|
rtc_control = CMOS_READ(RTC_CONTROL);
|
||||||
|
|
||||||
|
@ -802,14 +814,18 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
||||||
cmos_rtc.dev = NULL;
|
cmos_rtc.dev = NULL;
|
||||||
rtc_device_unregister(cmos_rtc.rtc);
|
rtc_device_unregister(cmos_rtc.rtc);
|
||||||
cleanup0:
|
cleanup0:
|
||||||
release_region(ports->start, resource_size(ports));
|
if (RTC_IOMAPPED)
|
||||||
|
release_region(ports->start, resource_size(ports));
|
||||||
|
else
|
||||||
|
release_mem_region(ports->start, resource_size(ports));
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cmos_do_shutdown(void)
|
static void cmos_do_shutdown(int rtc_irq)
|
||||||
{
|
{
|
||||||
spin_lock_irq(&rtc_lock);
|
spin_lock_irq(&rtc_lock);
|
||||||
cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
|
if (is_valid_irq(rtc_irq))
|
||||||
|
cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
|
||||||
spin_unlock_irq(&rtc_lock);
|
spin_unlock_irq(&rtc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,7 +834,7 @@ static void __exit cmos_do_remove(struct device *dev)
|
||||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||||
struct resource *ports;
|
struct resource *ports;
|
||||||
|
|
||||||
cmos_do_shutdown();
|
cmos_do_shutdown(cmos->irq);
|
||||||
|
|
||||||
sysfs_remove_bin_file(&dev->kobj, &nvram);
|
sysfs_remove_bin_file(&dev->kobj, &nvram);
|
||||||
|
|
||||||
|
@ -831,7 +847,10 @@ static void __exit cmos_do_remove(struct device *dev)
|
||||||
cmos->rtc = NULL;
|
cmos->rtc = NULL;
|
||||||
|
|
||||||
ports = cmos->iomem;
|
ports = cmos->iomem;
|
||||||
release_region(ports->start, resource_size(ports));
|
if (RTC_IOMAPPED)
|
||||||
|
release_region(ports->start, resource_size(ports));
|
||||||
|
else
|
||||||
|
release_mem_region(ports->start, resource_size(ports));
|
||||||
cmos->iomem = NULL;
|
cmos->iomem = NULL;
|
||||||
|
|
||||||
cmos->dev = NULL;
|
cmos->dev = NULL;
|
||||||
|
@ -1065,10 +1084,13 @@ static void __exit cmos_pnp_remove(struct pnp_dev *pnp)
|
||||||
|
|
||||||
static void cmos_pnp_shutdown(struct pnp_dev *pnp)
|
static void cmos_pnp_shutdown(struct pnp_dev *pnp)
|
||||||
{
|
{
|
||||||
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pnp->dev))
|
struct device *dev = &pnp->dev;
|
||||||
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cmos_do_shutdown();
|
cmos_do_shutdown(cmos->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pnp_device_id rtc_ids[] = {
|
static const struct pnp_device_id rtc_ids[] = {
|
||||||
|
@ -1143,11 +1165,21 @@ static inline void cmos_of_init(struct platform_device *pdev) {}
|
||||||
|
|
||||||
static int __init cmos_platform_probe(struct platform_device *pdev)
|
static int __init cmos_platform_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct resource *resource;
|
||||||
|
int irq;
|
||||||
|
|
||||||
cmos_of_init(pdev);
|
cmos_of_init(pdev);
|
||||||
cmos_wake_setup(&pdev->dev);
|
cmos_wake_setup(&pdev->dev);
|
||||||
return cmos_do_probe(&pdev->dev,
|
|
||||||
platform_get_resource(pdev, IORESOURCE_IO, 0),
|
if (RTC_IOMAPPED)
|
||||||
platform_get_irq(pdev, 0));
|
resource = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
|
else
|
||||||
|
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
irq = platform_get_irq(pdev, 0);
|
||||||
|
if (irq < 0)
|
||||||
|
irq = -1;
|
||||||
|
|
||||||
|
return cmos_do_probe(&pdev->dev, resource, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __exit cmos_platform_remove(struct platform_device *pdev)
|
static int __exit cmos_platform_remove(struct platform_device *pdev)
|
||||||
|
@ -1158,10 +1190,13 @@ static int __exit cmos_platform_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
static void cmos_platform_shutdown(struct platform_device *pdev)
|
static void cmos_platform_shutdown(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(&pdev->dev))
|
struct device *dev = &pdev->dev;
|
||||||
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cmos_do_shutdown();
|
cmos_do_shutdown(cmos->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* work with hotplug and coldplug */
|
/* work with hotplug and coldplug */
|
||||||
|
|
|
@ -20,28 +20,28 @@
|
||||||
#include <linux/mfd/da9052/da9052.h>
|
#include <linux/mfd/da9052/da9052.h>
|
||||||
#include <linux/mfd/da9052/reg.h>
|
#include <linux/mfd/da9052/reg.h>
|
||||||
|
|
||||||
#define rtc_err(da9052, fmt, ...) \
|
#define rtc_err(rtc, fmt, ...) \
|
||||||
dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
|
dev_err(rtc->da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
|
||||||
|
|
||||||
struct da9052_rtc {
|
struct da9052_rtc {
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
struct da9052 *da9052;
|
struct da9052 *da9052;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
|
static int da9052_rtc_enable_alarm(struct da9052_rtc *rtc, bool enable)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if (enable) {
|
if (enable) {
|
||||||
ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
|
ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
|
||||||
DA9052_ALARM_Y_ALARM_ON,
|
DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON,
|
||||||
DA9052_ALARM_Y_ALARM_ON);
|
DA9052_ALARM_Y_ALARM_ON);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
rtc_err(da9052, "Failed to enable ALM: %d\n", ret);
|
rtc_err(rtc, "Failed to enable ALM: %d\n", ret);
|
||||||
} else {
|
} else {
|
||||||
ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
|
ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
|
||||||
DA9052_ALARM_Y_ALARM_ON, 0);
|
DA9052_ALARM_Y_ALARM_ON|DA9052_ALARM_Y_TICK_ON, 0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
rtc_err(da9052, "Write error: %d\n", ret);
|
rtc_err(rtc, "Write error: %d\n", ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -49,31 +49,20 @@ static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
|
||||||
static irqreturn_t da9052_rtc_irq(int irq, void *data)
|
static irqreturn_t da9052_rtc_irq(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct da9052_rtc *rtc = data;
|
struct da9052_rtc *rtc = data;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG);
|
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
|
||||||
if (ret < 0) {
|
|
||||||
rtc_err(rtc->da9052, "Read error: %d\n", ret);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret & DA9052_ALARMMI_ALARMTYPE) {
|
|
||||||
da9052_rtc_enable_alarm(rtc->da9052, 0);
|
|
||||||
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
|
|
||||||
} else
|
|
||||||
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_PF);
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
|
static int da9052_read_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t v[5];
|
uint8_t v[5];
|
||||||
|
|
||||||
ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v);
|
ret = da9052_group_read(rtc->da9052, DA9052_ALARM_MI_REG, 5, v);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
rtc_err(da9052, "Failed to group read ALM: %d\n", ret);
|
rtc_err(rtc, "Failed to group read ALM: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,23 +73,33 @@ static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
|
||||||
rtc_tm->tm_min = v[0] & DA9052_RTC_MIN;
|
rtc_tm->tm_min = v[0] & DA9052_RTC_MIN;
|
||||||
|
|
||||||
ret = rtc_valid_tm(rtc_tm);
|
ret = rtc_valid_tm(rtc_tm);
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
|
static int da9052_set_alarm(struct da9052_rtc *rtc, struct rtc_time *rtc_tm)
|
||||||
{
|
{
|
||||||
|
struct da9052 *da9052 = rtc->da9052;
|
||||||
|
unsigned long alm_time;
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t v[3];
|
uint8_t v[3];
|
||||||
|
|
||||||
|
ret = rtc_tm_to_time(rtc_tm, &alm_time);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (rtc_tm->tm_sec > 0) {
|
||||||
|
alm_time += 60 - rtc_tm->tm_sec;
|
||||||
|
rtc_time_to_tm(alm_time, rtc_tm);
|
||||||
|
}
|
||||||
|
BUG_ON(rtc_tm->tm_sec); /* it will cause repeated irqs if not zero */
|
||||||
|
|
||||||
rtc_tm->tm_year -= 100;
|
rtc_tm->tm_year -= 100;
|
||||||
rtc_tm->tm_mon += 1;
|
rtc_tm->tm_mon += 1;
|
||||||
|
|
||||||
ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
|
ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
|
||||||
DA9052_RTC_MIN, rtc_tm->tm_min);
|
DA9052_RTC_MIN, rtc_tm->tm_min);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret);
|
rtc_err(rtc, "Failed to write ALRM MIN: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,22 +114,22 @@ static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
|
||||||
ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
|
ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
|
||||||
DA9052_RTC_YEAR, rtc_tm->tm_year);
|
DA9052_RTC_YEAR, rtc_tm->tm_year);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret);
|
rtc_err(rtc, "Failed to write ALRM YEAR: %d\n", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_rtc_get_alarm_status(struct da9052 *da9052)
|
static int da9052_rtc_get_alarm_status(struct da9052_rtc *rtc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG);
|
ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_Y_REG);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
rtc_err(da9052, "Failed to read ALM: %d\n", ret);
|
rtc_err(rtc, "Failed to read ALM: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret &= DA9052_ALARM_Y_ALARM_ON;
|
|
||||||
return (ret > 0) ? 1 : 0;
|
return !!(ret&DA9052_ALARM_Y_ALARM_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
|
static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
|
||||||
|
@ -141,7 +140,7 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
|
||||||
|
|
||||||
ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
|
ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret);
|
rtc_err(rtc, "Failed to read RTC time : %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,18 +152,14 @@ static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
|
||||||
rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC;
|
rtc_tm->tm_sec = v[0] & DA9052_RTC_SEC;
|
||||||
|
|
||||||
ret = rtc_valid_tm(rtc_tm);
|
ret = rtc_valid_tm(rtc_tm);
|
||||||
if (ret != 0) {
|
return ret;
|
||||||
rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct da9052_rtc *rtc;
|
struct da9052_rtc *rtc;
|
||||||
uint8_t v[6];
|
uint8_t v[6];
|
||||||
|
int ret;
|
||||||
|
|
||||||
rtc = dev_get_drvdata(dev);
|
rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
@ -175,7 +170,10 @@ static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
v[4] = tm->tm_mon + 1;
|
v[4] = tm->tm_mon + 1;
|
||||||
v[5] = tm->tm_year - 100;
|
v[5] = tm->tm_year - 100;
|
||||||
|
|
||||||
return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
|
ret = da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
|
||||||
|
if (ret < 0)
|
||||||
|
rtc_err(rtc, "failed to set RTC time: %d\n", ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
@ -184,13 +182,13 @@ static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
struct rtc_time *tm = &alrm->time;
|
struct rtc_time *tm = &alrm->time;
|
||||||
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
ret = da9052_read_alarm(rtc->da9052, tm);
|
ret = da9052_read_alarm(rtc, tm);
|
||||||
|
if (ret < 0) {
|
||||||
if (ret)
|
rtc_err(rtc, "failed to read RTC alarm: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052);
|
alrm->enabled = da9052_rtc_get_alarm_status(rtc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,16 +198,15 @@ static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
struct rtc_time *tm = &alrm->time;
|
struct rtc_time *tm = &alrm->time;
|
||||||
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
ret = da9052_rtc_enable_alarm(rtc->da9052, 0);
|
ret = da9052_rtc_enable_alarm(rtc, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = da9052_set_alarm(rtc->da9052, tm);
|
ret = da9052_set_alarm(rtc, tm);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = da9052_rtc_enable_alarm(rtc->da9052, 1);
|
ret = da9052_rtc_enable_alarm(rtc, 1);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +214,7 @@ static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
{
|
{
|
||||||
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
struct da9052_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
return da9052_rtc_enable_alarm(rtc->da9052, enabled);
|
return da9052_rtc_enable_alarm(rtc, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct rtc_class_ops da9052_rtc_ops = {
|
static const struct rtc_class_ops da9052_rtc_ops = {
|
||||||
|
@ -239,10 +236,23 @@ static int da9052_rtc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
|
rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
|
||||||
platform_set_drvdata(pdev, rtc);
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
|
ret = da9052_reg_write(rtc->da9052, DA9052_BBAT_CONT_REG, 0xFE);
|
||||||
|
if (ret < 0) {
|
||||||
|
rtc_err(rtc,
|
||||||
|
"Failed to setup RTC battery charging: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = da9052_reg_update(rtc->da9052, DA9052_ALARM_Y_REG,
|
||||||
|
DA9052_ALARM_Y_TICK_ON, 0);
|
||||||
|
if (ret != 0)
|
||||||
|
rtc_err(rtc, "Failed to disable TICKS: %d\n", ret);
|
||||||
|
|
||||||
ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
|
ret = da9052_request_irq(rtc->da9052, DA9052_IRQ_ALARM, "ALM",
|
||||||
da9052_rtc_irq, rtc);
|
da9052_rtc_irq, rtc);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
|
rtc_err(rtc, "irq registration failed: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +271,7 @@ static struct platform_driver da9052_rtc_driver = {
|
||||||
|
|
||||||
module_platform_driver(da9052_rtc_driver);
|
module_platform_driver(da9052_rtc_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
MODULE_AUTHOR("Anthony Olech <Anthony.Olech@diasemi.com>");
|
||||||
MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
|
MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_ALIAS("platform:da9052-rtc");
|
MODULE_ALIAS("platform:da9052-rtc");
|
||||||
|
|
333
drivers/rtc/rtc-da9063.c
Normal file
333
drivers/rtc/rtc-da9063.c
Normal file
|
@ -0,0 +1,333 @@
|
||||||
|
/* rtc-da9063.c - Real time clock device driver for DA9063
|
||||||
|
* Copyright (C) 2013-14 Dialog Semiconductor Ltd.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Library General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Library General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/mfd/da9063/registers.h>
|
||||||
|
#include <linux/mfd/da9063/core.h>
|
||||||
|
|
||||||
|
#define YEARS_TO_DA9063(year) ((year) - 100)
|
||||||
|
#define MONTHS_TO_DA9063(month) ((month) + 1)
|
||||||
|
#define YEARS_FROM_DA9063(year) ((year) + 100)
|
||||||
|
#define MONTHS_FROM_DA9063(month) ((month) - 1)
|
||||||
|
|
||||||
|
#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
|
||||||
|
#define RTC_SEC 0
|
||||||
|
#define RTC_MIN 1
|
||||||
|
#define RTC_HOUR 2
|
||||||
|
#define RTC_DAY 3
|
||||||
|
#define RTC_MONTH 4
|
||||||
|
#define RTC_YEAR 5
|
||||||
|
|
||||||
|
struct da9063_rtc {
|
||||||
|
struct rtc_device *rtc_dev;
|
||||||
|
struct da9063 *hw;
|
||||||
|
struct rtc_time alarm_time;
|
||||||
|
bool rtc_sync;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
tm->tm_sec = data[RTC_SEC] & DA9063_COUNT_SEC_MASK;
|
||||||
|
tm->tm_min = data[RTC_MIN] & DA9063_COUNT_MIN_MASK;
|
||||||
|
tm->tm_hour = data[RTC_HOUR] & DA9063_COUNT_HOUR_MASK;
|
||||||
|
tm->tm_mday = data[RTC_DAY] & DA9063_COUNT_DAY_MASK;
|
||||||
|
tm->tm_mon = MONTHS_FROM_DA9063(data[RTC_MONTH] &
|
||||||
|
DA9063_COUNT_MONTH_MASK);
|
||||||
|
tm->tm_year = YEARS_FROM_DA9063(data[RTC_YEAR] &
|
||||||
|
DA9063_COUNT_YEAR_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void da9063_tm_to_data(struct rtc_time *tm, u8 *data)
|
||||||
|
{
|
||||||
|
data[RTC_SEC] &= ~DA9063_COUNT_SEC_MASK;
|
||||||
|
data[RTC_SEC] |= tm->tm_sec & DA9063_COUNT_SEC_MASK;
|
||||||
|
|
||||||
|
data[RTC_MIN] &= ~DA9063_COUNT_MIN_MASK;
|
||||||
|
data[RTC_MIN] |= tm->tm_min & DA9063_COUNT_MIN_MASK;
|
||||||
|
|
||||||
|
data[RTC_HOUR] &= ~DA9063_COUNT_HOUR_MASK;
|
||||||
|
data[RTC_HOUR] |= tm->tm_hour & DA9063_COUNT_HOUR_MASK;
|
||||||
|
|
||||||
|
data[RTC_DAY] &= ~DA9063_COUNT_DAY_MASK;
|
||||||
|
data[RTC_DAY] |= tm->tm_mday & DA9063_COUNT_DAY_MASK;
|
||||||
|
|
||||||
|
data[RTC_MONTH] &= ~DA9063_COUNT_MONTH_MASK;
|
||||||
|
data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) &
|
||||||
|
DA9063_COUNT_MONTH_MASK;
|
||||||
|
|
||||||
|
data[RTC_YEAR] &= ~DA9063_COUNT_YEAR_MASK;
|
||||||
|
data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) &
|
||||||
|
DA9063_COUNT_YEAR_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_stop_alarm(struct device *dev)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
|
||||||
|
DA9063_ALARM_ON, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_start_alarm(struct device *dev)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
|
||||||
|
DA9063_ALARM_ON, DA9063_ALARM_ON);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
unsigned long tm_secs;
|
||||||
|
unsigned long al_secs;
|
||||||
|
u8 data[RTC_DATA_LEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_COUNT_S,
|
||||||
|
data, RTC_DATA_LEN);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "Failed to read RTC time data: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(data[RTC_SEC] & DA9063_RTC_READ)) {
|
||||||
|
dev_dbg(dev, "RTC not yet ready to be read by the host\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
da9063_data_to_tm(data, tm);
|
||||||
|
|
||||||
|
rtc_tm_to_time(tm, &tm_secs);
|
||||||
|
rtc_tm_to_time(&rtc->alarm_time, &al_secs);
|
||||||
|
|
||||||
|
/* handle the rtc synchronisation delay */
|
||||||
|
if (rtc->rtc_sync == true && al_secs - tm_secs == 1)
|
||||||
|
memcpy(tm, &rtc->alarm_time, sizeof(struct rtc_time));
|
||||||
|
else
|
||||||
|
rtc->rtc_sync = false;
|
||||||
|
|
||||||
|
return rtc_valid_tm(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
u8 data[RTC_DATA_LEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
da9063_tm_to_data(tm, data);
|
||||||
|
ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_COUNT_S,
|
||||||
|
data, RTC_DATA_LEN);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(dev, "Failed to set RTC time data: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
u8 data[RTC_DATA_LEN];
|
||||||
|
int ret;
|
||||||
|
unsigned int val;
|
||||||
|
|
||||||
|
ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_ALARM_S,
|
||||||
|
&data[RTC_SEC], RTC_DATA_LEN);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
da9063_data_to_tm(data, &alrm->time);
|
||||||
|
|
||||||
|
alrm->enabled = !!(data[RTC_YEAR] & DA9063_ALARM_ON);
|
||||||
|
|
||||||
|
ret = regmap_read(rtc->hw->regmap, DA9063_REG_EVENT_A, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (val & (DA9063_E_ALARM))
|
||||||
|
alrm->pending = 1;
|
||||||
|
else
|
||||||
|
alrm->pending = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
u8 data[RTC_DATA_LEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
da9063_tm_to_data(&alrm->time, data);
|
||||||
|
|
||||||
|
ret = da9063_rtc_stop_alarm(dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "Failed to stop alarm: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_ALARM_S,
|
||||||
|
data, RTC_DATA_LEN);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "Failed to write alarm: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc->alarm_time = alrm->time;
|
||||||
|
|
||||||
|
if (alrm->enabled) {
|
||||||
|
ret = da9063_rtc_start_alarm(dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(dev, "Failed to start alarm: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
return da9063_rtc_start_alarm(dev);
|
||||||
|
else
|
||||||
|
return da9063_rtc_stop_alarm(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t da9063_alarm_event(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct da9063_rtc *rtc = data;
|
||||||
|
|
||||||
|
regmap_update_bits(rtc->hw->regmap, DA9063_REG_ALARM_Y,
|
||||||
|
DA9063_ALARM_ON, 0);
|
||||||
|
|
||||||
|
rtc->rtc_sync = true;
|
||||||
|
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops da9063_rtc_ops = {
|
||||||
|
.read_time = da9063_rtc_read_time,
|
||||||
|
.set_time = da9063_rtc_set_time,
|
||||||
|
.read_alarm = da9063_rtc_read_alarm,
|
||||||
|
.set_alarm = da9063_rtc_set_alarm,
|
||||||
|
.alarm_irq_enable = da9063_rtc_alarm_irq_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int da9063_rtc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
|
||||||
|
struct da9063_rtc *rtc;
|
||||||
|
int irq_alarm;
|
||||||
|
u8 data[RTC_DATA_LEN];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_E,
|
||||||
|
DA9063_RTC_EN, DA9063_RTC_EN);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to enable RTC\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_update_bits(da9063->regmap, DA9063_REG_EN_32K,
|
||||||
|
DA9063_CRYSTAL, DA9063_CRYSTAL);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
|
||||||
|
DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
|
||||||
|
0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_S,
|
||||||
|
DA9063_ALARM_STATUS_ALARM,
|
||||||
|
DA9063_ALARM_STATUS_ALARM);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_update_bits(da9063->regmap, DA9063_REG_ALARM_Y,
|
||||||
|
DA9063_TICK_ON, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to disable TICKs\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = regmap_bulk_read(da9063->regmap, DA9063_REG_ALARM_S,
|
||||||
|
data, RTC_DATA_LEN);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
|
||||||
|
ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
|
||||||
|
if (!rtc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
|
irq_alarm = platform_get_irq_byname(pdev, "ALARM");
|
||||||
|
ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
|
||||||
|
da9063_alarm_event,
|
||||||
|
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||||
|
"ALARM", rtc);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
|
||||||
|
irq_alarm, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc->hw = da9063;
|
||||||
|
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
|
||||||
|
&da9063_rtc_ops, THIS_MODULE);
|
||||||
|
if (IS_ERR(rtc->rtc_dev))
|
||||||
|
return PTR_ERR(rtc->rtc_dev);
|
||||||
|
|
||||||
|
da9063_data_to_tm(data, &rtc->alarm_time);
|
||||||
|
rtc->rtc_sync = false;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver da9063_rtc_driver = {
|
||||||
|
.probe = da9063_rtc_probe,
|
||||||
|
.driver = {
|
||||||
|
.name = DA9063_DRVNAME_RTC,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(da9063_rtc_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
|
||||||
|
MODULE_DESCRIPTION("Real time clock device driver for Dialog DA9063");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_ALIAS("platform:" DA9063_DRVNAME_RTC);
|
689
drivers/rtc/rtc-ds1343.c
Normal file
689
drivers/rtc/rtc-ds1343.c
Normal file
|
@ -0,0 +1,689 @@
|
||||||
|
/* rtc-ds1343.c
|
||||||
|
*
|
||||||
|
* Driver for Dallas Semiconductor DS1343 Low Current, SPI Compatible
|
||||||
|
* Real Time Clock
|
||||||
|
*
|
||||||
|
* Author : Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
#include <linux/bcd.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#define DS1343_DRV_VERSION "01.00"
|
||||||
|
#define DALLAS_MAXIM_DS1343 0
|
||||||
|
#define DALLAS_MAXIM_DS1344 1
|
||||||
|
|
||||||
|
/* RTC DS1343 Registers */
|
||||||
|
#define DS1343_SECONDS_REG 0x00
|
||||||
|
#define DS1343_MINUTES_REG 0x01
|
||||||
|
#define DS1343_HOURS_REG 0x02
|
||||||
|
#define DS1343_DAY_REG 0x03
|
||||||
|
#define DS1343_DATE_REG 0x04
|
||||||
|
#define DS1343_MONTH_REG 0x05
|
||||||
|
#define DS1343_YEAR_REG 0x06
|
||||||
|
#define DS1343_ALM0_SEC_REG 0x07
|
||||||
|
#define DS1343_ALM0_MIN_REG 0x08
|
||||||
|
#define DS1343_ALM0_HOUR_REG 0x09
|
||||||
|
#define DS1343_ALM0_DAY_REG 0x0A
|
||||||
|
#define DS1343_ALM1_SEC_REG 0x0B
|
||||||
|
#define DS1343_ALM1_MIN_REG 0x0C
|
||||||
|
#define DS1343_ALM1_HOUR_REG 0x0D
|
||||||
|
#define DS1343_ALM1_DAY_REG 0x0E
|
||||||
|
#define DS1343_CONTROL_REG 0x0F
|
||||||
|
#define DS1343_STATUS_REG 0x10
|
||||||
|
#define DS1343_TRICKLE_REG 0x11
|
||||||
|
|
||||||
|
/* DS1343 Control Registers bits */
|
||||||
|
#define DS1343_EOSC 0x80
|
||||||
|
#define DS1343_DOSF 0x20
|
||||||
|
#define DS1343_EGFIL 0x10
|
||||||
|
#define DS1343_SQW 0x08
|
||||||
|
#define DS1343_INTCN 0x04
|
||||||
|
#define DS1343_A1IE 0x02
|
||||||
|
#define DS1343_A0IE 0x01
|
||||||
|
|
||||||
|
/* DS1343 Status Registers bits */
|
||||||
|
#define DS1343_OSF 0x80
|
||||||
|
#define DS1343_IRQF1 0x02
|
||||||
|
#define DS1343_IRQF0 0x01
|
||||||
|
|
||||||
|
/* DS1343 Trickle Charger Registers bits */
|
||||||
|
#define DS1343_TRICKLE_MAGIC 0xa0
|
||||||
|
#define DS1343_TRICKLE_DS1 0x08
|
||||||
|
#define DS1343_TRICKLE_1K 0x01
|
||||||
|
#define DS1343_TRICKLE_2K 0x02
|
||||||
|
#define DS1343_TRICKLE_4K 0x03
|
||||||
|
|
||||||
|
static const struct spi_device_id ds1343_id[] = {
|
||||||
|
{ "ds1343", DALLAS_MAXIM_DS1343 },
|
||||||
|
{ "ds1344", DALLAS_MAXIM_DS1344 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(spi, ds1343_id);
|
||||||
|
|
||||||
|
struct ds1343_priv {
|
||||||
|
struct spi_device *spi;
|
||||||
|
struct rtc_device *rtc;
|
||||||
|
struct regmap *map;
|
||||||
|
struct mutex mutex;
|
||||||
|
unsigned int irqen;
|
||||||
|
int irq;
|
||||||
|
int alarm_sec;
|
||||||
|
int alarm_min;
|
||||||
|
int alarm_hour;
|
||||||
|
int alarm_mday;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ds1343_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
#ifdef RTC_SET_CHARGE
|
||||||
|
case RTC_SET_CHARGE:
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
if (copy_from_user(&val, (int __user *)arg, sizeof(int)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return regmap_write(priv->map, DS1343_TRICKLE_REG, val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ds1343_show_glitchfilter(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int glitch_filt_status, data;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_CONTROL_REG, &data);
|
||||||
|
|
||||||
|
glitch_filt_status = !!(data & DS1343_EGFIL);
|
||||||
|
|
||||||
|
if (glitch_filt_status)
|
||||||
|
return sprintf(buf, "enabled\n");
|
||||||
|
else
|
||||||
|
return sprintf(buf, "disabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t ds1343_store_glitchfilter(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int data;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_CONTROL_REG, &data);
|
||||||
|
|
||||||
|
if (strncmp(buf, "enabled", 7) == 0)
|
||||||
|
data |= DS1343_EGFIL;
|
||||||
|
|
||||||
|
else if (strncmp(buf, "disabled", 8) == 0)
|
||||||
|
data &= ~(DS1343_EGFIL);
|
||||||
|
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
regmap_write(priv->map, DS1343_CONTROL_REG, data);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(glitch_filter, S_IRUGO | S_IWUSR, ds1343_show_glitchfilter,
|
||||||
|
ds1343_store_glitchfilter);
|
||||||
|
|
||||||
|
static ssize_t ds1343_show_alarmstatus(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int alarmstatus, data;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_CONTROL_REG, &data);
|
||||||
|
|
||||||
|
alarmstatus = !!(data & DS1343_A0IE);
|
||||||
|
|
||||||
|
if (alarmstatus)
|
||||||
|
return sprintf(buf, "enabled\n");
|
||||||
|
else
|
||||||
|
return sprintf(buf, "disabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(alarm_status, S_IRUGO, ds1343_show_alarmstatus, NULL);
|
||||||
|
|
||||||
|
static ssize_t ds1343_show_alarmmode(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int alarm_mode, data;
|
||||||
|
char *alarm_str;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_ALM0_SEC_REG, &data);
|
||||||
|
alarm_mode = (data & 0x80) >> 4;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_ALM0_MIN_REG, &data);
|
||||||
|
alarm_mode |= (data & 0x80) >> 5;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_ALM0_HOUR_REG, &data);
|
||||||
|
alarm_mode |= (data & 0x80) >> 6;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_ALM0_DAY_REG, &data);
|
||||||
|
alarm_mode |= (data & 0x80) >> 7;
|
||||||
|
|
||||||
|
switch (alarm_mode) {
|
||||||
|
case 15:
|
||||||
|
alarm_str = "each second";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
alarm_str = "seconds match";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
alarm_str = "minutes and seconds match";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
alarm_str = "hours, minutes and seconds match";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
alarm_str = "day, hours, minutes and seconds match";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
alarm_str = "invalid";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%s\n", alarm_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(alarm_mode, S_IRUGO, ds1343_show_alarmmode, NULL);
|
||||||
|
|
||||||
|
static ssize_t ds1343_show_tricklecharger(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int data;
|
||||||
|
char *diodes = "disabled", *resistors = " ";
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_TRICKLE_REG, &data);
|
||||||
|
|
||||||
|
if ((data & 0xf0) == DS1343_TRICKLE_MAGIC) {
|
||||||
|
switch (data & 0x0c) {
|
||||||
|
case DS1343_TRICKLE_DS1:
|
||||||
|
diodes = "one diode,";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
diodes = "no diode,";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (data & 0x03) {
|
||||||
|
case DS1343_TRICKLE_1K:
|
||||||
|
resistors = "1k Ohm";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DS1343_TRICKLE_2K:
|
||||||
|
resistors = "2k Ohm";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DS1343_TRICKLE_4K:
|
||||||
|
resistors = "4k Ohm";
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
diodes = "disabled";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%s %s\n", diodes, resistors);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(trickle_charger, S_IRUGO, ds1343_show_tricklecharger, NULL);
|
||||||
|
|
||||||
|
static int ds1343_sysfs_register(struct device *dev)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = device_create_file(dev, &dev_attr_glitch_filter);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = device_create_file(dev, &dev_attr_trickle_charger);
|
||||||
|
if (err)
|
||||||
|
goto error1;
|
||||||
|
|
||||||
|
if (priv->irq <= 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = device_create_file(dev, &dev_attr_alarm_mode);
|
||||||
|
if (err)
|
||||||
|
goto error2;
|
||||||
|
|
||||||
|
err = device_create_file(dev, &dev_attr_alarm_status);
|
||||||
|
if (!err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
device_remove_file(dev, &dev_attr_alarm_mode);
|
||||||
|
|
||||||
|
error2:
|
||||||
|
device_remove_file(dev, &dev_attr_trickle_charger);
|
||||||
|
|
||||||
|
error1:
|
||||||
|
device_remove_file(dev, &dev_attr_glitch_filter);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds1343_sysfs_unregister(struct device *dev)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
device_remove_file(dev, &dev_attr_glitch_filter);
|
||||||
|
device_remove_file(dev, &dev_attr_trickle_charger);
|
||||||
|
|
||||||
|
if (priv->irq <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
device_remove_file(dev, &dev_attr_alarm_status);
|
||||||
|
device_remove_file(dev, &dev_attr_alarm_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_read_time(struct device *dev, struct rtc_time *dt)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
unsigned char buf[7];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = regmap_bulk_read(priv->map, DS1343_SECONDS_REG, buf, 7);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
dt->tm_sec = bcd2bin(buf[0]);
|
||||||
|
dt->tm_min = bcd2bin(buf[1]);
|
||||||
|
dt->tm_hour = bcd2bin(buf[2] & 0x3F);
|
||||||
|
dt->tm_wday = bcd2bin(buf[3]) - 1;
|
||||||
|
dt->tm_mday = bcd2bin(buf[4]);
|
||||||
|
dt->tm_mon = bcd2bin(buf[5] & 0x1F) - 1;
|
||||||
|
dt->tm_year = bcd2bin(buf[6]) + 100; /* year offset from 1900 */
|
||||||
|
|
||||||
|
return rtc_valid_tm(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_set_time(struct device *dev, struct rtc_time *dt)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_SECONDS_REG,
|
||||||
|
bin2bcd(dt->tm_sec));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_MINUTES_REG,
|
||||||
|
bin2bcd(dt->tm_min));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_HOURS_REG,
|
||||||
|
bin2bcd(dt->tm_hour) & 0x3F);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_DAY_REG,
|
||||||
|
bin2bcd(dt->tm_wday + 1));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_DATE_REG,
|
||||||
|
bin2bcd(dt->tm_mday));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_MONTH_REG,
|
||||||
|
bin2bcd(dt->tm_mon + 1));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
dt->tm_year %= 100;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_YEAR_REG,
|
||||||
|
bin2bcd(dt->tm_year));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_update_alarm(struct device *dev)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
unsigned int control, stat;
|
||||||
|
unsigned char buf[4];
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_CONTROL_REG, &control);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_STATUS_REG, &stat);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
control &= ~(DS1343_A0IE);
|
||||||
|
stat &= ~(DS1343_IRQF0);
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_CONTROL_REG, control);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
res = regmap_write(priv->map, DS1343_STATUS_REG, stat);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
buf[0] = priv->alarm_sec < 0 || (priv->irqen & RTC_UF) ?
|
||||||
|
0x80 : bin2bcd(priv->alarm_sec) & 0x7F;
|
||||||
|
buf[1] = priv->alarm_min < 0 || (priv->irqen & RTC_UF) ?
|
||||||
|
0x80 : bin2bcd(priv->alarm_min) & 0x7F;
|
||||||
|
buf[2] = priv->alarm_hour < 0 || (priv->irqen & RTC_UF) ?
|
||||||
|
0x80 : bin2bcd(priv->alarm_hour) & 0x3F;
|
||||||
|
buf[3] = priv->alarm_mday < 0 || (priv->irqen & RTC_UF) ?
|
||||||
|
0x80 : bin2bcd(priv->alarm_mday) & 0x7F;
|
||||||
|
|
||||||
|
res = regmap_bulk_write(priv->map, DS1343_ALM0_SEC_REG, buf, 4);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (priv->irqen) {
|
||||||
|
control |= DS1343_A0IE;
|
||||||
|
res = regmap_write(priv->map, DS1343_CONTROL_REG, control);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int res = 0;
|
||||||
|
unsigned int stat;
|
||||||
|
|
||||||
|
if (priv->irq <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_STATUS_REG, &stat);
|
||||||
|
if (res)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
alarm->enabled = !!(priv->irqen & RTC_AF);
|
||||||
|
alarm->pending = !!(stat & DS1343_IRQF0);
|
||||||
|
|
||||||
|
alarm->time.tm_sec = priv->alarm_sec < 0 ? 0 : priv->alarm_sec;
|
||||||
|
alarm->time.tm_min = priv->alarm_min < 0 ? 0 : priv->alarm_min;
|
||||||
|
alarm->time.tm_hour = priv->alarm_hour < 0 ? 0 : priv->alarm_hour;
|
||||||
|
alarm->time.tm_mday = priv->alarm_mday < 0 ? 0 : priv->alarm_mday;
|
||||||
|
|
||||||
|
alarm->time.tm_mon = -1;
|
||||||
|
alarm->time.tm_year = -1;
|
||||||
|
alarm->time.tm_wday = -1;
|
||||||
|
alarm->time.tm_yday = -1;
|
||||||
|
alarm->time.tm_isdst = -1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (priv->irq <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
|
priv->alarm_sec = alarm->time.tm_sec;
|
||||||
|
priv->alarm_min = alarm->time.tm_min;
|
||||||
|
priv->alarm_hour = alarm->time.tm_hour;
|
||||||
|
priv->alarm_mday = alarm->time.tm_mday;
|
||||||
|
|
||||||
|
if (alarm->enabled)
|
||||||
|
priv->irqen |= RTC_AF;
|
||||||
|
|
||||||
|
res = ds1343_update_alarm(dev);
|
||||||
|
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_get_drvdata(dev);
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (priv->irq <= 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
priv->irqen |= RTC_AF;
|
||||||
|
else
|
||||||
|
priv->irqen &= ~RTC_AF;
|
||||||
|
|
||||||
|
res = ds1343_update_alarm(dev);
|
||||||
|
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t ds1343_thread(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = dev_id;
|
||||||
|
unsigned int stat, control;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_STATUS_REG, &stat);
|
||||||
|
if (res)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (stat & DS1343_IRQF0) {
|
||||||
|
stat &= ~DS1343_IRQF0;
|
||||||
|
regmap_write(priv->map, DS1343_STATUS_REG, stat);
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_CONTROL_REG, &control);
|
||||||
|
if (res)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
control &= ~DS1343_A0IE;
|
||||||
|
regmap_write(priv->map, DS1343_CONTROL_REG, control);
|
||||||
|
|
||||||
|
rtc_update_irq(priv->rtc, 1, RTC_AF | RTC_IRQF);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops ds1343_rtc_ops = {
|
||||||
|
.ioctl = ds1343_ioctl,
|
||||||
|
.read_time = ds1343_read_time,
|
||||||
|
.set_time = ds1343_set_time,
|
||||||
|
.read_alarm = ds1343_read_alarm,
|
||||||
|
.set_alarm = ds1343_set_alarm,
|
||||||
|
.alarm_irq_enable = ds1343_alarm_irq_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ds1343_probe(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv;
|
||||||
|
struct regmap_config config;
|
||||||
|
unsigned int data;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
memset(&config, 0, sizeof(config));
|
||||||
|
config.reg_bits = 8;
|
||||||
|
config.val_bits = 8;
|
||||||
|
config.write_flag_mask = 0x80;
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&spi->dev, sizeof(struct ds1343_priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
priv->spi = spi;
|
||||||
|
mutex_init(&priv->mutex);
|
||||||
|
|
||||||
|
/* RTC DS1347 works in spi mode 3 and
|
||||||
|
* its chip select is active high
|
||||||
|
*/
|
||||||
|
spi->mode = SPI_MODE_3 | SPI_CS_HIGH;
|
||||||
|
spi->bits_per_word = 8;
|
||||||
|
res = spi_setup(spi);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
spi_set_drvdata(spi, priv);
|
||||||
|
|
||||||
|
priv->map = devm_regmap_init_spi(spi, &config);
|
||||||
|
|
||||||
|
if (IS_ERR(priv->map)) {
|
||||||
|
dev_err(&spi->dev, "spi regmap init failed for rtc ds1343\n");
|
||||||
|
return PTR_ERR(priv->map);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = regmap_read(priv->map, DS1343_SECONDS_REG, &data);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_CONTROL_REG, &data);
|
||||||
|
data |= DS1343_INTCN;
|
||||||
|
data &= ~(DS1343_EOSC | DS1343_A1IE | DS1343_A0IE);
|
||||||
|
regmap_write(priv->map, DS1343_CONTROL_REG, data);
|
||||||
|
|
||||||
|
regmap_read(priv->map, DS1343_STATUS_REG, &data);
|
||||||
|
data &= ~(DS1343_OSF | DS1343_IRQF1 | DS1343_IRQF0);
|
||||||
|
regmap_write(priv->map, DS1343_STATUS_REG, data);
|
||||||
|
|
||||||
|
priv->rtc = devm_rtc_device_register(&spi->dev, "ds1343",
|
||||||
|
&ds1343_rtc_ops, THIS_MODULE);
|
||||||
|
if (IS_ERR(priv->rtc)) {
|
||||||
|
dev_err(&spi->dev, "unable to register rtc ds1343\n");
|
||||||
|
return PTR_ERR(priv->rtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->irq = spi->irq;
|
||||||
|
|
||||||
|
if (priv->irq >= 0) {
|
||||||
|
res = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
|
||||||
|
ds1343_thread,
|
||||||
|
IRQF_NO_SUSPEND | IRQF_ONESHOT,
|
||||||
|
"ds1343", priv);
|
||||||
|
if (res) {
|
||||||
|
priv->irq = -1;
|
||||||
|
dev_err(&spi->dev,
|
||||||
|
"unable to request irq for rtc ds1343\n");
|
||||||
|
} else {
|
||||||
|
device_set_wakeup_capable(&spi->dev, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res = ds1343_sysfs_register(&spi->dev);
|
||||||
|
if (res)
|
||||||
|
dev_err(&spi->dev,
|
||||||
|
"unable to create sysfs entries for rtc ds1343\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_remove(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct ds1343_priv *priv = spi_get_drvdata(spi);
|
||||||
|
|
||||||
|
if (spi->irq) {
|
||||||
|
mutex_lock(&priv->mutex);
|
||||||
|
priv->irqen &= ~RTC_AF;
|
||||||
|
mutex_unlock(&priv->mutex);
|
||||||
|
|
||||||
|
devm_free_irq(&spi->dev, spi->irq, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_set_drvdata(spi, NULL);
|
||||||
|
|
||||||
|
ds1343_sysfs_unregister(&spi->dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
|
||||||
|
static int ds1343_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct spi_device *spi = to_spi_device(dev);
|
||||||
|
|
||||||
|
if (spi->irq >= 0 && device_may_wakeup(dev))
|
||||||
|
enable_irq_wake(spi->irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ds1343_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct spi_device *spi = to_spi_device(dev);
|
||||||
|
|
||||||
|
if (spi->irq >= 0 && device_may_wakeup(dev))
|
||||||
|
disable_irq_wake(spi->irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(ds1343_pm, ds1343_suspend, ds1343_resume);
|
||||||
|
|
||||||
|
static struct spi_driver ds1343_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "ds1343",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &ds1343_pm,
|
||||||
|
},
|
||||||
|
.probe = ds1343_probe,
|
||||||
|
.remove = ds1343_remove,
|
||||||
|
.id_table = ds1343_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_spi_driver(ds1343_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("DS1343 RTC SPI Driver");
|
||||||
|
MODULE_AUTHOR("Raghavendra Chandra Ganiga <ravi23ganiga@gmail.com>");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
||||||
|
MODULE_VERSION(DS1343_DRV_VERSION);
|
|
@ -219,7 +219,7 @@ static int ds1742_rtc_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct of_device_id __maybe_unused ds1742_rtc_of_match[] = {
|
static const struct of_device_id __maybe_unused ds1742_rtc_of_match[] = {
|
||||||
{ .compatible = "maxim,ds1742", },
|
{ .compatible = "maxim,ds1742", },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@ static inline int
|
||||||
compute_yday(efi_time_t *eft)
|
compute_yday(efi_time_t *eft)
|
||||||
{
|
{
|
||||||
/* efi_time_t.month is in the [1-12] so, we need -1 */
|
/* efi_time_t.month is in the [1-12] so, we need -1 */
|
||||||
return rtc_year_days(eft->day - 1, eft->month - 1, eft->year);
|
return rtc_year_days(eft->day, eft->month - 1, eft->year);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* returns day of the week [0-6] 0=Sunday
|
* returns day of the week [0-6] 0=Sunday
|
||||||
|
|
|
@ -418,6 +418,9 @@ static struct clk *hym8563_clkout_register_clk(struct hym8563 *hym8563)
|
||||||
init.num_parents = 0;
|
init.num_parents = 0;
|
||||||
hym8563->clkout_hw.init = &init;
|
hym8563->clkout_hw.init = &init;
|
||||||
|
|
||||||
|
/* optional override of the clockname */
|
||||||
|
of_property_read_string(node, "clock-output-names", &init.name);
|
||||||
|
|
||||||
/* register the clock */
|
/* register the clock */
|
||||||
clk = clk_register(&client->dev, &hym8563->clkout_hw);
|
clk = clk_register(&client->dev, &hym8563->clkout_hw);
|
||||||
|
|
||||||
|
@ -585,7 +588,7 @@ static const struct i2c_device_id hym8563_id[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, hym8563_id);
|
MODULE_DEVICE_TABLE(i2c, hym8563_id);
|
||||||
|
|
||||||
static struct of_device_id hym8563_dt_idtable[] = {
|
static const struct of_device_id hym8563_dt_idtable[] = {
|
||||||
{ .compatible = "haoyu,hym8563" },
|
{ .compatible = "haoyu,hym8563" },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
|
@ -278,7 +278,7 @@ static int isl12057_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static struct of_device_id isl12057_dt_match[] = {
|
static const struct of_device_id isl12057_dt_match[] = {
|
||||||
{ .compatible = "isl,isl12057" },
|
{ .compatible = "isl,isl12057" },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,8 +66,6 @@
|
||||||
#define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
|
#define M41T80_FEATURE_WD (1 << 3) /* Extra watchdog resolution */
|
||||||
#define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */
|
#define M41T80_FEATURE_SQ_ALT (1 << 4) /* RSx bits are in reg 4 */
|
||||||
|
|
||||||
#define DRV_VERSION "0.05"
|
|
||||||
|
|
||||||
static DEFINE_MUTEX(m41t80_rtc_mutex);
|
static DEFINE_MUTEX(m41t80_rtc_mutex);
|
||||||
static const struct i2c_device_id m41t80_id[] = {
|
static const struct i2c_device_id m41t80_id[] = {
|
||||||
{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
|
{ "m41t62", M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT },
|
||||||
|
@ -80,6 +78,7 @@ static const struct i2c_device_id m41t80_id[] = {
|
||||||
{ "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
{ "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
||||||
{ "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
{ "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
||||||
{ "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
{ "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ },
|
||||||
|
{ "rv4162", M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, m41t80_id);
|
MODULE_DEVICE_TABLE(i2c, m41t80_id);
|
||||||
|
@ -232,7 +231,7 @@ static ssize_t m41t80_sysfs_show_flags(struct device *dev,
|
||||||
|
|
||||||
val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
|
val = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return -EIO;
|
return val;
|
||||||
return sprintf(buf, "%#x\n", val);
|
return sprintf(buf, "%#x\n", val);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
|
static DEVICE_ATTR(flags, S_IRUGO, m41t80_sysfs_show_flags, NULL);
|
||||||
|
@ -252,7 +251,7 @@ static ssize_t m41t80_sysfs_show_sqwfreq(struct device *dev,
|
||||||
reg_sqw = M41T80_REG_WDAY;
|
reg_sqw = M41T80_REG_WDAY;
|
||||||
val = i2c_smbus_read_byte_data(client, reg_sqw);
|
val = i2c_smbus_read_byte_data(client, reg_sqw);
|
||||||
if (val < 0)
|
if (val < 0)
|
||||||
return -EIO;
|
return val;
|
||||||
val = (val >> 4) & 0xf;
|
val = (val >> 4) & 0xf;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -271,7 +270,7 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
|
||||||
{
|
{
|
||||||
struct i2c_client *client = to_i2c_client(dev);
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
struct m41t80_data *clientdata = i2c_get_clientdata(client);
|
struct m41t80_data *clientdata = i2c_get_clientdata(client);
|
||||||
int almon, sqw, reg_sqw;
|
int almon, sqw, reg_sqw, rc;
|
||||||
int val = simple_strtoul(buf, NULL, 0);
|
int val = simple_strtoul(buf, NULL, 0);
|
||||||
|
|
||||||
if (!(clientdata->features & M41T80_FEATURE_SQ))
|
if (!(clientdata->features & M41T80_FEATURE_SQ))
|
||||||
|
@ -291,21 +290,30 @@ static ssize_t m41t80_sysfs_set_sqwfreq(struct device *dev,
|
||||||
/* disable SQW, set SQW frequency & re-enable */
|
/* disable SQW, set SQW frequency & re-enable */
|
||||||
almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
|
almon = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
|
||||||
if (almon < 0)
|
if (almon < 0)
|
||||||
return -EIO;
|
return almon;
|
||||||
reg_sqw = M41T80_REG_SQW;
|
reg_sqw = M41T80_REG_SQW;
|
||||||
if (clientdata->features & M41T80_FEATURE_SQ_ALT)
|
if (clientdata->features & M41T80_FEATURE_SQ_ALT)
|
||||||
reg_sqw = M41T80_REG_WDAY;
|
reg_sqw = M41T80_REG_WDAY;
|
||||||
sqw = i2c_smbus_read_byte_data(client, reg_sqw);
|
sqw = i2c_smbus_read_byte_data(client, reg_sqw);
|
||||||
if (sqw < 0)
|
if (sqw < 0)
|
||||||
return -EIO;
|
return sqw;
|
||||||
sqw = (sqw & 0x0f) | (val << 4);
|
sqw = (sqw & 0x0f) | (val << 4);
|
||||||
if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
|
|
||||||
almon & ~M41T80_ALMON_SQWE) < 0 ||
|
rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
|
||||||
i2c_smbus_write_byte_data(client, reg_sqw, sqw) < 0)
|
almon & ~M41T80_ALMON_SQWE);
|
||||||
return -EIO;
|
if (rc < 0)
|
||||||
if (val && i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
|
return rc;
|
||||||
almon | M41T80_ALMON_SQWE) < 0)
|
|
||||||
return -EIO;
|
if (val) {
|
||||||
|
rc = i2c_smbus_write_byte_data(client, reg_sqw, sqw);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON,
|
||||||
|
almon | M41T80_ALMON_SQWE);
|
||||||
|
if (rc <0)
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(sqwfreq, S_IRUGO | S_IWUSR,
|
||||||
|
@ -629,40 +637,28 @@ static int m41t80_probe(struct i2c_client *client,
|
||||||
struct m41t80_data *clientdata = NULL;
|
struct m41t80_data *clientdata = NULL;
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
|
||||||
| I2C_FUNC_SMBUS_BYTE_DATA)) {
|
| I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
rc = -ENODEV;
|
return -ENODEV;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_info(&client->dev,
|
|
||||||
"chip found, driver version " DRV_VERSION "\n");
|
|
||||||
|
|
||||||
clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
|
clientdata = devm_kzalloc(&client->dev, sizeof(*clientdata),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!clientdata) {
|
if (!clientdata)
|
||||||
rc = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
clientdata->features = id->driver_data;
|
clientdata->features = id->driver_data;
|
||||||
i2c_set_clientdata(client, clientdata);
|
i2c_set_clientdata(client, clientdata);
|
||||||
|
|
||||||
rtc = devm_rtc_device_register(&client->dev, client->name,
|
rtc = devm_rtc_device_register(&client->dev, client->name,
|
||||||
&m41t80_rtc_ops, THIS_MODULE);
|
&m41t80_rtc_ops, THIS_MODULE);
|
||||||
if (IS_ERR(rtc)) {
|
if (IS_ERR(rtc))
|
||||||
rc = PTR_ERR(rtc);
|
return PTR_ERR(rtc);
|
||||||
rtc = NULL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
clientdata->rtc = rtc;
|
clientdata->rtc = rtc;
|
||||||
|
|
||||||
/* Make sure HT (Halt Update) bit is cleared */
|
/* Make sure HT (Halt Update) bit is cleared */
|
||||||
rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
|
rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
|
||||||
if (rc < 0)
|
|
||||||
goto ht_err;
|
|
||||||
|
|
||||||
if (rc & M41T80_ALHOUR_HT) {
|
if (rc >= 0 && rc & M41T80_ALHOUR_HT) {
|
||||||
if (clientdata->features & M41T80_FEATURE_HT) {
|
if (clientdata->features & M41T80_FEATURE_HT) {
|
||||||
m41t80_get_datetime(client, &tm);
|
m41t80_get_datetime(client, &tm);
|
||||||
dev_info(&client->dev, "HT bit was set!\n");
|
dev_info(&client->dev, "HT bit was set!\n");
|
||||||
|
@ -673,53 +669,44 @@ static int m41t80_probe(struct i2c_client *client,
|
||||||
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
|
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour,
|
||||||
tm.tm_min, tm.tm_sec);
|
tm.tm_min, tm.tm_sec);
|
||||||
}
|
}
|
||||||
if (i2c_smbus_write_byte_data(client,
|
rc = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_HOUR,
|
||||||
M41T80_REG_ALARM_HOUR,
|
rc & ~M41T80_ALHOUR_HT);
|
||||||
rc & ~M41T80_ALHOUR_HT) < 0)
|
}
|
||||||
goto ht_err;
|
|
||||||
|
if (rc < 0) {
|
||||||
|
dev_err(&client->dev, "Can't clear HT bit\n");
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure ST (stop) bit is cleared */
|
/* Make sure ST (stop) bit is cleared */
|
||||||
rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
|
rc = i2c_smbus_read_byte_data(client, M41T80_REG_SEC);
|
||||||
if (rc < 0)
|
|
||||||
goto st_err;
|
|
||||||
|
|
||||||
if (rc & M41T80_SEC_ST) {
|
if (rc >= 0 && rc & M41T80_SEC_ST)
|
||||||
if (i2c_smbus_write_byte_data(client, M41T80_REG_SEC,
|
rc = i2c_smbus_write_byte_data(client, M41T80_REG_SEC,
|
||||||
rc & ~M41T80_SEC_ST) < 0)
|
rc & ~M41T80_SEC_ST);
|
||||||
goto st_err;
|
if (rc < 0) {
|
||||||
|
dev_err(&client->dev, "Can't clear ST bit\n");
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = m41t80_sysfs_register(&client->dev);
|
rc = m41t80_sysfs_register(&client->dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto exit;
|
return rc;
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_DRV_M41T80_WDT
|
#ifdef CONFIG_RTC_DRV_M41T80_WDT
|
||||||
if (clientdata->features & M41T80_FEATURE_HT) {
|
if (clientdata->features & M41T80_FEATURE_HT) {
|
||||||
save_client = client;
|
save_client = client;
|
||||||
rc = misc_register(&wdt_dev);
|
rc = misc_register(&wdt_dev);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto exit;
|
return rc;
|
||||||
rc = register_reboot_notifier(&wdt_notifier);
|
rc = register_reboot_notifier(&wdt_notifier);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
misc_deregister(&wdt_dev);
|
misc_deregister(&wdt_dev);
|
||||||
goto exit;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
st_err:
|
|
||||||
rc = -EIO;
|
|
||||||
dev_err(&client->dev, "Can't clear ST bit\n");
|
|
||||||
goto exit;
|
|
||||||
ht_err:
|
|
||||||
rc = -EIO;
|
|
||||||
dev_err(&client->dev, "Can't clear HT bit\n");
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int m41t80_remove(struct i2c_client *client)
|
static int m41t80_remove(struct i2c_client *client)
|
||||||
|
@ -750,4 +737,3 @@ module_i2c_driver(m41t80_driver);
|
||||||
MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");
|
MODULE_AUTHOR("Alexander Bigga <ab@mycable.de>");
|
||||||
MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
|
MODULE_DESCRIPTION("ST Microelectronics M41T80 series RTC I2C Client Driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRV_VERSION);
|
|
||||||
|
|
199
drivers/rtc/rtc-mcp795.c
Normal file
199
drivers/rtc/rtc-mcp795.c
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* SPI Driver for Microchip MCP795 RTC
|
||||||
|
*
|
||||||
|
* Copyright (C) Josef Gajdusek <atx@atx.name>
|
||||||
|
*
|
||||||
|
* based on other Linux RTC drivers
|
||||||
|
*
|
||||||
|
* Device datasheet:
|
||||||
|
* http://ww1.microchip.com/downloads/en/DeviceDoc/22280A.pdf
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/printk.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
|
/* MCP795 Instructions, see datasheet table 3-1 */
|
||||||
|
#define MCP795_EEREAD 0x03
|
||||||
|
#define MCP795_EEWRITE 0x02
|
||||||
|
#define MCP795_EEWRDI 0x04
|
||||||
|
#define MCP795_EEWREN 0x06
|
||||||
|
#define MCP795_SRREAD 0x05
|
||||||
|
#define MCP795_SRWRITE 0x01
|
||||||
|
#define MCP795_READ 0x13
|
||||||
|
#define MCP795_WRITE 0x12
|
||||||
|
#define MCP795_UNLOCK 0x14
|
||||||
|
#define MCP795_IDWRITE 0x32
|
||||||
|
#define MCP795_IDREAD 0x33
|
||||||
|
#define MCP795_CLRWDT 0x44
|
||||||
|
#define MCP795_CLRRAM 0x54
|
||||||
|
|
||||||
|
#define MCP795_ST_BIT 0x80
|
||||||
|
#define MCP795_24_BIT 0x40
|
||||||
|
|
||||||
|
static int mcp795_rtcc_read(struct device *dev, u8 addr, u8 *buf, u8 count)
|
||||||
|
{
|
||||||
|
struct spi_device *spi = to_spi_device(dev);
|
||||||
|
int ret;
|
||||||
|
u8 tx[2];
|
||||||
|
|
||||||
|
tx[0] = MCP795_READ;
|
||||||
|
tx[1] = addr;
|
||||||
|
ret = spi_write_then_read(spi, tx, sizeof(tx), buf, count);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "Failed reading %d bytes from address %x.\n",
|
||||||
|
count, addr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcp795_rtcc_write(struct device *dev, u8 addr, u8 *data, u8 count)
|
||||||
|
{
|
||||||
|
struct spi_device *spi = to_spi_device(dev);
|
||||||
|
int ret;
|
||||||
|
u8 tx[2 + count];
|
||||||
|
|
||||||
|
tx[0] = MCP795_WRITE;
|
||||||
|
tx[1] = addr;
|
||||||
|
memcpy(&tx[2], data, count);
|
||||||
|
|
||||||
|
ret = spi_write(spi, tx, 2 + count);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
dev_err(dev, "Failed to write %d bytes to address %x.\n",
|
||||||
|
count, addr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcp795_rtcc_set_bits(struct device *dev, u8 addr, u8 mask, u8 state)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 tmp;
|
||||||
|
|
||||||
|
ret = mcp795_rtcc_read(dev, addr, &tmp, 1);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((tmp & mask) != state) {
|
||||||
|
tmp = (tmp & ~mask) | state;
|
||||||
|
ret = mcp795_rtcc_write(dev, addr, &tmp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcp795_set_time(struct device *dev, struct rtc_time *tim)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 data[7];
|
||||||
|
|
||||||
|
/* Read first, so we can leave config bits untouched */
|
||||||
|
ret = mcp795_rtcc_read(dev, 0x01, data, sizeof(data));
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
data[0] = (data[0] & 0x80) | ((tim->tm_sec / 10) << 4) | (tim->tm_sec % 10);
|
||||||
|
data[1] = (data[1] & 0x80) | ((tim->tm_min / 10) << 4) | (tim->tm_min % 10);
|
||||||
|
data[2] = ((tim->tm_hour / 10) << 4) | (tim->tm_hour % 10);
|
||||||
|
data[4] = ((tim->tm_mday / 10) << 4) | ((tim->tm_mday) % 10);
|
||||||
|
data[5] = (data[5] & 0x10) | (tim->tm_mon / 10) | (tim->tm_mon % 10);
|
||||||
|
|
||||||
|
if (tim->tm_year > 100)
|
||||||
|
tim->tm_year -= 100;
|
||||||
|
|
||||||
|
data[6] = ((tim->tm_year / 10) << 4) | (tim->tm_year % 10);
|
||||||
|
|
||||||
|
ret = mcp795_rtcc_write(dev, 0x01, data, sizeof(data));
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dev_dbg(dev, "Set mcp795: %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
|
||||||
|
tim->tm_hour, tim->tm_min, tim->tm_sec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mcp795_read_time(struct device *dev, struct rtc_time *tim)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u8 data[7];
|
||||||
|
|
||||||
|
ret = mcp795_rtcc_read(dev, 0x01, data, sizeof(data));
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
tim->tm_sec = ((data[0] & 0x70) >> 4) * 10 + (data[0] & 0x0f);
|
||||||
|
tim->tm_min = ((data[1] & 0x70) >> 4) * 10 + (data[1] & 0x0f);
|
||||||
|
tim->tm_hour = ((data[2] & 0x30) >> 4) * 10 + (data[2] & 0x0f);
|
||||||
|
tim->tm_mday = ((data[4] & 0x30) >> 4) * 10 + (data[4] & 0x0f);
|
||||||
|
tim->tm_mon = ((data[5] & 0x10) >> 4) * 10 + (data[5] & 0x0f);
|
||||||
|
tim->tm_year = ((data[6] & 0xf0) >> 4) * 10 + (data[6] & 0x0f) + 100; /* Assume we are in 20xx */
|
||||||
|
|
||||||
|
dev_dbg(dev, "Read from mcp795: %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||||
|
tim->tm_year + 1900, tim->tm_mon, tim->tm_mday,
|
||||||
|
tim->tm_hour, tim->tm_min, tim->tm_sec);
|
||||||
|
|
||||||
|
return rtc_valid_tm(tim);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rtc_class_ops mcp795_rtc_ops = {
|
||||||
|
.read_time = mcp795_read_time,
|
||||||
|
.set_time = mcp795_set_time
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mcp795_probe(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct rtc_device *rtc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spi->mode = SPI_MODE_0;
|
||||||
|
spi->bits_per_word = 8;
|
||||||
|
ret = spi_setup(spi);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&spi->dev, "Unable to setup SPI\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the oscillator */
|
||||||
|
mcp795_rtcc_set_bits(&spi->dev, 0x01, MCP795_ST_BIT, MCP795_ST_BIT);
|
||||||
|
/* Clear the 12 hour mode flag*/
|
||||||
|
mcp795_rtcc_set_bits(&spi->dev, 0x03, MCP795_24_BIT, 0);
|
||||||
|
|
||||||
|
rtc = devm_rtc_device_register(&spi->dev, "rtc-mcp795",
|
||||||
|
&mcp795_rtc_ops, THIS_MODULE);
|
||||||
|
if (IS_ERR(rtc))
|
||||||
|
return PTR_ERR(rtc);
|
||||||
|
|
||||||
|
spi_set_drvdata(spi, rtc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct spi_driver mcp795_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "rtc-mcp795",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = mcp795_probe,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_spi_driver(mcp795_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("MCP795 RTC SPI Driver");
|
||||||
|
MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("spi:mcp795");
|
|
@ -319,7 +319,7 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static struct of_device_id rtc_mv_of_match_table[] = {
|
static const struct of_device_id rtc_mv_of_match_table[] = {
|
||||||
{ .compatible = "marvell,orion-rtc", },
|
{ .compatible = "marvell,orion-rtc", },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,43 +73,52 @@
|
||||||
#define OMAP_RTC_IRQWAKEEN 0x7c
|
#define OMAP_RTC_IRQWAKEEN 0x7c
|
||||||
|
|
||||||
/* OMAP_RTC_CTRL_REG bit fields: */
|
/* OMAP_RTC_CTRL_REG bit fields: */
|
||||||
#define OMAP_RTC_CTRL_SPLIT (1<<7)
|
#define OMAP_RTC_CTRL_SPLIT BIT(7)
|
||||||
#define OMAP_RTC_CTRL_DISABLE (1<<6)
|
#define OMAP_RTC_CTRL_DISABLE BIT(6)
|
||||||
#define OMAP_RTC_CTRL_SET_32_COUNTER (1<<5)
|
#define OMAP_RTC_CTRL_SET_32_COUNTER BIT(5)
|
||||||
#define OMAP_RTC_CTRL_TEST (1<<4)
|
#define OMAP_RTC_CTRL_TEST BIT(4)
|
||||||
#define OMAP_RTC_CTRL_MODE_12_24 (1<<3)
|
#define OMAP_RTC_CTRL_MODE_12_24 BIT(3)
|
||||||
#define OMAP_RTC_CTRL_AUTO_COMP (1<<2)
|
#define OMAP_RTC_CTRL_AUTO_COMP BIT(2)
|
||||||
#define OMAP_RTC_CTRL_ROUND_30S (1<<1)
|
#define OMAP_RTC_CTRL_ROUND_30S BIT(1)
|
||||||
#define OMAP_RTC_CTRL_STOP (1<<0)
|
#define OMAP_RTC_CTRL_STOP BIT(0)
|
||||||
|
|
||||||
/* OMAP_RTC_STATUS_REG bit fields: */
|
/* OMAP_RTC_STATUS_REG bit fields: */
|
||||||
#define OMAP_RTC_STATUS_POWER_UP (1<<7)
|
#define OMAP_RTC_STATUS_POWER_UP BIT(7)
|
||||||
#define OMAP_RTC_STATUS_ALARM (1<<6)
|
#define OMAP_RTC_STATUS_ALARM BIT(6)
|
||||||
#define OMAP_RTC_STATUS_1D_EVENT (1<<5)
|
#define OMAP_RTC_STATUS_1D_EVENT BIT(5)
|
||||||
#define OMAP_RTC_STATUS_1H_EVENT (1<<4)
|
#define OMAP_RTC_STATUS_1H_EVENT BIT(4)
|
||||||
#define OMAP_RTC_STATUS_1M_EVENT (1<<3)
|
#define OMAP_RTC_STATUS_1M_EVENT BIT(3)
|
||||||
#define OMAP_RTC_STATUS_1S_EVENT (1<<2)
|
#define OMAP_RTC_STATUS_1S_EVENT BIT(2)
|
||||||
#define OMAP_RTC_STATUS_RUN (1<<1)
|
#define OMAP_RTC_STATUS_RUN BIT(1)
|
||||||
#define OMAP_RTC_STATUS_BUSY (1<<0)
|
#define OMAP_RTC_STATUS_BUSY BIT(0)
|
||||||
|
|
||||||
/* OMAP_RTC_INTERRUPTS_REG bit fields: */
|
/* OMAP_RTC_INTERRUPTS_REG bit fields: */
|
||||||
#define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3)
|
#define OMAP_RTC_INTERRUPTS_IT_ALARM BIT(3)
|
||||||
#define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2)
|
#define OMAP_RTC_INTERRUPTS_IT_TIMER BIT(2)
|
||||||
|
|
||||||
|
/* OMAP_RTC_OSC_REG bit fields: */
|
||||||
|
#define OMAP_RTC_OSC_32KCLK_EN BIT(6)
|
||||||
|
|
||||||
/* OMAP_RTC_IRQWAKEEN bit fields: */
|
/* OMAP_RTC_IRQWAKEEN bit fields: */
|
||||||
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN (1<<1)
|
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1)
|
||||||
|
|
||||||
/* OMAP_RTC_KICKER values */
|
/* OMAP_RTC_KICKER values */
|
||||||
#define KICK0_VALUE 0x83e70b13
|
#define KICK0_VALUE 0x83e70b13
|
||||||
#define KICK1_VALUE 0x95a4f1e0
|
#define KICK1_VALUE 0x95a4f1e0
|
||||||
|
|
||||||
#define OMAP_RTC_HAS_KICKER 0x1
|
#define OMAP_RTC_HAS_KICKER BIT(0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
|
* Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
|
||||||
* generation for event Alarm.
|
* generation for event Alarm.
|
||||||
*/
|
*/
|
||||||
#define OMAP_RTC_HAS_IRQWAKEEN 0x2
|
#define OMAP_RTC_HAS_IRQWAKEEN BIT(1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some RTC IP revisions (like those in AM335x and DRA7x) need
|
||||||
|
* the 32KHz clock to be explicitly enabled.
|
||||||
|
*/
|
||||||
|
#define OMAP_RTC_HAS_32KCLK_EN BIT(2)
|
||||||
|
|
||||||
static void __iomem *rtc_base;
|
static void __iomem *rtc_base;
|
||||||
|
|
||||||
|
@ -162,17 +171,28 @@ static irqreturn_t rtc_irq(int irq, void *rtc)
|
||||||
|
|
||||||
static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
{
|
{
|
||||||
u8 reg;
|
u8 reg, irqwake_reg = 0;
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
const struct platform_device_id *id_entry =
|
||||||
|
platform_get_device_id(pdev);
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
rtc_wait_not_busy();
|
rtc_wait_not_busy();
|
||||||
reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
||||||
if (enabled)
|
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
|
||||||
|
irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
|
||||||
|
|
||||||
|
if (enabled) {
|
||||||
reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
|
reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
|
||||||
else
|
irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
||||||
|
} else {
|
||||||
reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
|
reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
|
||||||
|
irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
||||||
|
}
|
||||||
rtc_wait_not_busy();
|
rtc_wait_not_busy();
|
||||||
rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
|
||||||
|
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
|
||||||
|
rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -272,7 +292,10 @@ static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||||
|
|
||||||
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||||
{
|
{
|
||||||
u8 reg;
|
u8 reg, irqwake_reg = 0;
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
const struct platform_device_id *id_entry =
|
||||||
|
platform_get_device_id(pdev);
|
||||||
|
|
||||||
if (tm2bcd(&alm->time) < 0)
|
if (tm2bcd(&alm->time) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -288,11 +311,19 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
||||||
rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
|
rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
|
||||||
|
|
||||||
reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
||||||
if (alm->enabled)
|
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
|
||||||
|
irqwake_reg = rtc_read(OMAP_RTC_IRQWAKEEN);
|
||||||
|
|
||||||
|
if (alm->enabled) {
|
||||||
reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
|
reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
|
||||||
else
|
irqwake_reg |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
||||||
|
} else {
|
||||||
reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
|
reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
|
||||||
|
irqwake_reg &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
||||||
|
}
|
||||||
rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
|
||||||
|
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN)
|
||||||
|
rtc_write(irqwake_reg, OMAP_RTC_IRQWAKEEN);
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
|
@ -319,7 +350,8 @@ static struct platform_device_id omap_rtc_devtype[] = {
|
||||||
},
|
},
|
||||||
[OMAP_RTC_DATA_AM3352_IDX] = {
|
[OMAP_RTC_DATA_AM3352_IDX] = {
|
||||||
.name = "am3352-rtc",
|
.name = "am3352-rtc",
|
||||||
.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
|
.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN |
|
||||||
|
OMAP_RTC_HAS_32KCLK_EN,
|
||||||
},
|
},
|
||||||
[OMAP_RTC_DATA_DA830_IDX] = {
|
[OMAP_RTC_DATA_DA830_IDX] = {
|
||||||
.name = "da830-rtc",
|
.name = "da830-rtc",
|
||||||
|
@ -352,6 +384,12 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
|
||||||
if (of_id)
|
if (of_id)
|
||||||
pdev->id_entry = of_id->data;
|
pdev->id_entry = of_id->data;
|
||||||
|
|
||||||
|
id_entry = platform_get_device_id(pdev);
|
||||||
|
if (!id_entry) {
|
||||||
|
dev_err(&pdev->dev, "no matching device entry\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
omap_rtc_timer = platform_get_irq(pdev, 0);
|
omap_rtc_timer = platform_get_irq(pdev, 0);
|
||||||
if (omap_rtc_timer <= 0) {
|
if (omap_rtc_timer <= 0) {
|
||||||
pr_debug("%s: no update irq?\n", pdev->name);
|
pr_debug("%s: no update irq?\n", pdev->name);
|
||||||
|
@ -373,8 +411,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
|
||||||
pm_runtime_enable(&pdev->dev);
|
pm_runtime_enable(&pdev->dev);
|
||||||
pm_runtime_get_sync(&pdev->dev);
|
pm_runtime_get_sync(&pdev->dev);
|
||||||
|
|
||||||
id_entry = platform_get_device_id(pdev);
|
if (id_entry->driver_data & OMAP_RTC_HAS_KICKER) {
|
||||||
if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) {
|
|
||||||
rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
|
rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG);
|
||||||
rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
|
rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG);
|
||||||
}
|
}
|
||||||
|
@ -393,6 +430,10 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
|
||||||
*/
|
*/
|
||||||
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
||||||
|
|
||||||
|
/* enable RTC functional clock */
|
||||||
|
if (id_entry->driver_data & OMAP_RTC_HAS_32KCLK_EN)
|
||||||
|
rtc_writel(OMAP_RTC_OSC_32KCLK_EN, OMAP_RTC_OSC_REG);
|
||||||
|
|
||||||
/* clear old status */
|
/* clear old status */
|
||||||
reg = rtc_read(OMAP_RTC_STATUS_REG);
|
reg = rtc_read(OMAP_RTC_STATUS_REG);
|
||||||
if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
|
if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
|
||||||
|
@ -452,7 +493,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail0:
|
fail0:
|
||||||
if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
|
if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
|
||||||
rtc_writel(0, OMAP_RTC_KICK0_REG);
|
rtc_writel(0, OMAP_RTC_KICK0_REG);
|
||||||
pm_runtime_put_sync(&pdev->dev);
|
pm_runtime_put_sync(&pdev->dev);
|
||||||
pm_runtime_disable(&pdev->dev);
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
@ -469,7 +510,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
|
||||||
/* leave rtc running, but disable irqs */
|
/* leave rtc running, but disable irqs */
|
||||||
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
||||||
|
|
||||||
if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER))
|
if (id_entry->driver_data & OMAP_RTC_HAS_KICKER)
|
||||||
rtc_writel(0, OMAP_RTC_KICK0_REG);
|
rtc_writel(0, OMAP_RTC_KICK0_REG);
|
||||||
|
|
||||||
/* Disable the clock/module */
|
/* Disable the clock/module */
|
||||||
|
@ -484,28 +525,16 @@ static u8 irqstat;
|
||||||
|
|
||||||
static int omap_rtc_suspend(struct device *dev)
|
static int omap_rtc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
u8 irqwake_stat;
|
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
|
||||||
const struct platform_device_id *id_entry =
|
|
||||||
platform_get_device_id(pdev);
|
|
||||||
|
|
||||||
irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
|
||||||
|
|
||||||
/* FIXME the RTC alarm is not currently acting as a wakeup event
|
/* FIXME the RTC alarm is not currently acting as a wakeup event
|
||||||
* source on some platforms, and in fact this enable() call is just
|
* source on some platforms, and in fact this enable() call is just
|
||||||
* saving a flag that's never used...
|
* saving a flag that's never used...
|
||||||
*/
|
*/
|
||||||
if (device_may_wakeup(dev)) {
|
if (device_may_wakeup(dev))
|
||||||
enable_irq_wake(omap_rtc_alarm);
|
enable_irq_wake(omap_rtc_alarm);
|
||||||
|
else
|
||||||
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
|
|
||||||
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
|
|
||||||
irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
|
||||||
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable the clock/module */
|
/* Disable the clock/module */
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put_sync(dev);
|
||||||
|
@ -515,25 +544,14 @@ static int omap_rtc_suspend(struct device *dev)
|
||||||
|
|
||||||
static int omap_rtc_resume(struct device *dev)
|
static int omap_rtc_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
u8 irqwake_stat;
|
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
|
||||||
const struct platform_device_id *id_entry =
|
|
||||||
platform_get_device_id(pdev);
|
|
||||||
|
|
||||||
/* Enable the clock/module so that we can access the registers */
|
/* Enable the clock/module so that we can access the registers */
|
||||||
pm_runtime_get_sync(dev);
|
pm_runtime_get_sync(dev);
|
||||||
|
|
||||||
if (device_may_wakeup(dev)) {
|
if (device_may_wakeup(dev))
|
||||||
disable_irq_wake(omap_rtc_alarm);
|
disable_irq_wake(omap_rtc_alarm);
|
||||||
|
else
|
||||||
if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
|
|
||||||
irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
|
|
||||||
irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
|
|
||||||
rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
|
rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -352,7 +352,7 @@ static SIMPLE_DEV_PM_OPS(palmas_rtc_pm_ops, palmas_rtc_suspend,
|
||||||
palmas_rtc_resume);
|
palmas_rtc_resume);
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static struct of_device_id of_palmas_rtc_match[] = {
|
static const struct of_device_id of_palmas_rtc_match[] = {
|
||||||
{ .compatible = "ti,palmas-rtc"},
|
{ .compatible = "ti,palmas-rtc"},
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
|
@ -389,7 +389,7 @@ static int __exit pxa_rtc_remove(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static struct of_device_id pxa_rtc_dt_ids[] = {
|
static const struct of_device_id pxa_rtc_dt_ids[] = {
|
||||||
{ .compatible = "marvell,pxa-rtc" },
|
{ .compatible = "marvell,pxa-rtc" },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
|
@ -338,7 +338,7 @@ static SIMPLE_DEV_PM_OPS(sa1100_rtc_pm_ops, sa1100_rtc_suspend,
|
||||||
sa1100_rtc_resume);
|
sa1100_rtc_resume);
|
||||||
|
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
static struct of_device_id sa1100_rtc_dt_ids[] = {
|
static const struct of_device_id sa1100_rtc_dt_ids[] = {
|
||||||
{ .compatible = "mrvl,sa1100-rtc", },
|
{ .compatible = "mrvl,sa1100-rtc", },
|
||||||
{ .compatible = "mrvl,mmp-rtc", },
|
{ .compatible = "mrvl,mmp-rtc", },
|
||||||
{}
|
{}
|
||||||
|
|
278
drivers/rtc/rtc-xgene.c
Normal file
278
drivers/rtc/rtc-xgene.c
Normal file
|
@ -0,0 +1,278 @@
|
||||||
|
/*
|
||||||
|
* APM X-Gene SoC Real Time Clock Driver
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014, Applied Micro Circuits Corporation
|
||||||
|
* Author: Rameshwar Prasad Sahu <rsahu@apm.com>
|
||||||
|
* Loc Ho <lho@apm.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
|
/* RTC CSR Registers */
|
||||||
|
#define RTC_CCVR 0x00
|
||||||
|
#define RTC_CMR 0x04
|
||||||
|
#define RTC_CLR 0x08
|
||||||
|
#define RTC_CCR 0x0C
|
||||||
|
#define RTC_CCR_IE BIT(0)
|
||||||
|
#define RTC_CCR_MASK BIT(1)
|
||||||
|
#define RTC_CCR_EN BIT(2)
|
||||||
|
#define RTC_CCR_WEN BIT(3)
|
||||||
|
#define RTC_STAT 0x10
|
||||||
|
#define RTC_STAT_BIT BIT(0)
|
||||||
|
#define RTC_RSTAT 0x14
|
||||||
|
#define RTC_EOI 0x18
|
||||||
|
#define RTC_VER 0x1C
|
||||||
|
|
||||||
|
struct xgene_rtc_dev {
|
||||||
|
struct rtc_device *rtc;
|
||||||
|
struct device *dev;
|
||||||
|
unsigned long alarm_time;
|
||||||
|
void __iomem *csr_base;
|
||||||
|
struct clk *clk;
|
||||||
|
unsigned int irq_wake;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
rtc_time_to_tm(readl(pdata->csr_base + RTC_CCVR), tm);
|
||||||
|
return rtc_valid_tm(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_set_mmss(struct device *dev, unsigned long secs)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: After the following write, the RTC_CCVR is only reflected
|
||||||
|
* after the update cycle of 1 seconds.
|
||||||
|
*/
|
||||||
|
writel((u32) secs, pdata->csr_base + RTC_CLR);
|
||||||
|
readl(pdata->csr_base + RTC_CLR); /* Force a barrier */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
rtc_time_to_tm(pdata->alarm_time, &alrm->time);
|
||||||
|
alrm->enabled = readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
|
||||||
|
u32 ccr;
|
||||||
|
|
||||||
|
ccr = readl(pdata->csr_base + RTC_CCR);
|
||||||
|
if (enabled) {
|
||||||
|
ccr &= ~RTC_CCR_MASK;
|
||||||
|
ccr |= RTC_CCR_IE;
|
||||||
|
} else {
|
||||||
|
ccr &= ~RTC_CCR_IE;
|
||||||
|
ccr |= RTC_CCR_MASK;
|
||||||
|
}
|
||||||
|
writel(ccr, pdata->csr_base + RTC_CCR);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
|
||||||
|
unsigned long rtc_time;
|
||||||
|
unsigned long alarm_time;
|
||||||
|
|
||||||
|
rtc_time = readl(pdata->csr_base + RTC_CCVR);
|
||||||
|
rtc_tm_to_time(&alrm->time, &alarm_time);
|
||||||
|
|
||||||
|
pdata->alarm_time = alarm_time;
|
||||||
|
writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR);
|
||||||
|
|
||||||
|
xgene_rtc_alarm_irq_enable(dev, alrm->enabled);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rtc_class_ops xgene_rtc_ops = {
|
||||||
|
.read_time = xgene_rtc_read_time,
|
||||||
|
.set_mmss = xgene_rtc_set_mmss,
|
||||||
|
.read_alarm = xgene_rtc_read_alarm,
|
||||||
|
.set_alarm = xgene_rtc_set_alarm,
|
||||||
|
.alarm_irq_enable = xgene_rtc_alarm_irq_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static irqreturn_t xgene_rtc_interrupt(int irq, void *id)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = (struct xgene_rtc_dev *) id;
|
||||||
|
|
||||||
|
/* Check if interrupt asserted */
|
||||||
|
if (!(readl(pdata->csr_base + RTC_STAT) & RTC_STAT_BIT))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
/* Clear interrupt */
|
||||||
|
readl(pdata->csr_base + RTC_EOI);
|
||||||
|
|
||||||
|
rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata;
|
||||||
|
struct resource *res;
|
||||||
|
int ret;
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||||
|
if (!pdata)
|
||||||
|
return -ENOMEM;
|
||||||
|
platform_set_drvdata(pdev, pdata);
|
||||||
|
pdata->dev = &pdev->dev;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
pdata->csr_base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(pdata->csr_base))
|
||||||
|
return PTR_ERR(pdata->csr_base);
|
||||||
|
|
||||||
|
irq = platform_get_irq(pdev, 0);
|
||||||
|
if (irq < 0) {
|
||||||
|
dev_err(&pdev->dev, "No IRQ resource\n");
|
||||||
|
return irq;
|
||||||
|
}
|
||||||
|
ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0,
|
||||||
|
dev_name(&pdev->dev), pdata);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Could not request IRQ\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(pdata->clk)) {
|
||||||
|
dev_err(&pdev->dev, "Couldn't get the clock for RTC\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
clk_prepare_enable(pdata->clk);
|
||||||
|
|
||||||
|
/* Turn on the clock and the crystal */
|
||||||
|
writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR);
|
||||||
|
|
||||||
|
device_init_wakeup(&pdev->dev, 1);
|
||||||
|
|
||||||
|
pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
|
||||||
|
&xgene_rtc_ops, THIS_MODULE);
|
||||||
|
if (IS_ERR(pdata->rtc)) {
|
||||||
|
clk_disable_unprepare(pdata->clk);
|
||||||
|
return PTR_ERR(pdata->rtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HW does not support update faster than 1 seconds */
|
||||||
|
pdata->rtc->uie_unsupported = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
xgene_rtc_alarm_irq_enable(&pdev->dev, 0);
|
||||||
|
device_init_wakeup(&pdev->dev, 0);
|
||||||
|
clk_disable_unprepare(pdata->clk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int xgene_rtc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
irq = platform_get_irq(pdev, 0);
|
||||||
|
if (device_may_wakeup(&pdev->dev)) {
|
||||||
|
if (!enable_irq_wake(irq))
|
||||||
|
pdata->irq_wake = 1;
|
||||||
|
} else {
|
||||||
|
xgene_rtc_alarm_irq_enable(dev, 0);
|
||||||
|
clk_disable(pdata->clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xgene_rtc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
irq = platform_get_irq(pdev, 0);
|
||||||
|
if (device_may_wakeup(&pdev->dev)) {
|
||||||
|
if (pdata->irq_wake) {
|
||||||
|
disable_irq_wake(irq);
|
||||||
|
pdata->irq_wake = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clk_enable(pdata->clk);
|
||||||
|
xgene_rtc_alarm_irq_enable(dev, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id xgene_rtc_of_match[] = {
|
||||||
|
{.compatible = "apm,xgene-rtc" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, xgene_rtc_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct platform_driver xgene_rtc_driver = {
|
||||||
|
.probe = xgene_rtc_probe,
|
||||||
|
.remove = xgene_rtc_remove,
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "xgene-rtc",
|
||||||
|
.pm = &xgene_rtc_pm_ops,
|
||||||
|
.of_match_table = of_match_ptr(xgene_rtc_of_match),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(xgene_rtc_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("APM X-Gene SoC RTC driver");
|
||||||
|
MODULE_AUTHOR("Rameshwar Sahu <rsahu@apm.com>");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -12,7 +12,7 @@
|
||||||
#include "scsi_priv.h"
|
#include "scsi_priv.h"
|
||||||
|
|
||||||
|
|
||||||
static ctl_table scsi_table[] = {
|
static struct ctl_table scsi_table[] = {
|
||||||
{ .procname = "logging_level",
|
{ .procname = "logging_level",
|
||||||
.data = &scsi_logging_level,
|
.data = &scsi_logging_level,
|
||||||
.maxlen = sizeof(scsi_logging_level),
|
.maxlen = sizeof(scsi_logging_level),
|
||||||
|
@ -21,14 +21,14 @@ static ctl_table scsi_table[] = {
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table scsi_dir_table[] = {
|
static struct ctl_table scsi_dir_table[] = {
|
||||||
{ .procname = "scsi",
|
{ .procname = "scsi",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
.child = scsi_table },
|
.child = scsi_table },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table scsi_root_table[] = {
|
static struct ctl_table scsi_root_table[] = {
|
||||||
{ .procname = "dev",
|
{ .procname = "dev",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
.child = scsi_dir_table },
|
.child = scsi_dir_table },
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/rcupdate.h>
|
||||||
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/irq_regs.h>
|
#include <asm/irq_regs.h>
|
||||||
|
@ -510,9 +511,9 @@ void __handle_sysrq(int key, bool check_mask)
|
||||||
struct sysrq_key_op *op_p;
|
struct sysrq_key_op *op_p;
|
||||||
int orig_log_level;
|
int orig_log_level;
|
||||||
int i;
|
int i;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sysrq_key_table_lock, flags);
|
rcu_sysrq_start();
|
||||||
|
rcu_read_lock();
|
||||||
/*
|
/*
|
||||||
* Raise the apparent loglevel to maximum so that the sysrq header
|
* Raise the apparent loglevel to maximum so that the sysrq header
|
||||||
* is shown to provide the user with positive feedback. We do not
|
* is shown to provide the user with positive feedback. We do not
|
||||||
|
@ -554,7 +555,8 @@ void __handle_sysrq(int key, bool check_mask)
|
||||||
printk("\n");
|
printk("\n");
|
||||||
console_loglevel = orig_log_level;
|
console_loglevel = orig_log_level;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
|
rcu_read_unlock();
|
||||||
|
rcu_sysrq_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_sysrq(int key)
|
void handle_sysrq(int key)
|
||||||
|
@ -1043,16 +1045,23 @@ static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
|
||||||
struct sysrq_key_op *remove_op_p)
|
struct sysrq_key_op *remove_op_p)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sysrq_key_table_lock, flags);
|
spin_lock(&sysrq_key_table_lock);
|
||||||
if (__sysrq_get_key_op(key) == remove_op_p) {
|
if (__sysrq_get_key_op(key) == remove_op_p) {
|
||||||
__sysrq_put_key_op(key, insert_op_p);
|
__sysrq_put_key_op(key, insert_op_p);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
} else {
|
} else {
|
||||||
retval = -1;
|
retval = -1;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
|
spin_unlock(&sysrq_key_table_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A concurrent __handle_sysrq either got the old op or the new op.
|
||||||
|
* Wait for it to go away before returning, so the code for an old
|
||||||
|
* op is not freed (eg. on module unload) while it is in use.
|
||||||
|
*/
|
||||||
|
synchronize_rcu();
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
#ifdef pr_fmt
|
||||||
|
#undef pr_fmt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/buffer_head.h>
|
#include <linux/buffer_head.h>
|
||||||
|
@ -206,7 +212,7 @@ affs_set_blocksize(struct super_block *sb, int size)
|
||||||
static inline struct buffer_head *
|
static inline struct buffer_head *
|
||||||
affs_bread(struct super_block *sb, int block)
|
affs_bread(struct super_block *sb, int block)
|
||||||
{
|
{
|
||||||
pr_debug("affs_bread: %d\n", block);
|
pr_debug("%s: %d\n", __func__, block);
|
||||||
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
|
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
|
||||||
return sb_bread(sb, block);
|
return sb_bread(sb, block);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -214,7 +220,7 @@ affs_bread(struct super_block *sb, int block)
|
||||||
static inline struct buffer_head *
|
static inline struct buffer_head *
|
||||||
affs_getblk(struct super_block *sb, int block)
|
affs_getblk(struct super_block *sb, int block)
|
||||||
{
|
{
|
||||||
pr_debug("affs_getblk: %d\n", block);
|
pr_debug("%s: %d\n", __func__, block);
|
||||||
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
|
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size)
|
||||||
return sb_getblk(sb, block);
|
return sb_getblk(sb, block);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -223,7 +229,7 @@ static inline struct buffer_head *
|
||||||
affs_getzeroblk(struct super_block *sb, int block)
|
affs_getzeroblk(struct super_block *sb, int block)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
pr_debug("affs_getzeroblk: %d\n", block);
|
pr_debug("%s: %d\n", __func__, block);
|
||||||
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
|
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
|
||||||
bh = sb_getblk(sb, block);
|
bh = sb_getblk(sb, block);
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
|
@ -238,7 +244,7 @@ static inline struct buffer_head *
|
||||||
affs_getemptyblk(struct super_block *sb, int block)
|
affs_getemptyblk(struct super_block *sb, int block)
|
||||||
{
|
{
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
pr_debug("affs_getemptyblk: %d\n", block);
|
pr_debug("%s: %d\n", __func__, block);
|
||||||
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
|
if (block >= AFFS_SB(sb)->s_reserved && block < AFFS_SB(sb)->s_partition_size) {
|
||||||
bh = sb_getblk(sb, block);
|
bh = sb_getblk(sb, block);
|
||||||
wait_on_buffer(bh);
|
wait_on_buffer(bh);
|
||||||
|
@ -251,7 +257,7 @@ static inline void
|
||||||
affs_brelse(struct buffer_head *bh)
|
affs_brelse(struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
if (bh)
|
if (bh)
|
||||||
pr_debug("affs_brelse: %lld\n", (long long) bh->b_blocknr);
|
pr_debug("%s: %lld\n", __func__, (long long) bh->b_blocknr);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ affs_insert_hash(struct inode *dir, struct buffer_head *bh)
|
||||||
ino = bh->b_blocknr;
|
ino = bh->b_blocknr;
|
||||||
offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]);
|
offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]);
|
||||||
|
|
||||||
pr_debug("AFFS: insert_hash(dir=%u, ino=%d)\n", (u32)dir->i_ino, ino);
|
pr_debug("%s(dir=%u, ino=%d)\n", __func__, (u32)dir->i_ino, ino);
|
||||||
|
|
||||||
dir_bh = affs_bread(sb, dir->i_ino);
|
dir_bh = affs_bread(sb, dir->i_ino);
|
||||||
if (!dir_bh)
|
if (!dir_bh)
|
||||||
|
@ -84,7 +84,8 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
|
||||||
sb = dir->i_sb;
|
sb = dir->i_sb;
|
||||||
rem_ino = rem_bh->b_blocknr;
|
rem_ino = rem_bh->b_blocknr;
|
||||||
offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]);
|
offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]);
|
||||||
pr_debug("AFFS: remove_hash(dir=%d, ino=%d, hashval=%d)\n", (u32)dir->i_ino, rem_ino, offset);
|
pr_debug("%s(dir=%d, ino=%d, hashval=%d)\n",
|
||||||
|
__func__, (u32)dir->i_ino, rem_ino, offset);
|
||||||
|
|
||||||
bh = affs_bread(sb, dir->i_ino);
|
bh = affs_bread(sb, dir->i_ino);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
|
@ -147,7 +148,7 @@ affs_remove_link(struct dentry *dentry)
|
||||||
u32 link_ino, ino;
|
u32 link_ino, ino;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
pr_debug("AFFS: remove_link(key=%ld)\n", inode->i_ino);
|
pr_debug("%s(key=%ld)\n", __func__, inode->i_ino);
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
bh = affs_bread(sb, inode->i_ino);
|
bh = affs_bread(sb, inode->i_ino);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
|
@ -279,7 +280,7 @@ affs_remove_header(struct dentry *dentry)
|
||||||
if (!inode)
|
if (!inode)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
pr_debug("AFFS: remove_header(key=%ld)\n", inode->i_ino);
|
pr_debug("%s(key=%ld)\n", __func__, inode->i_ino);
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
bh = affs_bread(sb, (u32)(long)dentry->d_fsdata);
|
bh = affs_bread(sb, (u32)(long)dentry->d_fsdata);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
|
@ -451,10 +452,10 @@ affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
|
||||||
vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
|
vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printk(KERN_CRIT "AFFS error (device %s): %s(): %s\n", sb->s_id,
|
pr_crit("error (device %s): %s(): %s\n", sb->s_id,
|
||||||
function,ErrorBuffer);
|
function,ErrorBuffer);
|
||||||
if (!(sb->s_flags & MS_RDONLY))
|
if (!(sb->s_flags & MS_RDONLY))
|
||||||
printk(KERN_WARNING "AFFS: Remounting filesystem read-only\n");
|
pr_warn("Remounting filesystem read-only\n");
|
||||||
sb->s_flags |= MS_RDONLY;
|
sb->s_flags |= MS_RDONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,7 +468,7 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
|
||||||
vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
|
vsnprintf(ErrorBuffer,sizeof(ErrorBuffer),fmt,args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
printk(KERN_WARNING "AFFS warning (device %s): %s(): %s\n", sb->s_id,
|
pr_warn("(device %s): %s(): %s\n", sb->s_id,
|
||||||
function,ErrorBuffer);
|
function,ErrorBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ affs_count_free_blocks(struct super_block *sb)
|
||||||
u32 free;
|
u32 free;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pr_debug("AFFS: count_free_blocks()\n");
|
pr_debug("%s()\n", __func__);
|
||||||
|
|
||||||
if (sb->s_flags & MS_RDONLY)
|
if (sb->s_flags & MS_RDONLY)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -43,7 +43,7 @@ affs_free_block(struct super_block *sb, u32 block)
|
||||||
u32 blk, bmap, bit, mask, tmp;
|
u32 blk, bmap, bit, mask, tmp;
|
||||||
__be32 *data;
|
__be32 *data;
|
||||||
|
|
||||||
pr_debug("AFFS: free_block(%u)\n", block);
|
pr_debug("%s(%u)\n", __func__, block);
|
||||||
|
|
||||||
if (block > sbi->s_partition_size)
|
if (block > sbi->s_partition_size)
|
||||||
goto err_range;
|
goto err_range;
|
||||||
|
@ -125,7 +125,7 @@ affs_alloc_block(struct inode *inode, u32 goal)
|
||||||
sb = inode->i_sb;
|
sb = inode->i_sb;
|
||||||
sbi = AFFS_SB(sb);
|
sbi = AFFS_SB(sb);
|
||||||
|
|
||||||
pr_debug("AFFS: balloc(inode=%lu,goal=%u): ", inode->i_ino, goal);
|
pr_debug("balloc(inode=%lu,goal=%u): ", inode->i_ino, goal);
|
||||||
|
|
||||||
if (AFFS_I(inode)->i_pa_cnt) {
|
if (AFFS_I(inode)->i_pa_cnt) {
|
||||||
pr_debug("%d\n", AFFS_I(inode)->i_lastalloc+1);
|
pr_debug("%d\n", AFFS_I(inode)->i_lastalloc+1);
|
||||||
|
@ -254,8 +254,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
|
if (!AFFS_ROOT_TAIL(sb, sbi->s_root_bh)->bm_flag) {
|
||||||
printk(KERN_NOTICE "AFFS: Bitmap invalid - mounting %s read only\n",
|
pr_notice("Bitmap invalid - mounting %s read only\n", sb->s_id);
|
||||||
sb->s_id);
|
|
||||||
*flags |= MS_RDONLY;
|
*flags |= MS_RDONLY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +267,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
|
||||||
size = sbi->s_bmap_count * sizeof(*bm);
|
size = sbi->s_bmap_count * sizeof(*bm);
|
||||||
bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL);
|
bm = sbi->s_bitmap = kzalloc(size, GFP_KERNEL);
|
||||||
if (!sbi->s_bitmap) {
|
if (!sbi->s_bitmap) {
|
||||||
printk(KERN_ERR "AFFS: Bitmap allocation failed\n");
|
pr_err("Bitmap allocation failed\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,17 +281,17 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
|
||||||
bm->bm_key = be32_to_cpu(bmap_blk[blk]);
|
bm->bm_key = be32_to_cpu(bmap_blk[blk]);
|
||||||
bh = affs_bread(sb, bm->bm_key);
|
bh = affs_bread(sb, bm->bm_key);
|
||||||
if (!bh) {
|
if (!bh) {
|
||||||
printk(KERN_ERR "AFFS: Cannot read bitmap\n");
|
pr_err("Cannot read bitmap\n");
|
||||||
res = -EIO;
|
res = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (affs_checksum_block(sb, bh)) {
|
if (affs_checksum_block(sb, bh)) {
|
||||||
printk(KERN_WARNING "AFFS: Bitmap %u invalid - mounting %s read only.\n",
|
pr_warn("Bitmap %u invalid - mounting %s read only.\n",
|
||||||
bm->bm_key, sb->s_id);
|
bm->bm_key, sb->s_id);
|
||||||
*flags |= MS_RDONLY;
|
*flags |= MS_RDONLY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
pr_debug("AFFS: read bitmap block %d: %d\n", blk, bm->bm_key);
|
pr_debug("read bitmap block %d: %d\n", blk, bm->bm_key);
|
||||||
bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4);
|
bm->bm_free = memweight(bh->b_data + 4, sb->s_blocksize - 4);
|
||||||
|
|
||||||
/* Don't try read the extension if this is the last block,
|
/* Don't try read the extension if this is the last block,
|
||||||
|
@ -304,7 +303,7 @@ int affs_init_bitmap(struct super_block *sb, int *flags)
|
||||||
affs_brelse(bmap_bh);
|
affs_brelse(bmap_bh);
|
||||||
bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
|
bmap_bh = affs_bread(sb, be32_to_cpu(bmap_blk[blk]));
|
||||||
if (!bmap_bh) {
|
if (!bmap_bh) {
|
||||||
printk(KERN_ERR "AFFS: Cannot read bitmap extension\n");
|
pr_err("Cannot read bitmap extension\n");
|
||||||
res = -EIO;
|
res = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,8 @@ affs_readdir(struct file *file, struct dir_context *ctx)
|
||||||
u32 ino;
|
u32 ino;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
pr_debug("AFFS: readdir(ino=%lu,f_pos=%lx)\n",
|
pr_debug("%s(ino=%lu,f_pos=%lx)\n",
|
||||||
inode->i_ino, (unsigned long)ctx->pos);
|
__func__, inode->i_ino, (unsigned long)ctx->pos);
|
||||||
|
|
||||||
if (ctx->pos < 2) {
|
if (ctx->pos < 2) {
|
||||||
file->private_data = (void *)0;
|
file->private_data = (void *)0;
|
||||||
|
@ -81,7 +81,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
|
||||||
*/
|
*/
|
||||||
ino = (u32)(long)file->private_data;
|
ino = (u32)(long)file->private_data;
|
||||||
if (ino && file->f_version == inode->i_version) {
|
if (ino && file->f_version == inode->i_version) {
|
||||||
pr_debug("AFFS: readdir() left off=%d\n", ino);
|
pr_debug("readdir() left off=%d\n", ino);
|
||||||
goto inside;
|
goto inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ affs_readdir(struct file *file, struct dir_context *ctx)
|
||||||
|
|
||||||
namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
|
namelen = min(AFFS_TAIL(sb, fh_bh)->name[0], (u8)30);
|
||||||
name = AFFS_TAIL(sb, fh_bh)->name + 1;
|
name = AFFS_TAIL(sb, fh_bh)->name + 1;
|
||||||
pr_debug("AFFS: readdir(): dir_emit(\"%.*s\", "
|
pr_debug("readdir(): dir_emit(\"%.*s\", "
|
||||||
"ino=%u), hash=%d, f_pos=%x\n",
|
"ino=%u), hash=%d, f_pos=%x\n",
|
||||||
namelen, name, ino, hash_pos, (u32)ctx->pos);
|
namelen, name, ino, hash_pos, (u32)ctx->pos);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ const struct inode_operations affs_file_inode_operations = {
|
||||||
static int
|
static int
|
||||||
affs_file_open(struct inode *inode, struct file *filp)
|
affs_file_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
pr_debug("AFFS: open(%lu,%d)\n",
|
pr_debug("open(%lu,%d)\n",
|
||||||
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
|
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
|
||||||
atomic_inc(&AFFS_I(inode)->i_opencnt);
|
atomic_inc(&AFFS_I(inode)->i_opencnt);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -54,7 +54,7 @@ affs_file_open(struct inode *inode, struct file *filp)
|
||||||
static int
|
static int
|
||||||
affs_file_release(struct inode *inode, struct file *filp)
|
affs_file_release(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
pr_debug("AFFS: release(%lu, %d)\n",
|
pr_debug("release(%lu, %d)\n",
|
||||||
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
|
inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
|
||||||
|
|
||||||
if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
|
if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
|
||||||
|
@ -324,7 +324,8 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul
|
||||||
struct buffer_head *ext_bh;
|
struct buffer_head *ext_bh;
|
||||||
u32 ext;
|
u32 ext;
|
||||||
|
|
||||||
pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
|
pr_debug("%s(%u, %lu)\n",
|
||||||
|
__func__, (u32)inode->i_ino, (unsigned long)block);
|
||||||
|
|
||||||
BUG_ON(block > (sector_t)0x7fffffffUL);
|
BUG_ON(block > (sector_t)0x7fffffffUL);
|
||||||
|
|
||||||
|
@ -498,34 +499,36 @@ affs_getemptyblk_ino(struct inode *inode, int block)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
|
affs_do_readpage_ofs(struct page *page, unsigned to)
|
||||||
{
|
{
|
||||||
struct inode *inode = page->mapping->host;
|
struct inode *inode = page->mapping->host;
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
char *data;
|
char *data;
|
||||||
|
unsigned pos = 0;
|
||||||
u32 bidx, boff, bsize;
|
u32 bidx, boff, bsize;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
|
pr_debug("%s(%u, %ld, 0, %d)\n", __func__, (u32)inode->i_ino,
|
||||||
BUG_ON(from > to || to > PAGE_CACHE_SIZE);
|
page->index, to);
|
||||||
|
BUG_ON(to > PAGE_CACHE_SIZE);
|
||||||
kmap(page);
|
kmap(page);
|
||||||
data = page_address(page);
|
data = page_address(page);
|
||||||
bsize = AFFS_SB(sb)->s_data_blksize;
|
bsize = AFFS_SB(sb)->s_data_blksize;
|
||||||
tmp = (page->index << PAGE_CACHE_SHIFT) + from;
|
tmp = page->index << PAGE_CACHE_SHIFT;
|
||||||
bidx = tmp / bsize;
|
bidx = tmp / bsize;
|
||||||
boff = tmp % bsize;
|
boff = tmp % bsize;
|
||||||
|
|
||||||
while (from < to) {
|
while (pos < to) {
|
||||||
bh = affs_bread_ino(inode, bidx, 0);
|
bh = affs_bread_ino(inode, bidx, 0);
|
||||||
if (IS_ERR(bh))
|
if (IS_ERR(bh))
|
||||||
return PTR_ERR(bh);
|
return PTR_ERR(bh);
|
||||||
tmp = min(bsize - boff, to - from);
|
tmp = min(bsize - boff, to - pos);
|
||||||
BUG_ON(from + tmp > to || tmp > bsize);
|
BUG_ON(pos + tmp > to || tmp > bsize);
|
||||||
memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
|
memcpy(data + pos, AFFS_DATA(bh) + boff, tmp);
|
||||||
affs_brelse(bh);
|
affs_brelse(bh);
|
||||||
bidx++;
|
bidx++;
|
||||||
from += tmp;
|
pos += tmp;
|
||||||
boff = 0;
|
boff = 0;
|
||||||
}
|
}
|
||||||
flush_dcache_page(page);
|
flush_dcache_page(page);
|
||||||
|
@ -542,7 +545,7 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
|
||||||
u32 size, bsize;
|
u32 size, bsize;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
pr_debug("AFFS: extent_file(%u, %d)\n", (u32)inode->i_ino, newsize);
|
pr_debug("%s(%u, %d)\n", __func__, (u32)inode->i_ino, newsize);
|
||||||
bsize = AFFS_SB(sb)->s_data_blksize;
|
bsize = AFFS_SB(sb)->s_data_blksize;
|
||||||
bh = NULL;
|
bh = NULL;
|
||||||
size = AFFS_I(inode)->mmu_private;
|
size = AFFS_I(inode)->mmu_private;
|
||||||
|
@ -608,14 +611,14 @@ affs_readpage_ofs(struct file *file, struct page *page)
|
||||||
u32 to;
|
u32 to;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
pr_debug("AFFS: read_page(%u, %ld)\n", (u32)inode->i_ino, page->index);
|
pr_debug("%s(%u, %ld)\n", __func__, (u32)inode->i_ino, page->index);
|
||||||
to = PAGE_CACHE_SIZE;
|
to = PAGE_CACHE_SIZE;
|
||||||
if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {
|
if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {
|
||||||
to = inode->i_size & ~PAGE_CACHE_MASK;
|
to = inode->i_size & ~PAGE_CACHE_MASK;
|
||||||
memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
|
memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = affs_do_readpage_ofs(file, page, 0, to);
|
err = affs_do_readpage_ofs(page, to);
|
||||||
if (!err)
|
if (!err)
|
||||||
SetPageUptodate(page);
|
SetPageUptodate(page);
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
|
@ -631,7 +634,8 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
|
||||||
pgoff_t index;
|
pgoff_t index;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
|
pr_debug("%s(%u, %llu, %llu)\n", __func__, (u32)inode->i_ino,
|
||||||
|
(unsigned long long)pos, (unsigned long long)pos + len);
|
||||||
if (pos > AFFS_I(inode)->mmu_private) {
|
if (pos > AFFS_I(inode)->mmu_private) {
|
||||||
/* XXX: this probably leaves a too-big i_size in case of
|
/* XXX: this probably leaves a too-big i_size in case of
|
||||||
* failure. Should really be updating i_size at write_end time
|
* failure. Should really be updating i_size at write_end time
|
||||||
|
@ -651,7 +655,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* XXX: inefficient but safe in the face of short writes */
|
/* XXX: inefficient but safe in the face of short writes */
|
||||||
err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE);
|
err = affs_do_readpage_ofs(page, PAGE_CACHE_SIZE);
|
||||||
if (err) {
|
if (err) {
|
||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
|
@ -680,7 +684,9 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
|
||||||
* due to write_begin.
|
* due to write_begin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
|
pr_debug("%s(%u, %llu, %llu)\n",
|
||||||
|
__func__, (u32)inode->i_ino, (unsigned long long)pos,
|
||||||
|
(unsigned long long)pos + len);
|
||||||
bsize = AFFS_SB(sb)->s_data_blksize;
|
bsize = AFFS_SB(sb)->s_data_blksize;
|
||||||
data = page_address(page);
|
data = page_address(page);
|
||||||
|
|
||||||
|
@ -802,7 +808,7 @@ affs_free_prealloc(struct inode *inode)
|
||||||
{
|
{
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
|
|
||||||
pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);
|
pr_debug("free_prealloc(ino=%lu)\n", inode->i_ino);
|
||||||
|
|
||||||
while (AFFS_I(inode)->i_pa_cnt) {
|
while (AFFS_I(inode)->i_pa_cnt) {
|
||||||
AFFS_I(inode)->i_pa_cnt--;
|
AFFS_I(inode)->i_pa_cnt--;
|
||||||
|
@ -822,7 +828,7 @@ affs_truncate(struct inode *inode)
|
||||||
struct buffer_head *ext_bh;
|
struct buffer_head *ext_bh;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",
|
pr_debug("truncate(inode=%d, oldsize=%u, newsize=%u)\n",
|
||||||
(u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size);
|
(u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size);
|
||||||
|
|
||||||
last_blk = 0;
|
last_blk = 0;
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
|
||||||
if (!(inode->i_state & I_NEW))
|
if (!(inode->i_state & I_NEW))
|
||||||
return inode;
|
return inode;
|
||||||
|
|
||||||
pr_debug("AFFS: affs_iget(%lu)\n", inode->i_ino);
|
pr_debug("affs_iget(%lu)\n", inode->i_ino);
|
||||||
|
|
||||||
block = inode->i_ino;
|
block = inode->i_ino;
|
||||||
bh = affs_bread(sb, block);
|
bh = affs_bread(sb, block);
|
||||||
|
@ -175,7 +175,7 @@ affs_write_inode(struct inode *inode, struct writeback_control *wbc)
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
|
||||||
pr_debug("AFFS: write_inode(%lu)\n",inode->i_ino);
|
pr_debug("write_inode(%lu)\n", inode->i_ino);
|
||||||
|
|
||||||
if (!inode->i_nlink)
|
if (!inode->i_nlink)
|
||||||
// possibly free block
|
// possibly free block
|
||||||
|
@ -220,7 +220,7 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
|
||||||
struct inode *inode = dentry->d_inode;
|
struct inode *inode = dentry->d_inode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
|
pr_debug("notify_change(%lu,0x%x)\n", inode->i_ino, attr->ia_valid);
|
||||||
|
|
||||||
error = inode_change_ok(inode,attr);
|
error = inode_change_ok(inode,attr);
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -258,7 +258,8 @@ void
|
||||||
affs_evict_inode(struct inode *inode)
|
affs_evict_inode(struct inode *inode)
|
||||||
{
|
{
|
||||||
unsigned long cache_page;
|
unsigned long cache_page;
|
||||||
pr_debug("AFFS: evict_inode(ino=%lu, nlink=%u)\n", inode->i_ino, inode->i_nlink);
|
pr_debug("evict_inode(ino=%lu, nlink=%u)\n",
|
||||||
|
inode->i_ino, inode->i_nlink);
|
||||||
truncate_inode_pages_final(&inode->i_data);
|
truncate_inode_pages_final(&inode->i_data);
|
||||||
|
|
||||||
if (!inode->i_nlink) {
|
if (!inode->i_nlink) {
|
||||||
|
@ -271,7 +272,7 @@ affs_evict_inode(struct inode *inode)
|
||||||
affs_free_prealloc(inode);
|
affs_free_prealloc(inode);
|
||||||
cache_page = (unsigned long)AFFS_I(inode)->i_lc;
|
cache_page = (unsigned long)AFFS_I(inode)->i_lc;
|
||||||
if (cache_page) {
|
if (cache_page) {
|
||||||
pr_debug("AFFS: freeing ext cache\n");
|
pr_debug("freeing ext cache\n");
|
||||||
AFFS_I(inode)->i_lc = NULL;
|
AFFS_I(inode)->i_lc = NULL;
|
||||||
AFFS_I(inode)->i_ac = NULL;
|
AFFS_I(inode)->i_ac = NULL;
|
||||||
free_page(cache_page);
|
free_page(cache_page);
|
||||||
|
@ -350,7 +351,8 @@ affs_add_entry(struct inode *dir, struct inode *inode, struct dentry *dentry, s3
|
||||||
u32 block = 0;
|
u32 block = 0;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
pr_debug("AFFS: add_entry(dir=%u, inode=%u, \"%*s\", type=%d)\n", (u32)dir->i_ino,
|
pr_debug("%s(dir=%u, inode=%u, \"%*s\", type=%d)\n",
|
||||||
|
__func__, (u32)dir->i_ino,
|
||||||
(u32)inode->i_ino, (int)dentry->d_name.len, dentry->d_name.name, type);
|
(u32)inode->i_ino, (int)dentry->d_name.len, dentry->d_name.name, type);
|
||||||
|
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
|
|
|
@ -190,7 +190,8 @@ affs_find_entry(struct inode *dir, struct dentry *dentry)
|
||||||
toupper_t toupper = affs_get_toupper(sb);
|
toupper_t toupper = affs_get_toupper(sb);
|
||||||
u32 key;
|
u32 key;
|
||||||
|
|
||||||
pr_debug("AFFS: find_entry(\"%.*s\")\n", (int)dentry->d_name.len, dentry->d_name.name);
|
pr_debug("%s(\"%.*s\")\n",
|
||||||
|
__func__, (int)dentry->d_name.len, dentry->d_name.name);
|
||||||
|
|
||||||
bh = affs_bread(sb, dir->i_ino);
|
bh = affs_bread(sb, dir->i_ino);
|
||||||
if (!bh)
|
if (!bh)
|
||||||
|
@ -218,7 +219,8 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
|
|
||||||
pr_debug("AFFS: lookup(\"%.*s\")\n",(int)dentry->d_name.len,dentry->d_name.name);
|
pr_debug("%s(\"%.*s\")\n",
|
||||||
|
__func__, (int)dentry->d_name.len, dentry->d_name.name);
|
||||||
|
|
||||||
affs_lock_dir(dir);
|
affs_lock_dir(dir);
|
||||||
bh = affs_find_entry(dir, dentry);
|
bh = affs_find_entry(dir, dentry);
|
||||||
|
@ -248,9 +250,9 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
|
||||||
int
|
int
|
||||||
affs_unlink(struct inode *dir, struct dentry *dentry)
|
affs_unlink(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
pr_debug("AFFS: unlink(dir=%d, %lu \"%.*s\")\n", (u32)dir->i_ino,
|
pr_debug("%s(dir=%d, %lu \"%.*s\")\n",
|
||||||
dentry->d_inode->i_ino,
|
__func__, (u32)dir->i_ino, dentry->d_inode->i_ino,
|
||||||
(int)dentry->d_name.len, dentry->d_name.name);
|
(int)dentry->d_name.len, dentry->d_name.name);
|
||||||
|
|
||||||
return affs_remove_header(dentry);
|
return affs_remove_header(dentry);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +264,8 @@ affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
pr_debug("AFFS: create(%lu,\"%.*s\",0%ho)\n",dir->i_ino,(int)dentry->d_name.len,
|
pr_debug("%s(%lu,\"%.*s\",0%ho)\n",
|
||||||
|
__func__, dir->i_ino, (int)dentry->d_name.len,
|
||||||
dentry->d_name.name,mode);
|
dentry->d_name.name,mode);
|
||||||
|
|
||||||
inode = affs_new_inode(dir);
|
inode = affs_new_inode(dir);
|
||||||
|
@ -291,8 +294,9 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%ho)\n",dir->i_ino,
|
pr_debug("%s(%lu,\"%.*s\",0%ho)\n",
|
||||||
(int)dentry->d_name.len,dentry->d_name.name,mode);
|
__func__, dir->i_ino, (int)dentry->d_name.len,
|
||||||
|
dentry->d_name.name, mode);
|
||||||
|
|
||||||
inode = affs_new_inode(dir);
|
inode = affs_new_inode(dir);
|
||||||
if (!inode)
|
if (!inode)
|
||||||
|
@ -317,8 +321,8 @@ affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
int
|
int
|
||||||
affs_rmdir(struct inode *dir, struct dentry *dentry)
|
affs_rmdir(struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
pr_debug("AFFS: rmdir(dir=%u, %lu \"%.*s\")\n", (u32)dir->i_ino,
|
pr_debug("%s(dir=%u, %lu \"%.*s\")\n",
|
||||||
dentry->d_inode->i_ino,
|
__func__, (u32)dir->i_ino, dentry->d_inode->i_ino,
|
||||||
(int)dentry->d_name.len, dentry->d_name.name);
|
(int)dentry->d_name.len, dentry->d_name.name);
|
||||||
|
|
||||||
return affs_remove_header(dentry);
|
return affs_remove_header(dentry);
|
||||||
|
@ -334,8 +338,9 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
|
||||||
int i, maxlen, error;
|
int i, maxlen, error;
|
||||||
char c, lc;
|
char c, lc;
|
||||||
|
|
||||||
pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino,
|
pr_debug("%s(%lu,\"%.*s\" -> \"%s\")\n",
|
||||||
(int)dentry->d_name.len,dentry->d_name.name,symname);
|
__func__, dir->i_ino, (int)dentry->d_name.len,
|
||||||
|
dentry->d_name.name, symname);
|
||||||
|
|
||||||
maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
|
maxlen = AFFS_SB(sb)->s_hashsize * sizeof(u32) - 1;
|
||||||
inode = affs_new_inode(dir);
|
inode = affs_new_inode(dir);
|
||||||
|
@ -404,7 +409,8 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
|
||||||
{
|
{
|
||||||
struct inode *inode = old_dentry->d_inode;
|
struct inode *inode = old_dentry->d_inode;
|
||||||
|
|
||||||
pr_debug("AFFS: link(%u, %u, \"%.*s\")\n", (u32)inode->i_ino, (u32)dir->i_ino,
|
pr_debug("%s(%u, %u, \"%.*s\")\n",
|
||||||
|
__func__, (u32)inode->i_ino, (u32)dir->i_ino,
|
||||||
(int)dentry->d_name.len,dentry->d_name.name);
|
(int)dentry->d_name.len,dentry->d_name.name);
|
||||||
|
|
||||||
return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
|
return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
|
||||||
|
@ -418,9 +424,10 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry,
|
||||||
struct buffer_head *bh = NULL;
|
struct buffer_head *bh = NULL;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
pr_debug("AFFS: rename(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
|
pr_debug("%s(old=%u,\"%*s\" to new=%u,\"%*s\")\n",
|
||||||
(u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name,
|
__func__, (u32)old_dir->i_ino, (int)old_dentry->d_name.len,
|
||||||
(u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name);
|
old_dentry->d_name.name, (u32)new_dir->i_ino,
|
||||||
|
(int)new_dentry->d_name.len, new_dentry->d_name.name);
|
||||||
|
|
||||||
retval = affs_check_name(new_dentry->d_name.name,
|
retval = affs_check_name(new_dentry->d_name.name,
|
||||||
new_dentry->d_name.len,
|
new_dentry->d_name.len,
|
||||||
|
|
|
@ -46,7 +46,7 @@ static void
|
||||||
affs_put_super(struct super_block *sb)
|
affs_put_super(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct affs_sb_info *sbi = AFFS_SB(sb);
|
struct affs_sb_info *sbi = AFFS_SB(sb);
|
||||||
pr_debug("AFFS: put_super()\n");
|
pr_debug("%s()\n", __func__);
|
||||||
|
|
||||||
cancel_delayed_work_sync(&sbi->sb_work);
|
cancel_delayed_work_sync(&sbi->sb_work);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
|
||||||
return 0;
|
return 0;
|
||||||
if (n != 512 && n != 1024 && n != 2048
|
if (n != 512 && n != 1024 && n != 2048
|
||||||
&& n != 4096) {
|
&& n != 4096) {
|
||||||
printk ("AFFS: Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
|
pr_warn("Invalid blocksize (512, 1024, 2048, 4096 allowed)\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*blocksize = n;
|
*blocksize = n;
|
||||||
|
@ -285,8 +285,8 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved,
|
||||||
/* Silently ignore the quota options */
|
/* Silently ignore the quota options */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk("AFFS: Unrecognized mount option \"%s\" "
|
pr_warn("Unrecognized mount option \"%s\" or missing value\n",
|
||||||
"or missing value\n", p);
|
p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,7 +319,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
|
|
||||||
save_mount_options(sb, data);
|
save_mount_options(sb, data);
|
||||||
|
|
||||||
pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
|
pr_debug("read_super(%s)\n", data ? (const char *)data : "no options");
|
||||||
|
|
||||||
sb->s_magic = AFFS_SUPER_MAGIC;
|
sb->s_magic = AFFS_SUPER_MAGIC;
|
||||||
sb->s_op = &affs_sops;
|
sb->s_op = &affs_sops;
|
||||||
|
@ -339,7 +339,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
|
if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
|
||||||
&blocksize,&sbi->s_prefix,
|
&blocksize,&sbi->s_prefix,
|
||||||
sbi->s_volume, &mount_flags)) {
|
sbi->s_volume, &mount_flags)) {
|
||||||
printk(KERN_ERR "AFFS: Error parsing options\n");
|
pr_err("Error parsing options\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/* N.B. after this point s_prefix must be released */
|
/* N.B. after this point s_prefix must be released */
|
||||||
|
@ -356,7 +356,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size = sb->s_bdev->bd_inode->i_size >> 9;
|
size = sb->s_bdev->bd_inode->i_size >> 9;
|
||||||
pr_debug("AFFS: initial blocksize=%d, #blocks=%d\n", 512, size);
|
pr_debug("initial blocksize=%d, #blocks=%d\n", 512, size);
|
||||||
|
|
||||||
affs_set_blocksize(sb, PAGE_SIZE);
|
affs_set_blocksize(sb, PAGE_SIZE);
|
||||||
/* Try to find root block. Its location depends on the block size. */
|
/* Try to find root block. Its location depends on the block size. */
|
||||||
|
@ -371,7 +371,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
sbi->s_root_block = root_block;
|
sbi->s_root_block = root_block;
|
||||||
if (root_block < 0)
|
if (root_block < 0)
|
||||||
sbi->s_root_block = (reserved + size - 1) / 2;
|
sbi->s_root_block = (reserved + size - 1) / 2;
|
||||||
pr_debug("AFFS: setting blocksize to %d\n", blocksize);
|
pr_debug("setting blocksize to %d\n", blocksize);
|
||||||
affs_set_blocksize(sb, blocksize);
|
affs_set_blocksize(sb, blocksize);
|
||||||
sbi->s_partition_size = size;
|
sbi->s_partition_size = size;
|
||||||
|
|
||||||
|
@ -386,7 +386,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
* block behind the calculated one. So we check this one, too.
|
* block behind the calculated one. So we check this one, too.
|
||||||
*/
|
*/
|
||||||
for (num_bm = 0; num_bm < 2; num_bm++) {
|
for (num_bm = 0; num_bm < 2; num_bm++) {
|
||||||
pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, "
|
pr_debug("Dev %s, trying root=%u, bs=%d, "
|
||||||
"size=%d, reserved=%d\n",
|
"size=%d, reserved=%d\n",
|
||||||
sb->s_id,
|
sb->s_id,
|
||||||
sbi->s_root_block + num_bm,
|
sbi->s_root_block + num_bm,
|
||||||
|
@ -407,8 +407,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!silent)
|
if (!silent)
|
||||||
printk(KERN_ERR "AFFS: No valid root block on device %s\n",
|
pr_err("No valid root block on device %s\n", sb->s_id);
|
||||||
sb->s_id);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* N.B. after this point bh must be released */
|
/* N.B. after this point bh must be released */
|
||||||
|
@ -420,7 +419,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
/* Find out which kind of FS we have */
|
/* Find out which kind of FS we have */
|
||||||
boot_bh = sb_bread(sb, 0);
|
boot_bh = sb_bread(sb, 0);
|
||||||
if (!boot_bh) {
|
if (!boot_bh) {
|
||||||
printk(KERN_ERR "AFFS: Cannot read boot block\n");
|
pr_err("Cannot read boot block\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
memcpy(sig, boot_bh->b_data, 4);
|
memcpy(sig, boot_bh->b_data, 4);
|
||||||
|
@ -433,8 +432,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
*/
|
*/
|
||||||
if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
|
if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS
|
||||||
|| chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
|
|| chksum == MUFS_DCOFS) && !(sb->s_flags & MS_RDONLY)) {
|
||||||
printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n",
|
pr_notice("Dircache FS - mounting %s read only\n", sb->s_id);
|
||||||
sb->s_id);
|
|
||||||
sb->s_flags |= MS_RDONLY;
|
sb->s_flags |= MS_RDONLY;
|
||||||
}
|
}
|
||||||
switch (chksum) {
|
switch (chksum) {
|
||||||
|
@ -468,14 +466,14 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
sb->s_flags |= MS_NOEXEC;
|
sb->s_flags |= MS_NOEXEC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n",
|
pr_err("Unknown filesystem on device %s: %08X\n",
|
||||||
sb->s_id, chksum);
|
sb->s_id, chksum);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount_flags & SF_VERBOSE) {
|
if (mount_flags & SF_VERBOSE) {
|
||||||
u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
|
u8 len = AFFS_ROOT_TAIL(sb, root_bh)->disk_name[0];
|
||||||
printk(KERN_NOTICE "AFFS: Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
|
pr_notice("Mounting volume \"%.*s\": Type=%.3s\\%c, Blocksize=%d\n",
|
||||||
len > 31 ? 31 : len,
|
len > 31 ? 31 : len,
|
||||||
AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
|
AFFS_ROOT_TAIL(sb, root_bh)->disk_name + 1,
|
||||||
sig, sig[3] + '0', blocksize);
|
sig, sig[3] + '0', blocksize);
|
||||||
|
@ -506,11 +504,11 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
|
|
||||||
sb->s_root = d_make_root(root_inode);
|
sb->s_root = d_make_root(root_inode);
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
printk(KERN_ERR "AFFS: Get root inode failed\n");
|
pr_err("AFFS: Get root inode failed\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("AFFS: s_flags=%lX\n",sb->s_flags);
|
pr_debug("s_flags=%lX\n", sb->s_flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +528,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
|
||||||
char volume[32];
|
char volume[32];
|
||||||
char *prefix = NULL;
|
char *prefix = NULL;
|
||||||
|
|
||||||
pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
|
pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data);
|
||||||
|
|
||||||
sync_filesystem(sb);
|
sync_filesystem(sb);
|
||||||
*flags |= MS_NODIRATIME;
|
*flags |= MS_NODIRATIME;
|
||||||
|
@ -578,8 +576,9 @@ affs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||||
int free;
|
int free;
|
||||||
u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
|
u64 id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||||
|
|
||||||
pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size,
|
pr_debug("%s() partsize=%d, reserved=%d\n",
|
||||||
AFFS_SB(sb)->s_reserved);
|
__func__, AFFS_SB(sb)->s_partition_size,
|
||||||
|
AFFS_SB(sb)->s_reserved);
|
||||||
|
|
||||||
free = affs_count_free_blocks(sb);
|
free = affs_count_free_blocks(sb);
|
||||||
buf->f_type = AFFS_SUPER_MAGIC;
|
buf->f_type = AFFS_SUPER_MAGIC;
|
||||||
|
|
|
@ -21,7 +21,7 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
|
||||||
char c;
|
char c;
|
||||||
char lc;
|
char lc;
|
||||||
|
|
||||||
pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
|
pr_debug("follow_link(ino=%lu)\n", inode->i_ino);
|
||||||
|
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
bh = affs_bread(inode->i_sb, inode->i_ino);
|
bh = affs_bread(inode->i_sb, inode->i_ino);
|
||||||
|
|
|
@ -318,7 +318,7 @@ befs_btree_find(struct super_block *sb, befs_data_stream * ds,
|
||||||
* befs_find_key - Search for a key within a node
|
* befs_find_key - Search for a key within a node
|
||||||
* @sb: Filesystem superblock
|
* @sb: Filesystem superblock
|
||||||
* @node: Node to find the key within
|
* @node: Node to find the key within
|
||||||
* @key: Keystring to search for
|
* @findkey: Keystring to search for
|
||||||
* @value: If key is found, the value stored with the key is put here
|
* @value: If key is found, the value stored with the key is put here
|
||||||
*
|
*
|
||||||
* finds exact match if one exists, and returns BEFS_BT_MATCH
|
* finds exact match if one exists, and returns BEFS_BT_MATCH
|
||||||
|
@ -405,7 +405,7 @@ befs_find_key(struct super_block *sb, befs_btree_node * node,
|
||||||
* Heres how it works: Key_no is the index of the key/value pair to
|
* Heres how it works: Key_no is the index of the key/value pair to
|
||||||
* return in keybuf/value.
|
* return in keybuf/value.
|
||||||
* Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
|
* Bufsize is the size of keybuf (BEFS_NAME_LEN+1 is a good size). Keysize is
|
||||||
* the number of charecters in the key (just a convenience).
|
* the number of characters in the key (just a convenience).
|
||||||
*
|
*
|
||||||
* Algorithm:
|
* Algorithm:
|
||||||
* Get the first leafnode of the tree. See if the requested key is in that
|
* Get the first leafnode of the tree. See if the requested key is in that
|
||||||
|
@ -502,12 +502,11 @@ befs_btree_read(struct super_block *sb, befs_data_stream * ds,
|
||||||
"for key of size %d", __func__, bufsize, keylen);
|
"for key of size %d", __func__, bufsize, keylen);
|
||||||
brelse(this_node->bh);
|
brelse(this_node->bh);
|
||||||
goto error_alloc;
|
goto error_alloc;
|
||||||
};
|
}
|
||||||
|
|
||||||
strncpy(keybuf, keystart, keylen);
|
strlcpy(keybuf, keystart, keylen + 1);
|
||||||
*value = fs64_to_cpu(sb, valarray[cur_key]);
|
*value = fs64_to_cpu(sb, valarray[cur_key]);
|
||||||
*keysize = keylen;
|
*keysize = keylen;
|
||||||
keybuf[keylen] = '\0';
|
|
||||||
|
|
||||||
befs_debug(sb, "Read [%llu,%d]: Key \"%.*s\", Value %llu", node_off,
|
befs_debug(sb, "Read [%llu,%d]: Key \"%.*s\", Value %llu", node_off,
|
||||||
cur_key, keylen, keybuf, *value);
|
cur_key, keylen, keybuf, *value);
|
||||||
|
@ -707,7 +706,7 @@ befs_bt_get_key(struct super_block *sb, befs_btree_node * node,
|
||||||
* @key1: pointer to the first key to be compared
|
* @key1: pointer to the first key to be compared
|
||||||
* @keylen1: length in bytes of key1
|
* @keylen1: length in bytes of key1
|
||||||
* @key2: pointer to the second key to be compared
|
* @key2: pointer to the second key to be compared
|
||||||
* @kelen2: length in bytes of key2
|
* @keylen2: length in bytes of key2
|
||||||
*
|
*
|
||||||
* Returns 0 if @key1 and @key2 are equal.
|
* Returns 0 if @key1 and @key2 are equal.
|
||||||
* Returns >0 if @key1 is greater.
|
* Returns >0 if @key1 is greater.
|
||||||
|
|
|
@ -116,7 +116,7 @@ befs_fblock2brun(struct super_block *sb, befs_data_stream * data,
|
||||||
* befs_read_lsmylink - read long symlink from datastream.
|
* befs_read_lsmylink - read long symlink from datastream.
|
||||||
* @sb: Filesystem superblock
|
* @sb: Filesystem superblock
|
||||||
* @ds: Datastrem to read from
|
* @ds: Datastrem to read from
|
||||||
* @buf: Buffer in which to place long symlink data
|
* @buff: Buffer in which to place long symlink data
|
||||||
* @len: Length of the long symlink in bytes
|
* @len: Length of the long symlink in bytes
|
||||||
*
|
*
|
||||||
* Returns the number of bytes read
|
* Returns the number of bytes read
|
||||||
|
|
|
@ -133,14 +133,6 @@ befs_get_block(struct inode *inode, sector_t block,
|
||||||
|
|
||||||
befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
|
befs_debug(sb, "---> befs_get_block() for inode %lu, block %ld",
|
||||||
(unsigned long)inode->i_ino, (long)block);
|
(unsigned long)inode->i_ino, (long)block);
|
||||||
|
|
||||||
if (block < 0) {
|
|
||||||
befs_error(sb, "befs_get_block() was asked for a block "
|
|
||||||
"number less than zero: block %ld in inode %lu",
|
|
||||||
(long)block, (unsigned long)inode->i_ino);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (create) {
|
if (create) {
|
||||||
befs_error(sb, "befs_get_block() was asked to write to "
|
befs_error(sb, "befs_get_block() was asked to write to "
|
||||||
"block %ld in inode %lu", (long)block,
|
"block %ld in inode %lu", (long)block,
|
||||||
|
@ -396,9 +388,8 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
|
||||||
if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
|
if (S_ISLNK(inode->i_mode) && !(befs_ino->i_flags & BEFS_LONG_SYMLINK)){
|
||||||
inode->i_size = 0;
|
inode->i_size = 0;
|
||||||
inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
|
inode->i_blocks = befs_sb->block_size / VFS_BLOCK_SIZE;
|
||||||
strncpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
|
strlcpy(befs_ino->i_data.symlink, raw_inode->data.symlink,
|
||||||
BEFS_SYMLINK_LEN - 1);
|
BEFS_SYMLINK_LEN);
|
||||||
befs_ino->i_data.symlink[BEFS_SYMLINK_LEN - 1] = '\0';
|
|
||||||
} else {
|
} else {
|
||||||
int num_blks;
|
int num_blks;
|
||||||
|
|
||||||
|
@ -591,21 +582,21 @@ befs_utf2nls(struct super_block *sb, const char *in,
|
||||||
/**
|
/**
|
||||||
* befs_nls2utf - Convert NLS string to utf8 encodeing
|
* befs_nls2utf - Convert NLS string to utf8 encodeing
|
||||||
* @sb: Superblock
|
* @sb: Superblock
|
||||||
* @src: Input string buffer in NLS format
|
* @in: Input string buffer in NLS format
|
||||||
* @srclen: Length of input string in bytes
|
* @in_len: Length of input string in bytes
|
||||||
* @dest: The output string in UTF-8 format
|
* @out: The output string in UTF-8 format
|
||||||
* @destlen: Length of the output buffer
|
* @out_len: Length of the output buffer
|
||||||
*
|
*
|
||||||
* Converts input string @src, which is in the format of the loaded NLS map,
|
* Converts input string @in, which is in the format of the loaded NLS map,
|
||||||
* into a utf8 string.
|
* into a utf8 string.
|
||||||
*
|
*
|
||||||
* The destination string @dest is allocated by this function and the caller is
|
* The destination string @out is allocated by this function and the caller is
|
||||||
* responsible for freeing it with kfree()
|
* responsible for freeing it with kfree()
|
||||||
*
|
*
|
||||||
* On return, *@destlen is the length of @dest in bytes.
|
* On return, *@out_len is the length of @out in bytes.
|
||||||
*
|
*
|
||||||
* On success, the return value is the number of utf8 characters written to
|
* On success, the return value is the number of utf8 characters written to
|
||||||
* the output buffer @dest.
|
* the output buffer @out.
|
||||||
*
|
*
|
||||||
* On Failure, a negative number coresponding to the error code is returned.
|
* On Failure, a negative number coresponding to the error code is returned.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -50,18 +50,18 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
|
||||||
cache->brun_percent < 100);
|
cache->brun_percent < 100);
|
||||||
|
|
||||||
if (*args) {
|
if (*args) {
|
||||||
kerror("'bind' command doesn't take an argument");
|
pr_err("'bind' command doesn't take an argument");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cache->rootdirname) {
|
if (!cache->rootdirname) {
|
||||||
kerror("No cache directory specified");
|
pr_err("No cache directory specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't permit already bound caches to be re-bound */
|
/* don't permit already bound caches to be re-bound */
|
||||||
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
kerror("Cache already bound");
|
pr_err("Cache already bound");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +228,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
|
||||||
set_bit(CACHEFILES_READY, &cache->flags);
|
set_bit(CACHEFILES_READY, &cache->flags);
|
||||||
dput(root);
|
dput(root);
|
||||||
|
|
||||||
printk(KERN_INFO "CacheFiles:"
|
pr_info("File cache on %s registered\n", cache->cache.identifier);
|
||||||
" File cache on %s registered\n",
|
|
||||||
cache->cache.identifier);
|
|
||||||
|
|
||||||
/* check how much space the cache has */
|
/* check how much space the cache has */
|
||||||
cachefiles_has_space(cache, 0, 0);
|
cachefiles_has_space(cache, 0, 0);
|
||||||
|
@ -250,7 +248,7 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
|
||||||
kmem_cache_free(cachefiles_object_jar, fsdef);
|
kmem_cache_free(cachefiles_object_jar, fsdef);
|
||||||
error_root_object:
|
error_root_object:
|
||||||
cachefiles_end_secure(cache, saved_cred);
|
cachefiles_end_secure(cache, saved_cred);
|
||||||
kerror("Failed to register: %d", ret);
|
pr_err("Failed to register: %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,9 +260,8 @@ void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
|
||||||
_enter("");
|
_enter("");
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
printk(KERN_INFO "CacheFiles:"
|
pr_info("File cache on %s unregistering\n",
|
||||||
" File cache on %s unregistering\n",
|
cache->cache.identifier);
|
||||||
cache->cache.identifier);
|
|
||||||
|
|
||||||
fscache_withdraw_cache(&cache->cache);
|
fscache_withdraw_cache(&cache->cache);
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,8 +315,7 @@ static unsigned int cachefiles_daemon_poll(struct file *file,
|
||||||
static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
|
static int cachefiles_daemon_range_error(struct cachefiles_cache *cache,
|
||||||
char *args)
|
char *args)
|
||||||
{
|
{
|
||||||
kerror("Free space limits must be in range"
|
pr_err("Free space limits must be in range 0%%<=stop<cull<run<100%%");
|
||||||
" 0%%<=stop<cull<run<100%%");
|
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -476,12 +475,12 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
kerror("Empty directory specified");
|
pr_err("Empty directory specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->rootdirname) {
|
if (cache->rootdirname) {
|
||||||
kerror("Second cache directory specified");
|
pr_err("Second cache directory specified");
|
||||||
return -EEXIST;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,12 +503,12 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
kerror("Empty security context specified");
|
pr_err("Empty security context specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cache->secctx) {
|
if (cache->secctx) {
|
||||||
kerror("Second security context specified");
|
pr_err("Second security context specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,7 +531,7 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args)
|
||||||
_enter(",%s", args);
|
_enter(",%s", args);
|
||||||
|
|
||||||
if (!*args) {
|
if (!*args) {
|
||||||
kerror("Empty tag specified");
|
pr_err("Empty tag specified");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,12 +562,12 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
|
||||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
kerror("cull applied to unready cache");
|
pr_err("cull applied to unready cache");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||||
kerror("cull applied to dead cache");
|
pr_err("cull applied to dead cache");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,11 +587,11 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args)
|
||||||
|
|
||||||
notdir:
|
notdir:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
kerror("cull command requires dirfd to be a directory");
|
pr_err("cull command requires dirfd to be a directory");
|
||||||
return -ENOTDIR;
|
return -ENOTDIR;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
kerror("cull command requires dirfd and filename");
|
pr_err("cull command requires dirfd and filename");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,7 +614,7 @@ static int cachefiles_daemon_debug(struct cachefiles_cache *cache, char *args)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
kerror("debug command requires mask");
|
pr_err("debug command requires mask");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,12 +634,12 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
||||||
goto inval;
|
goto inval;
|
||||||
|
|
||||||
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
if (!test_bit(CACHEFILES_READY, &cache->flags)) {
|
||||||
kerror("inuse applied to unready cache");
|
pr_err("inuse applied to unready cache");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
if (test_bit(CACHEFILES_DEAD, &cache->flags)) {
|
||||||
kerror("inuse applied to dead cache");
|
pr_err("inuse applied to dead cache");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,11 +659,11 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args)
|
||||||
|
|
||||||
notdir:
|
notdir:
|
||||||
path_put(&path);
|
path_put(&path);
|
||||||
kerror("inuse command requires dirfd to be a directory");
|
pr_err("inuse command requires dirfd to be a directory");
|
||||||
return -ENOTDIR;
|
return -ENOTDIR;
|
||||||
|
|
||||||
inval:
|
inval:
|
||||||
kerror("inuse command requires dirfd and filename");
|
pr_err("inuse command requires dirfd and filename");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,8 +146,7 @@ static int cachefiles_lookup_object(struct fscache_object *_object)
|
||||||
|
|
||||||
if (ret < 0 && ret != -ETIMEDOUT) {
|
if (ret < 0 && ret != -ETIMEDOUT) {
|
||||||
if (ret != -ENOBUFS)
|
if (ret != -ENOBUFS)
|
||||||
printk(KERN_WARNING
|
pr_warn("Lookup failed error %d\n", ret);
|
||||||
"CacheFiles: Lookup failed error %d\n", ret);
|
|
||||||
fscache_object_lookup_error(&object->fscache);
|
fscache_object_lookup_error(&object->fscache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,13 @@
|
||||||
* 2 of the Licence, or (at your option) any later version.
|
* 2 of the Licence, or (at your option) any later version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef pr_fmt
|
||||||
|
#undef pr_fmt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "CacheFiles: " fmt
|
||||||
|
|
||||||
|
|
||||||
#include <linux/fscache-cache.h>
|
#include <linux/fscache-cache.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
@ -245,11 +252,10 @@ extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache,
|
||||||
/*
|
/*
|
||||||
* error handling
|
* error handling
|
||||||
*/
|
*/
|
||||||
#define kerror(FMT, ...) printk(KERN_ERR "CacheFiles: "FMT"\n", ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#define cachefiles_io_error(___cache, FMT, ...) \
|
#define cachefiles_io_error(___cache, FMT, ...) \
|
||||||
do { \
|
do { \
|
||||||
kerror("I/O Error: " FMT, ##__VA_ARGS__); \
|
pr_err("I/O Error: " FMT, ##__VA_ARGS__); \
|
||||||
fscache_io_error(&(___cache)->cache); \
|
fscache_io_error(&(___cache)->cache); \
|
||||||
set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
|
set_bit(CACHEFILES_DEAD, &(___cache)->flags); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -310,8 +316,8 @@ do { \
|
||||||
#define ASSERT(X) \
|
#define ASSERT(X) \
|
||||||
do { \
|
do { \
|
||||||
if (unlikely(!(X))) { \
|
if (unlikely(!(X))) { \
|
||||||
printk(KERN_ERR "\n"); \
|
pr_err("\n"); \
|
||||||
printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
|
pr_err("Assertion failed\n"); \
|
||||||
BUG(); \
|
BUG(); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -319,9 +325,9 @@ do { \
|
||||||
#define ASSERTCMP(X, OP, Y) \
|
#define ASSERTCMP(X, OP, Y) \
|
||||||
do { \
|
do { \
|
||||||
if (unlikely(!((X) OP (Y)))) { \
|
if (unlikely(!((X) OP (Y)))) { \
|
||||||
printk(KERN_ERR "\n"); \
|
pr_err("\n"); \
|
||||||
printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
|
pr_err("Assertion failed\n"); \
|
||||||
printk(KERN_ERR "%lx " #OP " %lx is false\n", \
|
pr_err("%lx " #OP " %lx is false\n", \
|
||||||
(unsigned long)(X), (unsigned long)(Y)); \
|
(unsigned long)(X), (unsigned long)(Y)); \
|
||||||
BUG(); \
|
BUG(); \
|
||||||
} \
|
} \
|
||||||
|
@ -330,8 +336,8 @@ do { \
|
||||||
#define ASSERTIF(C, X) \
|
#define ASSERTIF(C, X) \
|
||||||
do { \
|
do { \
|
||||||
if (unlikely((C) && !(X))) { \
|
if (unlikely((C) && !(X))) { \
|
||||||
printk(KERN_ERR "\n"); \
|
pr_err("\n"); \
|
||||||
printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
|
pr_err("Assertion failed\n"); \
|
||||||
BUG(); \
|
BUG(); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -339,9 +345,9 @@ do { \
|
||||||
#define ASSERTIFCMP(C, X, OP, Y) \
|
#define ASSERTIFCMP(C, X, OP, Y) \
|
||||||
do { \
|
do { \
|
||||||
if (unlikely((C) && !((X) OP (Y)))) { \
|
if (unlikely((C) && !((X) OP (Y)))) { \
|
||||||
printk(KERN_ERR "\n"); \
|
pr_err("\n"); \
|
||||||
printk(KERN_ERR "CacheFiles: Assertion failed\n"); \
|
pr_err("Assertion failed\n"); \
|
||||||
printk(KERN_ERR "%lx " #OP " %lx is false\n", \
|
pr_err("%lx " #OP " %lx is false\n", \
|
||||||
(unsigned long)(X), (unsigned long)(Y)); \
|
(unsigned long)(X), (unsigned long)(Y)); \
|
||||||
BUG(); \
|
BUG(); \
|
||||||
} \
|
} \
|
||||||
|
|
|
@ -68,8 +68,7 @@ static int __init cachefiles_init(void)
|
||||||
SLAB_HWCACHE_ALIGN,
|
SLAB_HWCACHE_ALIGN,
|
||||||
cachefiles_object_init_once);
|
cachefiles_object_init_once);
|
||||||
if (!cachefiles_object_jar) {
|
if (!cachefiles_object_jar) {
|
||||||
printk(KERN_NOTICE
|
pr_notice("Failed to allocate an object jar\n");
|
||||||
"CacheFiles: Failed to allocate an object jar\n");
|
|
||||||
goto error_object_jar;
|
goto error_object_jar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +76,7 @@ static int __init cachefiles_init(void)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_proc;
|
goto error_proc;
|
||||||
|
|
||||||
printk(KERN_INFO "CacheFiles: Loaded\n");
|
pr_info("Loaded\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_proc:
|
error_proc:
|
||||||
|
@ -85,7 +84,7 @@ static int __init cachefiles_init(void)
|
||||||
error_object_jar:
|
error_object_jar:
|
||||||
misc_deregister(&cachefiles_dev);
|
misc_deregister(&cachefiles_dev);
|
||||||
error_dev:
|
error_dev:
|
||||||
kerror("failed to register: %d", ret);
|
pr_err("failed to register: %d", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +95,7 @@ fs_initcall(cachefiles_init);
|
||||||
*/
|
*/
|
||||||
static void __exit cachefiles_exit(void)
|
static void __exit cachefiles_exit(void)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO "CacheFiles: Unloading\n");
|
pr_info("Unloading\n");
|
||||||
|
|
||||||
cachefiles_proc_cleanup();
|
cachefiles_proc_cleanup();
|
||||||
kmem_cache_destroy(cachefiles_object_jar);
|
kmem_cache_destroy(cachefiles_object_jar);
|
||||||
|
|
|
@ -35,22 +35,21 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
|
||||||
struct fscache_cookie *cookie;
|
struct fscache_cookie *cookie;
|
||||||
unsigned keylen, loop;
|
unsigned keylen, loop;
|
||||||
|
|
||||||
printk(KERN_ERR "%sobject: OBJ%x\n",
|
pr_err("%sobject: OBJ%x\n", prefix, object->fscache.debug_id);
|
||||||
prefix, object->fscache.debug_id);
|
pr_err("%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
|
||||||
printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
|
|
||||||
prefix, object->fscache.state->name,
|
prefix, object->fscache.state->name,
|
||||||
object->fscache.flags, work_busy(&object->fscache.work),
|
object->fscache.flags, work_busy(&object->fscache.work),
|
||||||
object->fscache.events, object->fscache.event_mask);
|
object->fscache.events, object->fscache.event_mask);
|
||||||
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
|
pr_err("%sops=%u inp=%u exc=%u\n",
|
||||||
prefix, object->fscache.n_ops, object->fscache.n_in_progress,
|
prefix, object->fscache.n_ops, object->fscache.n_in_progress,
|
||||||
object->fscache.n_exclusive);
|
object->fscache.n_exclusive);
|
||||||
printk(KERN_ERR "%sparent=%p\n",
|
pr_err("%sparent=%p\n",
|
||||||
prefix, object->fscache.parent);
|
prefix, object->fscache.parent);
|
||||||
|
|
||||||
spin_lock(&object->fscache.lock);
|
spin_lock(&object->fscache.lock);
|
||||||
cookie = object->fscache.cookie;
|
cookie = object->fscache.cookie;
|
||||||
if (cookie) {
|
if (cookie) {
|
||||||
printk(KERN_ERR "%scookie=%p [pr=%p nd=%p fl=%lx]\n",
|
pr_err("%scookie=%p [pr=%p nd=%p fl=%lx]\n",
|
||||||
prefix,
|
prefix,
|
||||||
object->fscache.cookie,
|
object->fscache.cookie,
|
||||||
object->fscache.cookie->parent,
|
object->fscache.cookie->parent,
|
||||||
|
@ -62,16 +61,16 @@ void __cachefiles_printk_object(struct cachefiles_object *object,
|
||||||
else
|
else
|
||||||
keylen = 0;
|
keylen = 0;
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_ERR "%scookie=NULL\n", prefix);
|
pr_err("%scookie=NULL\n", prefix);
|
||||||
keylen = 0;
|
keylen = 0;
|
||||||
}
|
}
|
||||||
spin_unlock(&object->fscache.lock);
|
spin_unlock(&object->fscache.lock);
|
||||||
|
|
||||||
if (keylen) {
|
if (keylen) {
|
||||||
printk(KERN_ERR "%skey=[%u] '", prefix, keylen);
|
pr_err("%skey=[%u] '", prefix, keylen);
|
||||||
for (loop = 0; loop < keylen; loop++)
|
for (loop = 0; loop < keylen; loop++)
|
||||||
printk("%02x", keybuf[loop]);
|
pr_cont("%02x", keybuf[loop]);
|
||||||
printk("'\n");
|
pr_cont("'\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +130,11 @@ static void cachefiles_mark_object_buried(struct cachefiles_cache *cache,
|
||||||
dentry);
|
dentry);
|
||||||
|
|
||||||
if (fscache_object_is_live(&object->fscache)) {
|
if (fscache_object_is_live(&object->fscache)) {
|
||||||
printk(KERN_ERR "\n");
|
pr_err("\n");
|
||||||
printk(KERN_ERR "CacheFiles: Error:"
|
pr_err("Error: Can't preemptively bury live object\n");
|
||||||
" Can't preemptively bury live object\n");
|
|
||||||
cachefiles_printk_object(object, NULL);
|
cachefiles_printk_object(object, NULL);
|
||||||
} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
|
} else if (test_and_set_bit(CACHEFILES_OBJECT_BURIED, &object->flags)) {
|
||||||
printk(KERN_ERR "CacheFiles: Error:"
|
pr_err("Error: Object already preemptively buried\n");
|
||||||
" Object already preemptively buried\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
write_unlock(&cache->active_lock);
|
write_unlock(&cache->active_lock);
|
||||||
|
@ -160,7 +157,7 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
|
||||||
write_lock(&cache->active_lock);
|
write_lock(&cache->active_lock);
|
||||||
|
|
||||||
if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
|
if (test_and_set_bit(CACHEFILES_OBJECT_ACTIVE, &object->flags)) {
|
||||||
printk(KERN_ERR "CacheFiles: Error: Object already active\n");
|
pr_err("Error: Object already active\n");
|
||||||
cachefiles_printk_object(object, NULL);
|
cachefiles_printk_object(object, NULL);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
@ -193,9 +190,8 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
|
||||||
* need to wait for it to be destroyed */
|
* need to wait for it to be destroyed */
|
||||||
wait_for_old_object:
|
wait_for_old_object:
|
||||||
if (fscache_object_is_live(&object->fscache)) {
|
if (fscache_object_is_live(&object->fscache)) {
|
||||||
printk(KERN_ERR "\n");
|
pr_err("\n");
|
||||||
printk(KERN_ERR "CacheFiles: Error:"
|
pr_err("Error: Unexpected object collision\n");
|
||||||
" Unexpected object collision\n");
|
|
||||||
cachefiles_printk_object(object, xobject);
|
cachefiles_printk_object(object, xobject);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
@ -241,9 +237,8 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout <= 0) {
|
if (timeout <= 0) {
|
||||||
printk(KERN_ERR "\n");
|
pr_err("\n");
|
||||||
printk(KERN_ERR "CacheFiles: Error: Overlong"
|
pr_err("Error: Overlong wait for old active object to go away\n");
|
||||||
" wait for old active object to go away\n");
|
|
||||||
cachefiles_printk_object(object, xobject);
|
cachefiles_printk_object(object, xobject);
|
||||||
goto requeue;
|
goto requeue;
|
||||||
}
|
}
|
||||||
|
@ -548,7 +543,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
next, next->d_inode, next->d_inode->i_ino);
|
next, next->d_inode, next->d_inode->i_ino);
|
||||||
|
|
||||||
} else if (!S_ISDIR(next->d_inode->i_mode)) {
|
} else if (!S_ISDIR(next->d_inode->i_mode)) {
|
||||||
kerror("inode %lu is not a directory",
|
pr_err("inode %lu is not a directory",
|
||||||
next->d_inode->i_ino);
|
next->d_inode->i_ino);
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -579,7 +574,7 @@ int cachefiles_walk_to_object(struct cachefiles_object *parent,
|
||||||
} else if (!S_ISDIR(next->d_inode->i_mode) &&
|
} else if (!S_ISDIR(next->d_inode->i_mode) &&
|
||||||
!S_ISREG(next->d_inode->i_mode)
|
!S_ISREG(next->d_inode->i_mode)
|
||||||
) {
|
) {
|
||||||
kerror("inode %lu is not a file or directory",
|
pr_err("inode %lu is not a file or directory",
|
||||||
next->d_inode->i_ino);
|
next->d_inode->i_ino);
|
||||||
ret = -ENOBUFS;
|
ret = -ENOBUFS;
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -773,7 +768,7 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
ASSERT(subdir->d_inode);
|
ASSERT(subdir->d_inode);
|
||||||
|
|
||||||
if (!S_ISDIR(subdir->d_inode->i_mode)) {
|
if (!S_ISDIR(subdir->d_inode->i_mode)) {
|
||||||
kerror("%s is not a directory", dirname);
|
pr_err("%s is not a directory", dirname);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto check_error;
|
goto check_error;
|
||||||
}
|
}
|
||||||
|
@ -800,13 +795,13 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache,
|
||||||
mkdir_error:
|
mkdir_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
dput(subdir);
|
dput(subdir);
|
||||||
kerror("mkdir %s failed with error %d", dirname, ret);
|
pr_err("mkdir %s failed with error %d", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
lookup_error:
|
lookup_error:
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
ret = PTR_ERR(subdir);
|
ret = PTR_ERR(subdir);
|
||||||
kerror("Lookup %s failed with error %d", dirname, ret);
|
pr_err("Lookup %s failed with error %d", dirname, ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
nomem_d_alloc:
|
nomem_d_alloc:
|
||||||
|
@ -896,7 +891,7 @@ static struct dentry *cachefiles_check_active(struct cachefiles_cache *cache,
|
||||||
if (ret == -EIO) {
|
if (ret == -EIO) {
|
||||||
cachefiles_io_error(cache, "Lookup failed");
|
cachefiles_io_error(cache, "Lookup failed");
|
||||||
} else if (ret != -ENOMEM) {
|
} else if (ret != -ENOMEM) {
|
||||||
kerror("Internal error: %d", ret);
|
pr_err("Internal error: %d", ret);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,7 +950,7 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != -ENOMEM) {
|
if (ret != -ENOMEM) {
|
||||||
kerror("Internal error: %d", ret);
|
pr_err("Internal error: %d", ret);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,7 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache)
|
||||||
ret = set_security_override_from_ctx(new, cache->secctx);
|
ret = set_security_override_from_ctx(new, cache->secctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
put_cred(new);
|
put_cred(new);
|
||||||
printk(KERN_ERR "CacheFiles:"
|
pr_err("Security denies permission to nominate security context: error %d\n",
|
||||||
" Security denies permission to nominate"
|
|
||||||
" security context: error %d\n",
|
|
||||||
ret);
|
ret);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -59,16 +57,14 @@ static int cachefiles_check_cache_dir(struct cachefiles_cache *cache,
|
||||||
|
|
||||||
ret = security_inode_mkdir(root->d_inode, root, 0);
|
ret = security_inode_mkdir(root->d_inode, root, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "CacheFiles:"
|
pr_err("Security denies permission to make dirs: error %d",
|
||||||
" Security denies permission to make dirs: error %d",
|
|
||||||
ret);
|
ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = security_inode_create(root->d_inode, root, 0);
|
ret = security_inode_create(root->d_inode, root, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
printk(KERN_ERR "CacheFiles:"
|
pr_err("Security denies permission to create files: error %d",
|
||||||
" Security denies permission to create files: error %d",
|
|
||||||
ret);
|
ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -51,7 +51,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != -EEXIST) {
|
if (ret != -EEXIST) {
|
||||||
kerror("Can't set xattr on %*.*s [%lu] (err %d)",
|
pr_err("Can't set xattr on %*.*s [%lu] (err %d)",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
-ret);
|
-ret);
|
||||||
|
@ -64,7 +64,7 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||||
if (ret == -ERANGE)
|
if (ret == -ERANGE)
|
||||||
goto bad_type_length;
|
goto bad_type_length;
|
||||||
|
|
||||||
kerror("Can't read xattr on %*.*s [%lu] (err %d)",
|
pr_err("Can't read xattr on %*.*s [%lu] (err %d)",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
-ret);
|
-ret);
|
||||||
|
@ -85,14 +85,14 @@ int cachefiles_check_object_type(struct cachefiles_object *object)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bad_type_length:
|
bad_type_length:
|
||||||
kerror("Cache object %lu type xattr length incorrect",
|
pr_err("Cache object %lu type xattr length incorrect",
|
||||||
dentry->d_inode->i_ino);
|
dentry->d_inode->i_ino);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
bad_type:
|
bad_type:
|
||||||
xtype[2] = 0;
|
xtype[2] = 0;
|
||||||
kerror("Cache object %*.*s [%lu] type %s not %s",
|
pr_err("Cache object %*.*s [%lu] type %s not %s",
|
||||||
dentry->d_name.len, dentry->d_name.len,
|
dentry->d_name.len, dentry->d_name.len,
|
||||||
dentry->d_name.name, dentry->d_inode->i_ino,
|
dentry->d_name.name, dentry->d_inode->i_ino,
|
||||||
xtype, type);
|
xtype, type);
|
||||||
|
@ -293,7 +293,7 @@ int cachefiles_check_object_xattr(struct cachefiles_object *object,
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
bad_type_length:
|
bad_type_length:
|
||||||
kerror("Cache object %lu xattr length incorrect",
|
pr_err("Cache object %lu xattr length incorrect",
|
||||||
dentry->d_inode->i_ino);
|
dentry->d_inode->i_ino);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -694,7 +694,7 @@ static int ceph_writepages_start(struct address_space *mapping,
|
||||||
(wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
|
(wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD"));
|
||||||
|
|
||||||
if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
|
if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) {
|
||||||
pr_warning("writepage_start %p on forced umount\n", inode);
|
pr_warn("writepage_start %p on forced umount\n", inode);
|
||||||
return -EIO; /* we're in a forced umount, don't write! */
|
return -EIO; /* we're in a forced umount, don't write! */
|
||||||
}
|
}
|
||||||
if (fsc->mount_options->wsize && fsc->mount_options->wsize < wsize)
|
if (fsc->mount_options->wsize && fsc->mount_options->wsize < wsize)
|
||||||
|
|
|
@ -71,9 +71,9 @@ static int mdsc_show(struct seq_file *s, void *p)
|
||||||
seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
|
seq_printf(s, "%s", ceph_mds_op_name(req->r_op));
|
||||||
|
|
||||||
if (req->r_got_unsafe)
|
if (req->r_got_unsafe)
|
||||||
seq_printf(s, "\t(unsafe)");
|
seq_puts(s, "\t(unsafe)");
|
||||||
else
|
else
|
||||||
seq_printf(s, "\t");
|
seq_puts(s, "\t");
|
||||||
|
|
||||||
if (req->r_inode) {
|
if (req->r_inode) {
|
||||||
seq_printf(s, " #%llx", ceph_ino(req->r_inode));
|
seq_printf(s, " #%llx", ceph_ino(req->r_inode));
|
||||||
|
@ -119,7 +119,7 @@ static int mdsc_show(struct seq_file *s, void *p)
|
||||||
seq_printf(s, " %s", req->r_path2);
|
seq_printf(s, " %s", req->r_path2);
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(s, "\n");
|
seq_puts(s, "\n");
|
||||||
}
|
}
|
||||||
mutex_unlock(&mdsc->mutex);
|
mutex_unlock(&mdsc->mutex);
|
||||||
|
|
||||||
|
|
|
@ -821,7 +821,7 @@ static int fill_inode(struct inode *inode,
|
||||||
spin_unlock(&ci->i_ceph_lock);
|
spin_unlock(&ci->i_ceph_lock);
|
||||||
}
|
}
|
||||||
} else if (cap_fmode >= 0) {
|
} else if (cap_fmode >= 0) {
|
||||||
pr_warning("mds issued no caps on %llx.%llx\n",
|
pr_warn("mds issued no caps on %llx.%llx\n",
|
||||||
ceph_vinop(inode));
|
ceph_vinop(inode));
|
||||||
__ceph_get_fmode(ci, cap_fmode);
|
__ceph_get_fmode(ci, cap_fmode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2218,13 +2218,13 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg)
|
||||||
/* dup? */
|
/* dup? */
|
||||||
if ((req->r_got_unsafe && !head->safe) ||
|
if ((req->r_got_unsafe && !head->safe) ||
|
||||||
(req->r_got_safe && head->safe)) {
|
(req->r_got_safe && head->safe)) {
|
||||||
pr_warning("got a dup %s reply on %llu from mds%d\n",
|
pr_warn("got a dup %s reply on %llu from mds%d\n",
|
||||||
head->safe ? "safe" : "unsafe", tid, mds);
|
head->safe ? "safe" : "unsafe", tid, mds);
|
||||||
mutex_unlock(&mdsc->mutex);
|
mutex_unlock(&mdsc->mutex);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (req->r_got_safe && !head->safe) {
|
if (req->r_got_safe && !head->safe) {
|
||||||
pr_warning("got unsafe after safe on %llu from mds%d\n",
|
pr_warn("got unsafe after safe on %llu from mds%d\n",
|
||||||
tid, mds);
|
tid, mds);
|
||||||
mutex_unlock(&mdsc->mutex);
|
mutex_unlock(&mdsc->mutex);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -3525,7 +3525,7 @@ static void peer_reset(struct ceph_connection *con)
|
||||||
struct ceph_mds_session *s = con->private;
|
struct ceph_mds_session *s = con->private;
|
||||||
struct ceph_mds_client *mdsc = s->s_mdsc;
|
struct ceph_mds_client *mdsc = s->s_mdsc;
|
||||||
|
|
||||||
pr_warning("mds%d closed our session\n", s->s_mds);
|
pr_warn("mds%d closed our session\n", s->s_mds);
|
||||||
send_mds_reconnect(mdsc, s);
|
send_mds_reconnect(mdsc, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
|
||||||
|
|
||||||
ceph_decode_16_safe(p, end, version, bad);
|
ceph_decode_16_safe(p, end, version, bad);
|
||||||
if (version > 3) {
|
if (version > 3) {
|
||||||
pr_warning("got mdsmap version %d > 3, failing", version);
|
pr_warn("got mdsmap version %d > 3, failing", version);
|
||||||
goto bad;
|
goto bad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
|
||||||
|
|
||||||
inode = coda_iget(sb, fid, &attr);
|
inode = coda_iget(sb, fid, &attr);
|
||||||
if (IS_ERR(inode))
|
if (IS_ERR(inode))
|
||||||
printk("coda_cnode_make: coda_iget failed\n");
|
pr_warn("%s: coda_iget failed\n", __func__);
|
||||||
return inode;
|
return inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb)
|
||||||
unsigned long hash = coda_f2i(fid);
|
unsigned long hash = coda_f2i(fid);
|
||||||
|
|
||||||
if ( !sb ) {
|
if ( !sb ) {
|
||||||
printk("coda_fid_to_inode: no sb!\n");
|
pr_warn("%s: no sb!\n", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,12 @@
|
||||||
#ifndef _LINUX_CODA_FS
|
#ifndef _LINUX_CODA_FS
|
||||||
#define _LINUX_CODA_FS
|
#define _LINUX_CODA_FS
|
||||||
|
|
||||||
|
#ifdef pr_fmt
|
||||||
|
#undef pr_fmt
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/param.h>
|
#include <linux/param.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
|
@ -63,7 +69,7 @@ void coda_sysctl_clean(void);
|
||||||
else \
|
else \
|
||||||
ptr = (cast)vzalloc((unsigned long) size); \
|
ptr = (cast)vzalloc((unsigned long) size); \
|
||||||
if (!ptr) \
|
if (!ptr) \
|
||||||
printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
|
pr_warn("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsig
|
||||||
int type = 0;
|
int type = 0;
|
||||||
|
|
||||||
if (length > CODA_MAXNAMLEN) {
|
if (length > CODA_MAXNAMLEN) {
|
||||||
printk(KERN_ERR "name too long: lookup, %s (%*s)\n",
|
pr_err("name too long: lookup, %s (%*s)\n",
|
||||||
coda_i2s(dir), (int)length, name);
|
coda_i2s(dir), (int)length, name);
|
||||||
return ERR_PTR(-ENAMETOOLONG);
|
return ERR_PTR(-ENAMETOOLONG);
|
||||||
}
|
}
|
||||||
|
@ -453,23 +453,23 @@ static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
|
||||||
ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
|
ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
|
||||||
sizeof(*vdir));
|
sizeof(*vdir));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
|
pr_err("%s: read dir %s failed %d\n",
|
||||||
coda_f2s(&cii->c_fid), ret);
|
__func__, coda_f2s(&cii->c_fid), ret);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret == 0) break; /* end of directory file reached */
|
if (ret == 0) break; /* end of directory file reached */
|
||||||
|
|
||||||
/* catch truncated reads */
|
/* catch truncated reads */
|
||||||
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
|
if (ret < vdir_size || ret < vdir_size + vdir->d_namlen) {
|
||||||
printk(KERN_ERR "coda readdir: short read on %s\n",
|
pr_err("%s: short read on %s\n",
|
||||||
coda_f2s(&cii->c_fid));
|
__func__, coda_f2s(&cii->c_fid));
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* validate whether the directory file actually makes sense */
|
/* validate whether the directory file actually makes sense */
|
||||||
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
|
if (vdir->d_reclen < vdir_size + vdir->d_namlen) {
|
||||||
printk(KERN_ERR "coda readdir: invalid dir %s\n",
|
pr_err("%s: invalid dir %s\n",
|
||||||
coda_f2s(&cii->c_fid));
|
__func__, coda_f2s(&cii->c_fid));
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -589,8 +589,8 @@ int coda_revalidate_inode(struct inode *inode)
|
||||||
coda_vattr_to_iattr(inode, &attr);
|
coda_vattr_to_iattr(inode, &attr);
|
||||||
|
|
||||||
if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
|
if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
|
||||||
printk("Coda: inode %ld, fid %s changed type!\n",
|
pr_warn("inode %ld, fid %s changed type!\n",
|
||||||
inode->i_ino, coda_f2s(&(cii->c_fid)));
|
inode->i_ino, coda_f2s(&(cii->c_fid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the following can happen when a local fid is replaced
|
/* the following can happen when a local fid is replaced
|
||||||
|
|
|
@ -119,12 +119,12 @@ static int get_device_index(struct coda_mount_data *data)
|
||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
printk("coda_read_super: Bad mount data\n");
|
pr_warn("%s: Bad mount data\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->version != CODA_MOUNT_VERSION) {
|
if (data->version != CODA_MOUNT_VERSION) {
|
||||||
printk("coda_read_super: Bad mount version\n");
|
pr_warn("%s: Bad mount version\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,13 +141,13 @@ static int get_device_index(struct coda_mount_data *data)
|
||||||
fdput(f);
|
fdput(f);
|
||||||
|
|
||||||
if (idx < 0 || idx >= MAX_CODADEVS) {
|
if (idx < 0 || idx >= MAX_CODADEVS) {
|
||||||
printk("coda_read_super: Bad minor number\n");
|
pr_warn("%s: Bad minor number\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
Ebadf:
|
Ebadf:
|
||||||
printk("coda_read_super: Bad file\n");
|
pr_warn("%s: Bad file\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,19 +168,19 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
if(idx == -1)
|
if(idx == -1)
|
||||||
idx = 0;
|
idx = 0;
|
||||||
|
|
||||||
printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
|
pr_info("%s: device index: %i\n", __func__, idx);
|
||||||
|
|
||||||
vc = &coda_comms[idx];
|
vc = &coda_comms[idx];
|
||||||
mutex_lock(&vc->vc_mutex);
|
mutex_lock(&vc->vc_mutex);
|
||||||
|
|
||||||
if (!vc->vc_inuse) {
|
if (!vc->vc_inuse) {
|
||||||
printk("coda_read_super: No pseudo device\n");
|
pr_warn("%s: No pseudo device\n", __func__);
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vc->vc_sb) {
|
if (vc->vc_sb) {
|
||||||
printk("coda_read_super: Device already mounted\n");
|
pr_warn("%s: Device already mounted\n", __func__);
|
||||||
error = -EBUSY;
|
error = -EBUSY;
|
||||||
goto unlock_out;
|
goto unlock_out;
|
||||||
}
|
}
|
||||||
|
@ -204,22 +204,23 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
|
||||||
/* get root fid from Venus: this needs the root inode */
|
/* get root fid from Venus: this needs the root inode */
|
||||||
error = venus_rootfid(sb, &fid);
|
error = venus_rootfid(sb, &fid);
|
||||||
if ( error ) {
|
if ( error ) {
|
||||||
printk("coda_read_super: coda_get_rootfid failed with %d\n",
|
pr_warn("%s: coda_get_rootfid failed with %d\n",
|
||||||
error);
|
__func__, error);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
|
pr_info("%s: rootfid is %s\n", __func__, coda_f2s(&fid));
|
||||||
|
|
||||||
/* make root inode */
|
/* make root inode */
|
||||||
root = coda_cnode_make(&fid, sb);
|
root = coda_cnode_make(&fid, sb);
|
||||||
if (IS_ERR(root)) {
|
if (IS_ERR(root)) {
|
||||||
error = PTR_ERR(root);
|
error = PTR_ERR(root);
|
||||||
printk("Failure of coda_cnode_make for root: error %d\n", error);
|
pr_warn("Failure of coda_cnode_make for root: error %d\n",
|
||||||
|
error);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk("coda_read_super: rootinode is %ld dev %s\n",
|
pr_info("%s: rootinode is %ld dev %s\n",
|
||||||
root->i_ino, root->i_sb->s_id);
|
__func__, root->i_ino, root->i_sb->s_id);
|
||||||
sb->s_root = d_make_root(root);
|
sb->s_root = d_make_root(root);
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
|
@ -246,7 +247,7 @@ static void coda_put_super(struct super_block *sb)
|
||||||
sb->s_fs_info = NULL;
|
sb->s_fs_info = NULL;
|
||||||
mutex_unlock(&vcp->vc_mutex);
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
printk("Coda: Bye bye.\n");
|
pr_info("Bye bye.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void coda_evict_inode(struct inode *inode)
|
static void coda_evict_inode(struct inode *inode)
|
||||||
|
|
|
@ -114,14 +114,14 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
|
||||||
int size = sizeof(*dcbuf);
|
int size = sizeof(*dcbuf);
|
||||||
|
|
||||||
if ( nbytes < sizeof(struct coda_out_hdr) ) {
|
if ( nbytes < sizeof(struct coda_out_hdr) ) {
|
||||||
printk("coda_downcall opc %d uniq %d, not enough!\n",
|
pr_warn("coda_downcall opc %d uniq %d, not enough!\n",
|
||||||
hdr.opcode, hdr.unique);
|
hdr.opcode, hdr.unique);
|
||||||
count = nbytes;
|
count = nbytes;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if ( nbytes > size ) {
|
if ( nbytes > size ) {
|
||||||
printk("Coda: downcall opc %d, uniq %d, too much!",
|
pr_warn("downcall opc %d, uniq %d, too much!",
|
||||||
hdr.opcode, hdr.unique);
|
hdr.opcode, hdr.unique);
|
||||||
nbytes = size;
|
nbytes = size;
|
||||||
}
|
}
|
||||||
CODA_ALLOC(dcbuf, union outputArgs *, nbytes);
|
CODA_ALLOC(dcbuf, union outputArgs *, nbytes);
|
||||||
|
@ -136,7 +136,8 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
|
||||||
|
|
||||||
CODA_FREE(dcbuf, nbytes);
|
CODA_FREE(dcbuf, nbytes);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk("psdev_write: coda_downcall error: %d\n", error);
|
pr_warn("%s: coda_downcall error: %d\n",
|
||||||
|
__func__, error);
|
||||||
retval = error;
|
retval = error;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -157,16 +158,17 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
|
||||||
mutex_unlock(&vcp->vc_mutex);
|
mutex_unlock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (!req) {
|
if (!req) {
|
||||||
printk("psdev_write: msg (%d, %d) not found\n",
|
pr_warn("%s: msg (%d, %d) not found\n",
|
||||||
hdr.opcode, hdr.unique);
|
__func__, hdr.opcode, hdr.unique);
|
||||||
retval = -ESRCH;
|
retval = -ESRCH;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* move data into response buffer. */
|
/* move data into response buffer. */
|
||||||
if (req->uc_outSize < nbytes) {
|
if (req->uc_outSize < nbytes) {
|
||||||
printk("psdev_write: too much cnt: %d, cnt: %ld, opc: %d, uniq: %d.\n",
|
pr_warn("%s: too much cnt: %d, cnt: %ld, opc: %d, uniq: %d.\n",
|
||||||
req->uc_outSize, (long)nbytes, hdr.opcode, hdr.unique);
|
__func__, req->uc_outSize, (long)nbytes,
|
||||||
|
hdr.opcode, hdr.unique);
|
||||||
nbytes = req->uc_outSize; /* don't have more space! */
|
nbytes = req->uc_outSize; /* don't have more space! */
|
||||||
}
|
}
|
||||||
if (copy_from_user(req->uc_data, buf, nbytes)) {
|
if (copy_from_user(req->uc_data, buf, nbytes)) {
|
||||||
|
@ -240,8 +242,8 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
|
||||||
/* Move the input args into userspace */
|
/* Move the input args into userspace */
|
||||||
count = req->uc_inSize;
|
count = req->uc_inSize;
|
||||||
if (nbytes < req->uc_inSize) {
|
if (nbytes < req->uc_inSize) {
|
||||||
printk ("psdev_read: Venus read %ld bytes of %d in message\n",
|
pr_warn("%s: Venus read %ld bytes of %d in message\n",
|
||||||
(long)nbytes, req->uc_inSize);
|
__func__, (long)nbytes, req->uc_inSize);
|
||||||
count = nbytes;
|
count = nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +307,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
|
||||||
struct upc_req *req, *tmp;
|
struct upc_req *req, *tmp;
|
||||||
|
|
||||||
if (!vcp || !vcp->vc_inuse ) {
|
if (!vcp || !vcp->vc_inuse ) {
|
||||||
printk("psdev_release: Not open.\n");
|
pr_warn("%s: Not open.\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,8 +356,8 @@ static int init_coda_psdev(void)
|
||||||
{
|
{
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
if (register_chrdev(CODA_PSDEV_MAJOR, "coda", &coda_psdev_fops)) {
|
if (register_chrdev(CODA_PSDEV_MAJOR, "coda", &coda_psdev_fops)) {
|
||||||
printk(KERN_ERR "coda_psdev: unable to get major %d\n",
|
pr_err("%s: unable to get major %d\n",
|
||||||
CODA_PSDEV_MAJOR);
|
__func__, CODA_PSDEV_MAJOR);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
coda_psdev_class = class_create(THIS_MODULE, "coda");
|
coda_psdev_class = class_create(THIS_MODULE, "coda");
|
||||||
|
@ -393,13 +395,13 @@ static int __init init_coda(void)
|
||||||
goto out2;
|
goto out2;
|
||||||
status = init_coda_psdev();
|
status = init_coda_psdev();
|
||||||
if ( status ) {
|
if ( status ) {
|
||||||
printk("Problem (%d) in init_coda_psdev\n", status);
|
pr_warn("Problem (%d) in init_coda_psdev\n", status);
|
||||||
goto out1;
|
goto out1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = register_filesystem(&coda_fs_type);
|
status = register_filesystem(&coda_fs_type);
|
||||||
if (status) {
|
if (status) {
|
||||||
printk("coda: failed to register filesystem!\n");
|
pr_warn("failed to register filesystem!\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -420,9 +422,8 @@ static void __exit exit_coda(void)
|
||||||
int err, i;
|
int err, i;
|
||||||
|
|
||||||
err = unregister_filesystem(&coda_fs_type);
|
err = unregister_filesystem(&coda_fs_type);
|
||||||
if ( err != 0 ) {
|
if (err != 0)
|
||||||
printk("coda: failed to unregister filesystem\n");
|
pr_warn("failed to unregister filesystem\n");
|
||||||
}
|
|
||||||
for (i = 0; i < MAX_CODADEVS; i++)
|
for (i = 0; i < MAX_CODADEVS; i++)
|
||||||
device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
|
device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
|
||||||
class_destroy(coda_psdev_class);
|
class_destroy(coda_psdev_class);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#ifdef CONFIG_SYSCTL
|
#ifdef CONFIG_SYSCTL
|
||||||
static struct ctl_table_header *fs_table_header;
|
static struct ctl_table_header *fs_table_header;
|
||||||
|
|
||||||
static ctl_table coda_table[] = {
|
static struct ctl_table coda_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "timeout",
|
.procname = "timeout",
|
||||||
.data = &coda_timeout,
|
.data = &coda_timeout,
|
||||||
|
@ -39,7 +39,7 @@ static ctl_table coda_table[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ctl_table fs_table[] = {
|
static struct ctl_table fs_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "coda",
|
.procname = "coda",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -508,8 +508,8 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
|
||||||
inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
|
inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
|
||||||
|
|
||||||
/* get the data out of user space */
|
/* get the data out of user space */
|
||||||
if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
|
if (copy_from_user((char *)inp + (long)inp->coda_ioctl.data,
|
||||||
data->vi.in, data->vi.in_size) ) {
|
data->vi.in, data->vi.in_size)) {
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -518,8 +518,8 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
|
||||||
&outsize, inp);
|
&outsize, inp);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
printk("coda_pioctl: Venus returns: %d for %s\n",
|
pr_warn("%s: Venus returns: %d for %s\n",
|
||||||
error, coda_f2s(fid));
|
__func__, error, coda_f2s(fid));
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,7 +675,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
mutex_lock(&vcp->vc_mutex);
|
mutex_lock(&vcp->vc_mutex);
|
||||||
|
|
||||||
if (!vcp->vc_inuse) {
|
if (!vcp->vc_inuse) {
|
||||||
printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
|
pr_notice("Venus dead, not sending upcall\n");
|
||||||
error = -ENXIO;
|
error = -ENXIO;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
@ -725,7 +725,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
|
|
||||||
error = -EINTR;
|
error = -EINTR;
|
||||||
if ((req->uc_flags & CODA_REQ_ABORT) || !signal_pending(current)) {
|
if ((req->uc_flags & CODA_REQ_ABORT) || !signal_pending(current)) {
|
||||||
printk(KERN_WARNING "coda: Unexpected interruption.\n");
|
pr_warn("Unexpected interruption.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +735,7 @@ static int coda_upcall(struct venus_comm *vcp,
|
||||||
|
|
||||||
/* Venus saw the upcall, make sure we can send interrupt signal */
|
/* Venus saw the upcall, make sure we can send interrupt signal */
|
||||||
if (!vcp->vc_inuse) {
|
if (!vcp->vc_inuse) {
|
||||||
printk(KERN_INFO "coda: Venus dead, not sending signal.\n");
|
pr_info("Venus dead, not sending signal.\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ static long get_nr_dentry_unused(void)
|
||||||
return sum < 0 ? 0 : sum;
|
return sum < 0 ? 0 : sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
int proc_nr_dentry(ctl_table *table, int write, void __user *buffer,
|
int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
|
||||||
size_t *lenp, loff_t *ppos)
|
size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
dentry_stat.nr_dentry = get_nr_dentry();
|
dentry_stat.nr_dentry = get_nr_dentry();
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
*
|
*
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
@ -148,10 +150,10 @@ static inline struct super_block *pts_sb_from_inode(struct inode *inode)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parse_mount_options():
|
* parse_mount_options():
|
||||||
* Set @opts to mount options specified in @data. If an option is not
|
* Set @opts to mount options specified in @data. If an option is not
|
||||||
* specified in @data, set it to its default value. The exception is
|
* specified in @data, set it to its default value. The exception is
|
||||||
* 'newinstance' option which can only be set/cleared on a mount (i.e.
|
* 'newinstance' option which can only be set/cleared on a mount (i.e.
|
||||||
* cannot be changed during remount).
|
* cannot be changed during remount).
|
||||||
*
|
*
|
||||||
* Note: @data may be NULL (in which case all options are set to default).
|
* Note: @data may be NULL (in which case all options are set to default).
|
||||||
*/
|
*/
|
||||||
|
@ -225,7 +227,7 @@ static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "devpts: called with bogus options\n");
|
pr_err("called with bogus options\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +263,7 @@ static int mknod_ptmx(struct super_block *sb)
|
||||||
|
|
||||||
dentry = d_alloc_name(root, "ptmx");
|
dentry = d_alloc_name(root, "ptmx");
|
||||||
if (!dentry) {
|
if (!dentry) {
|
||||||
printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
|
pr_err("Unable to alloc dentry for ptmx node\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +272,7 @@ static int mknod_ptmx(struct super_block *sb)
|
||||||
*/
|
*/
|
||||||
inode = new_inode(sb);
|
inode = new_inode(sb);
|
||||||
if (!inode) {
|
if (!inode) {
|
||||||
printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
|
pr_err("Unable to alloc inode for ptmx node\n");
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -303,7 +305,7 @@ static void update_ptmx_mode(struct pts_fs_info *fsi)
|
||||||
#else
|
#else
|
||||||
static inline void update_ptmx_mode(struct pts_fs_info *fsi)
|
static inline void update_ptmx_mode(struct pts_fs_info *fsi)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -333,9 +335,11 @@ static int devpts_show_options(struct seq_file *seq, struct dentry *root)
|
||||||
struct pts_mount_opts *opts = &fsi->mount_opts;
|
struct pts_mount_opts *opts = &fsi->mount_opts;
|
||||||
|
|
||||||
if (opts->setuid)
|
if (opts->setuid)
|
||||||
seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid));
|
seq_printf(seq, ",uid=%u",
|
||||||
|
from_kuid_munged(&init_user_ns, opts->uid));
|
||||||
if (opts->setgid)
|
if (opts->setgid)
|
||||||
seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid));
|
seq_printf(seq, ",gid=%u",
|
||||||
|
from_kgid_munged(&init_user_ns, opts->gid));
|
||||||
seq_printf(seq, ",mode=%03o", opts->mode);
|
seq_printf(seq, ",mode=%03o", opts->mode);
|
||||||
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
|
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
|
||||||
seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
|
seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
|
||||||
|
@ -396,7 +400,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
|
||||||
if (s->s_root)
|
if (s->s_root)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
printk(KERN_ERR "devpts: get root dentry failed\n");
|
pr_err("get root dentry failed\n");
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -157,11 +157,13 @@ static ssize_t cluster_set(struct dlm_cluster *cl, unsigned int *cl_field,
|
||||||
const char *buf, size_t len)
|
const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
rc = kstrtouint(buf, 0, &x);
|
||||||
x = simple_strtoul(buf, NULL, 0);
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
if (check_zero && !x)
|
if (check_zero && !x)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -730,7 +732,10 @@ static ssize_t comm_nodeid_read(struct dlm_comm *cm, char *buf)
|
||||||
static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
|
static ssize_t comm_nodeid_write(struct dlm_comm *cm, const char *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
cm->nodeid = simple_strtol(buf, NULL, 0);
|
int rc = kstrtoint(buf, 0, &cm->nodeid);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +747,10 @@ static ssize_t comm_local_read(struct dlm_comm *cm, char *buf)
|
||||||
static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
|
static ssize_t comm_local_write(struct dlm_comm *cm, const char *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
cm->local= simple_strtol(buf, NULL, 0);
|
int rc = kstrtoint(buf, 0, &cm->local);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
if (cm->local && !local_comm)
|
if (cm->local && !local_comm)
|
||||||
local_comm = cm;
|
local_comm = cm;
|
||||||
return len;
|
return len;
|
||||||
|
@ -846,7 +854,10 @@ static ssize_t node_nodeid_write(struct dlm_node *nd, const char *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
uint32_t seq = 0;
|
uint32_t seq = 0;
|
||||||
nd->nodeid = simple_strtol(buf, NULL, 0);
|
int rc = kstrtoint(buf, 0, &nd->nodeid);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
dlm_comm_seq(nd->nodeid, &seq);
|
dlm_comm_seq(nd->nodeid, &seq);
|
||||||
nd->comm_seq = seq;
|
nd->comm_seq = seq;
|
||||||
return len;
|
return len;
|
||||||
|
@ -860,7 +871,10 @@ static ssize_t node_weight_read(struct dlm_node *nd, char *buf)
|
||||||
static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
|
static ssize_t node_weight_write(struct dlm_node *nd, const char *buf,
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
nd->weight = simple_strtol(buf, NULL, 0);
|
int rc = kstrtoint(buf, 0, &nd->weight);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ static int print_format1_lock(struct seq_file *s, struct dlm_lkb *lkb,
|
||||||
if (lkb->lkb_wait_type)
|
if (lkb->lkb_wait_type)
|
||||||
seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
|
seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
|
||||||
|
|
||||||
return seq_printf(s, "\n");
|
return seq_puts(s, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_format1(struct dlm_rsb *res, struct seq_file *s)
|
static int print_format1(struct dlm_rsb *res, struct seq_file *s)
|
||||||
|
@ -92,31 +92,31 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res->res_nodeid > 0)
|
if (res->res_nodeid > 0)
|
||||||
rv = seq_printf(s, "\" \nLocal Copy, Master is node %d\n",
|
rv = seq_printf(s, "\"\nLocal Copy, Master is node %d\n",
|
||||||
res->res_nodeid);
|
res->res_nodeid);
|
||||||
else if (res->res_nodeid == 0)
|
else if (res->res_nodeid == 0)
|
||||||
rv = seq_printf(s, "\" \nMaster Copy\n");
|
rv = seq_puts(s, "\"\nMaster Copy\n");
|
||||||
else if (res->res_nodeid == -1)
|
else if (res->res_nodeid == -1)
|
||||||
rv = seq_printf(s, "\" \nLooking up master (lkid %x)\n",
|
rv = seq_printf(s, "\"\nLooking up master (lkid %x)\n",
|
||||||
res->res_first_lkid);
|
res->res_first_lkid);
|
||||||
else
|
else
|
||||||
rv = seq_printf(s, "\" \nInvalid master %d\n",
|
rv = seq_printf(s, "\"\nInvalid master %d\n",
|
||||||
res->res_nodeid);
|
res->res_nodeid);
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* Print the LVB: */
|
/* Print the LVB: */
|
||||||
if (res->res_lvbptr) {
|
if (res->res_lvbptr) {
|
||||||
seq_printf(s, "LVB: ");
|
seq_puts(s, "LVB: ");
|
||||||
for (i = 0; i < lvblen; i++) {
|
for (i = 0; i < lvblen; i++) {
|
||||||
if (i == lvblen / 2)
|
if (i == lvblen / 2)
|
||||||
seq_printf(s, "\n ");
|
seq_puts(s, "\n ");
|
||||||
seq_printf(s, "%02x ",
|
seq_printf(s, "%02x ",
|
||||||
(unsigned char) res->res_lvbptr[i]);
|
(unsigned char) res->res_lvbptr[i]);
|
||||||
}
|
}
|
||||||
if (rsb_flag(res, RSB_VALNOTVALID))
|
if (rsb_flag(res, RSB_VALNOTVALID))
|
||||||
seq_printf(s, " (INVALID)");
|
seq_puts(s, " (INVALID)");
|
||||||
rv = seq_printf(s, "\n");
|
rv = seq_puts(s, "\n");
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -133,21 +133,21 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the locks attached to this resource */
|
/* Print the locks attached to this resource */
|
||||||
seq_printf(s, "Granted Queue\n");
|
seq_puts(s, "Granted Queue\n");
|
||||||
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
|
list_for_each_entry(lkb, &res->res_grantqueue, lkb_statequeue) {
|
||||||
rv = print_format1_lock(s, lkb, res);
|
rv = print_format1_lock(s, lkb, res);
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(s, "Conversion Queue\n");
|
seq_puts(s, "Conversion Queue\n");
|
||||||
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
|
list_for_each_entry(lkb, &res->res_convertqueue, lkb_statequeue) {
|
||||||
rv = print_format1_lock(s, lkb, res);
|
rv = print_format1_lock(s, lkb, res);
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_printf(s, "Waiting Queue\n");
|
seq_puts(s, "Waiting Queue\n");
|
||||||
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
|
list_for_each_entry(lkb, &res->res_waitqueue, lkb_statequeue) {
|
||||||
rv = print_format1_lock(s, lkb, res);
|
rv = print_format1_lock(s, lkb, res);
|
||||||
if (rv)
|
if (rv)
|
||||||
|
@ -157,13 +157,13 @@ static int print_format1(struct dlm_rsb *res, struct seq_file *s)
|
||||||
if (list_empty(&res->res_lookup))
|
if (list_empty(&res->res_lookup))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
seq_printf(s, "Lookup Queue\n");
|
seq_puts(s, "Lookup Queue\n");
|
||||||
list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
|
list_for_each_entry(lkb, &res->res_lookup, lkb_rsb_lookup) {
|
||||||
rv = seq_printf(s, "%08x %s", lkb->lkb_id,
|
rv = seq_printf(s, "%08x %s", lkb->lkb_id,
|
||||||
print_lockmode(lkb->lkb_rqmode));
|
print_lockmode(lkb->lkb_rqmode));
|
||||||
if (lkb->lkb_wait_type)
|
if (lkb->lkb_wait_type)
|
||||||
seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
|
seq_printf(s, " wait_type: %d", lkb->lkb_wait_type);
|
||||||
rv = seq_printf(s, "\n");
|
rv = seq_puts(s, "\n");
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
unlock_rsb(res);
|
unlock_rsb(res);
|
||||||
|
@ -300,7 +300,7 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
|
||||||
else
|
else
|
||||||
seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
|
seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
|
||||||
}
|
}
|
||||||
rv = seq_printf(s, "\n");
|
rv = seq_puts(s, "\n");
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -311,7 +311,7 @@ static int print_format3(struct dlm_rsb *r, struct seq_file *s)
|
||||||
|
|
||||||
for (i = 0; i < lvblen; i++)
|
for (i = 0; i < lvblen; i++)
|
||||||
seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
|
seq_printf(s, " %02x", (unsigned char)r->res_lvbptr[i]);
|
||||||
rv = seq_printf(s, "\n");
|
rv = seq_puts(s, "\n");
|
||||||
if (rv)
|
if (rv)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -377,7 +377,7 @@ static int print_format4(struct dlm_rsb *r, struct seq_file *s)
|
||||||
else
|
else
|
||||||
seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
|
seq_printf(s, " %02x", (unsigned char)r->res_name[i]);
|
||||||
}
|
}
|
||||||
rv = seq_printf(s, "\n");
|
rv = seq_puts(s, "\n");
|
||||||
out:
|
out:
|
||||||
unlock_rsb(r);
|
unlock_rsb(r);
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -35,8 +35,11 @@ static struct task_struct * scand_task;
|
||||||
static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
|
static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
ssize_t ret = len;
|
ssize_t ret = len;
|
||||||
int n = simple_strtol(buf, NULL, 0);
|
int n;
|
||||||
|
int rc = kstrtoint(buf, 0, &n);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
ls = dlm_find_lockspace_local(ls->ls_local_handle);
|
ls = dlm_find_lockspace_local(ls->ls_local_handle);
|
||||||
if (!ls)
|
if (!ls)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -57,7 +60,10 @@ static ssize_t dlm_control_store(struct dlm_ls *ls, const char *buf, size_t len)
|
||||||
|
|
||||||
static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
|
static ssize_t dlm_event_store(struct dlm_ls *ls, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
ls->ls_uevent_result = simple_strtol(buf, NULL, 0);
|
int rc = kstrtoint(buf, 0, &ls->ls_uevent_result);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
|
set_bit(LSFL_UEVENT_WAIT, &ls->ls_flags);
|
||||||
wake_up(&ls->ls_uevent_wait);
|
wake_up(&ls->ls_uevent_wait);
|
||||||
return len;
|
return len;
|
||||||
|
@ -70,7 +76,10 @@ static ssize_t dlm_id_show(struct dlm_ls *ls, char *buf)
|
||||||
|
|
||||||
static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
|
static ssize_t dlm_id_store(struct dlm_ls *ls, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
ls->ls_global_id = simple_strtoul(buf, NULL, 0);
|
int rc = kstrtouint(buf, 0, &ls->ls_global_id);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +90,11 @@ static ssize_t dlm_nodir_show(struct dlm_ls *ls, char *buf)
|
||||||
|
|
||||||
static ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
|
static ssize_t dlm_nodir_store(struct dlm_ls *ls, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
int val = simple_strtoul(buf, NULL, 0);
|
int val;
|
||||||
|
int rc = kstrtoint(buf, 0, &val);
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
if (val == 1)
|
if (val == 1)
|
||||||
set_bit(LSFL_NODIR, &ls->ls_flags);
|
set_bit(LSFL_NODIR, &ls->ls_flags);
|
||||||
return len;
|
return len;
|
||||||
|
|
|
@ -50,7 +50,7 @@ static void drop_slab(void)
|
||||||
} while (nr_objects > 10);
|
} while (nr_objects > 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
int drop_caches_sysctl_handler(ctl_table *table, int write,
|
int drop_caches_sysctl_handler(struct ctl_table *table, int write,
|
||||||
void __user *buffer, size_t *length, loff_t *ppos)
|
void __user *buffer, size_t *length, loff_t *ppos)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
|
@ -293,7 +293,7 @@ static LIST_HEAD(tfile_check_list);
|
||||||
static long zero;
|
static long zero;
|
||||||
static long long_max = LONG_MAX;
|
static long long_max = LONG_MAX;
|
||||||
|
|
||||||
ctl_table epoll_table[] = {
|
struct ctl_table epoll_table[] = {
|
||||||
{
|
{
|
||||||
.procname = "max_user_watches",
|
.procname = "max_user_watches",
|
||||||
.data = &max_user_watches,
|
.data = &max_user_watches,
|
||||||
|
|
|
@ -52,7 +52,8 @@ struct fat_mount_options {
|
||||||
usefree:1, /* Use free_clusters for FAT32 */
|
usefree:1, /* Use free_clusters for FAT32 */
|
||||||
tz_set:1, /* Filesystem timestamps' offset set */
|
tz_set:1, /* Filesystem timestamps' offset set */
|
||||||
rodir:1, /* allow ATTR_RO for directory */
|
rodir:1, /* allow ATTR_RO for directory */
|
||||||
discard:1; /* Issue discard requests on deletions */
|
discard:1, /* Issue discard requests on deletions */
|
||||||
|
dos1xfloppy:1; /* Assume default BPB for DOS 1.x floppies */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FAT_HASH_BITS 8
|
#define FAT_HASH_BITS 8
|
||||||
|
|
345
fs/fat/inode.c
345
fs/fat/inode.c
|
@ -35,9 +35,71 @@
|
||||||
#define CONFIG_FAT_DEFAULT_IOCHARSET ""
|
#define CONFIG_FAT_DEFAULT_IOCHARSET ""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define KB_IN_SECTORS 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A deserialized copy of the on-disk structure laid out in struct
|
||||||
|
* fat_boot_sector.
|
||||||
|
*/
|
||||||
|
struct fat_bios_param_block {
|
||||||
|
u16 fat_sector_size;
|
||||||
|
u8 fat_sec_per_clus;
|
||||||
|
u16 fat_reserved;
|
||||||
|
u8 fat_fats;
|
||||||
|
u16 fat_dir_entries;
|
||||||
|
u16 fat_sectors;
|
||||||
|
u16 fat_fat_length;
|
||||||
|
u32 fat_total_sect;
|
||||||
|
|
||||||
|
u8 fat16_state;
|
||||||
|
u32 fat16_vol_id;
|
||||||
|
|
||||||
|
u32 fat32_length;
|
||||||
|
u32 fat32_root_cluster;
|
||||||
|
u16 fat32_info_sector;
|
||||||
|
u8 fat32_state;
|
||||||
|
u32 fat32_vol_id;
|
||||||
|
};
|
||||||
|
|
||||||
static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
|
static int fat_default_codepage = CONFIG_FAT_DEFAULT_CODEPAGE;
|
||||||
static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
|
static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
|
||||||
|
|
||||||
|
static struct fat_floppy_defaults {
|
||||||
|
unsigned nr_sectors;
|
||||||
|
unsigned sec_per_clus;
|
||||||
|
unsigned dir_entries;
|
||||||
|
unsigned media;
|
||||||
|
unsigned fat_length;
|
||||||
|
} floppy_defaults[] = {
|
||||||
|
{
|
||||||
|
.nr_sectors = 160 * KB_IN_SECTORS,
|
||||||
|
.sec_per_clus = 1,
|
||||||
|
.dir_entries = 64,
|
||||||
|
.media = 0xFE,
|
||||||
|
.fat_length = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.nr_sectors = 180 * KB_IN_SECTORS,
|
||||||
|
.sec_per_clus = 1,
|
||||||
|
.dir_entries = 64,
|
||||||
|
.media = 0xFC,
|
||||||
|
.fat_length = 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.nr_sectors = 320 * KB_IN_SECTORS,
|
||||||
|
.sec_per_clus = 2,
|
||||||
|
.dir_entries = 112,
|
||||||
|
.media = 0xFF,
|
||||||
|
.fat_length = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.nr_sectors = 360 * KB_IN_SECTORS,
|
||||||
|
.sec_per_clus = 2,
|
||||||
|
.dir_entries = 112,
|
||||||
|
.media = 0xFD,
|
||||||
|
.fat_length = 2,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static int fat_add_cluster(struct inode *inode)
|
static int fat_add_cluster(struct inode *inode)
|
||||||
{
|
{
|
||||||
|
@ -359,7 +421,7 @@ struct inode *fat_iget(struct super_block *sb, loff_t i_pos)
|
||||||
|
|
||||||
static int is_exec(unsigned char *extension)
|
static int is_exec(unsigned char *extension)
|
||||||
{
|
{
|
||||||
unsigned char *exe_extensions = "EXECOMBAT", *walk;
|
unsigned char exe_extensions[] = "EXECOMBAT", *walk;
|
||||||
|
|
||||||
for (walk = exe_extensions; *walk; walk += 3)
|
for (walk = exe_extensions; *walk; walk += 3)
|
||||||
if (!strncmp(extension, walk, 3))
|
if (!strncmp(extension, walk, 3))
|
||||||
|
@ -853,6 +915,8 @@ static int fat_show_options(struct seq_file *m, struct dentry *root)
|
||||||
seq_puts(m, ",nfs=stale_rw");
|
seq_puts(m, ",nfs=stale_rw");
|
||||||
if (opts->discard)
|
if (opts->discard)
|
||||||
seq_puts(m, ",discard");
|
seq_puts(m, ",discard");
|
||||||
|
if (opts->dos1xfloppy)
|
||||||
|
seq_puts(m, ",dos1xfloppy");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -867,7 +931,7 @@ enum {
|
||||||
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
|
Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
|
||||||
Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
|
Opt_obsolete, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
|
||||||
Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
|
Opt_err_panic, Opt_err_ro, Opt_discard, Opt_nfs, Opt_time_offset,
|
||||||
Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err,
|
Opt_nfs_stale_rw, Opt_nfs_nostale_ro, Opt_err, Opt_dos1xfloppy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const match_table_t fat_tokens = {
|
static const match_table_t fat_tokens = {
|
||||||
|
@ -900,6 +964,7 @@ static const match_table_t fat_tokens = {
|
||||||
{Opt_nfs_stale_rw, "nfs"},
|
{Opt_nfs_stale_rw, "nfs"},
|
||||||
{Opt_nfs_stale_rw, "nfs=stale_rw"},
|
{Opt_nfs_stale_rw, "nfs=stale_rw"},
|
||||||
{Opt_nfs_nostale_ro, "nfs=nostale_ro"},
|
{Opt_nfs_nostale_ro, "nfs=nostale_ro"},
|
||||||
|
{Opt_dos1xfloppy, "dos1xfloppy"},
|
||||||
{Opt_obsolete, "conv=binary"},
|
{Opt_obsolete, "conv=binary"},
|
||||||
{Opt_obsolete, "conv=text"},
|
{Opt_obsolete, "conv=text"},
|
||||||
{Opt_obsolete, "conv=auto"},
|
{Opt_obsolete, "conv=auto"},
|
||||||
|
@ -1102,6 +1167,9 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat,
|
||||||
case Opt_nfs_nostale_ro:
|
case Opt_nfs_nostale_ro:
|
||||||
opts->nfs = FAT_NFS_NOSTALE_RO;
|
opts->nfs = FAT_NFS_NOSTALE_RO;
|
||||||
break;
|
break;
|
||||||
|
case Opt_dos1xfloppy:
|
||||||
|
opts->dos1xfloppy = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
/* msdos specific */
|
/* msdos specific */
|
||||||
case Opt_dots:
|
case Opt_dots:
|
||||||
|
@ -1247,6 +1315,169 @@ static unsigned long calc_fat_clusters(struct super_block *sb)
|
||||||
return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
|
return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool fat_bpb_is_zero(struct fat_boot_sector *b)
|
||||||
|
{
|
||||||
|
if (get_unaligned_le16(&b->sector_size))
|
||||||
|
return false;
|
||||||
|
if (b->sec_per_clus)
|
||||||
|
return false;
|
||||||
|
if (b->reserved)
|
||||||
|
return false;
|
||||||
|
if (b->fats)
|
||||||
|
return false;
|
||||||
|
if (get_unaligned_le16(&b->dir_entries))
|
||||||
|
return false;
|
||||||
|
if (get_unaligned_le16(&b->sectors))
|
||||||
|
return false;
|
||||||
|
if (b->media)
|
||||||
|
return false;
|
||||||
|
if (b->fat_length)
|
||||||
|
return false;
|
||||||
|
if (b->secs_track)
|
||||||
|
return false;
|
||||||
|
if (b->heads)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fat_read_bpb(struct super_block *sb, struct fat_boot_sector *b,
|
||||||
|
int silent, struct fat_bios_param_block *bpb)
|
||||||
|
{
|
||||||
|
int error = -EINVAL;
|
||||||
|
|
||||||
|
/* Read in BPB ... */
|
||||||
|
memset(bpb, 0, sizeof(*bpb));
|
||||||
|
bpb->fat_sector_size = get_unaligned_le16(&b->sector_size);
|
||||||
|
bpb->fat_sec_per_clus = b->sec_per_clus;
|
||||||
|
bpb->fat_reserved = le16_to_cpu(b->reserved);
|
||||||
|
bpb->fat_fats = b->fats;
|
||||||
|
bpb->fat_dir_entries = get_unaligned_le16(&b->dir_entries);
|
||||||
|
bpb->fat_sectors = get_unaligned_le16(&b->sectors);
|
||||||
|
bpb->fat_fat_length = le16_to_cpu(b->fat_length);
|
||||||
|
bpb->fat_total_sect = le32_to_cpu(b->total_sect);
|
||||||
|
|
||||||
|
bpb->fat16_state = b->fat16.state;
|
||||||
|
bpb->fat16_vol_id = get_unaligned_le32(b->fat16.vol_id);
|
||||||
|
|
||||||
|
bpb->fat32_length = le32_to_cpu(b->fat32.length);
|
||||||
|
bpb->fat32_root_cluster = le32_to_cpu(b->fat32.root_cluster);
|
||||||
|
bpb->fat32_info_sector = le16_to_cpu(b->fat32.info_sector);
|
||||||
|
bpb->fat32_state = b->fat32.state;
|
||||||
|
bpb->fat32_vol_id = get_unaligned_le32(b->fat32.vol_id);
|
||||||
|
|
||||||
|
/* Validate this looks like a FAT filesystem BPB */
|
||||||
|
if (!bpb->fat_reserved) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR,
|
||||||
|
"bogus number of reserved sectors");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!bpb->fat_fats) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR, "bogus number of FAT structure");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Earlier we checked here that b->secs_track and b->head are nonzero,
|
||||||
|
* but it turns out valid FAT filesystems can have zero there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!fat_valid_media(b->media)) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR, "invalid media value (0x%02x)",
|
||||||
|
(unsigned)b->media);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_power_of_2(bpb->fat_sector_size)
|
||||||
|
|| (bpb->fat_sector_size < 512)
|
||||||
|
|| (bpb->fat_sector_size > 4096)) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR, "bogus logical sector size %u",
|
||||||
|
(unsigned)bpb->fat_sector_size);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_power_of_2(bpb->fat_sec_per_clus)) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR, "bogus sectors per cluster %u",
|
||||||
|
(unsigned)bpb->fat_sec_per_clus);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fat_read_static_bpb(struct super_block *sb,
|
||||||
|
struct fat_boot_sector *b, int silent,
|
||||||
|
struct fat_bios_param_block *bpb)
|
||||||
|
{
|
||||||
|
static const char *notdos1x = "This doesn't look like a DOS 1.x volume";
|
||||||
|
|
||||||
|
struct fat_floppy_defaults *fdefaults = NULL;
|
||||||
|
int error = -EINVAL;
|
||||||
|
sector_t bd_sects;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
bd_sects = i_size_read(sb->s_bdev->bd_inode) / SECTOR_SIZE;
|
||||||
|
|
||||||
|
/* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */
|
||||||
|
if (b->ignored[0] != 0xeb || b->ignored[2] != 0x90) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR,
|
||||||
|
"%s; no bootstrapping code", notdos1x);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If any value in this region is non-zero, it isn't archaic
|
||||||
|
* DOS.
|
||||||
|
*/
|
||||||
|
if (!fat_bpb_is_zero(b)) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_ERR,
|
||||||
|
"%s; DOS 2.x BPB is non-zero", notdos1x);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(floppy_defaults); i++) {
|
||||||
|
if (floppy_defaults[i].nr_sectors == bd_sects) {
|
||||||
|
fdefaults = &floppy_defaults[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdefaults == NULL) {
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_WARNING,
|
||||||
|
"This looks like a DOS 1.x volume, but isn't a recognized floppy size (%llu sectors)",
|
||||||
|
(u64)bd_sects);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent)
|
||||||
|
fat_msg(sb, KERN_INFO,
|
||||||
|
"This looks like a DOS 1.x volume; assuming default BPB values");
|
||||||
|
|
||||||
|
memset(bpb, 0, sizeof(*bpb));
|
||||||
|
bpb->fat_sector_size = SECTOR_SIZE;
|
||||||
|
bpb->fat_sec_per_clus = fdefaults->sec_per_clus;
|
||||||
|
bpb->fat_reserved = 1;
|
||||||
|
bpb->fat_fats = 2;
|
||||||
|
bpb->fat_dir_entries = fdefaults->dir_entries;
|
||||||
|
bpb->fat_sectors = fdefaults->nr_sectors;
|
||||||
|
bpb->fat_fat_length = fdefaults->fat_length;
|
||||||
|
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the super block of an MS-DOS FS.
|
* Read the super block of an MS-DOS FS.
|
||||||
*/
|
*/
|
||||||
|
@ -1256,12 +1487,11 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
struct inode *root_inode = NULL, *fat_inode = NULL;
|
struct inode *root_inode = NULL, *fat_inode = NULL;
|
||||||
struct inode *fsinfo_inode = NULL;
|
struct inode *fsinfo_inode = NULL;
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
struct fat_boot_sector *b;
|
struct fat_bios_param_block bpb;
|
||||||
struct msdos_sb_info *sbi;
|
struct msdos_sb_info *sbi;
|
||||||
u16 logical_sector_size;
|
u16 logical_sector_size;
|
||||||
u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
|
u32 total_sectors, total_clusters, fat_clusters, rootdir_sectors;
|
||||||
int debug;
|
int debug;
|
||||||
unsigned int media;
|
|
||||||
long error;
|
long error;
|
||||||
char buf[50];
|
char buf[50];
|
||||||
|
|
||||||
|
@ -1298,100 +1528,72 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = (struct fat_boot_sector *) bh->b_data;
|
error = fat_read_bpb(sb, (struct fat_boot_sector *)bh->b_data, silent,
|
||||||
if (!b->reserved) {
|
&bpb);
|
||||||
if (!silent)
|
if (error == -EINVAL && sbi->options.dos1xfloppy)
|
||||||
fat_msg(sb, KERN_ERR, "bogus number of reserved sectors");
|
error = fat_read_static_bpb(sb,
|
||||||
brelse(bh);
|
(struct fat_boot_sector *)bh->b_data, silent, &bpb);
|
||||||
goto out_invalid;
|
brelse(bh);
|
||||||
}
|
|
||||||
if (!b->fats) {
|
|
||||||
if (!silent)
|
|
||||||
fat_msg(sb, KERN_ERR, "bogus number of FAT structure");
|
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
if (error == -EINVAL)
|
||||||
* Earlier we checked here that b->secs_track and b->head are nonzero,
|
goto out_invalid;
|
||||||
* but it turns out valid FAT filesystems can have zero there.
|
else if (error)
|
||||||
*/
|
goto out_fail;
|
||||||
|
|
||||||
media = b->media;
|
logical_sector_size = bpb.fat_sector_size;
|
||||||
if (!fat_valid_media(media)) {
|
sbi->sec_per_clus = bpb.fat_sec_per_clus;
|
||||||
if (!silent)
|
|
||||||
fat_msg(sb, KERN_ERR, "invalid media value (0x%02x)",
|
|
||||||
media);
|
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
|
||||||
}
|
|
||||||
logical_sector_size = get_unaligned_le16(&b->sector_size);
|
|
||||||
if (!is_power_of_2(logical_sector_size)
|
|
||||||
|| (logical_sector_size < 512)
|
|
||||||
|| (logical_sector_size > 4096)) {
|
|
||||||
if (!silent)
|
|
||||||
fat_msg(sb, KERN_ERR, "bogus logical sector size %u",
|
|
||||||
logical_sector_size);
|
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
|
||||||
}
|
|
||||||
sbi->sec_per_clus = b->sec_per_clus;
|
|
||||||
if (!is_power_of_2(sbi->sec_per_clus)) {
|
|
||||||
if (!silent)
|
|
||||||
fat_msg(sb, KERN_ERR, "bogus sectors per cluster %u",
|
|
||||||
sbi->sec_per_clus);
|
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
error = -EIO;
|
||||||
if (logical_sector_size < sb->s_blocksize) {
|
if (logical_sector_size < sb->s_blocksize) {
|
||||||
fat_msg(sb, KERN_ERR, "logical sector size too small for device"
|
fat_msg(sb, KERN_ERR, "logical sector size too small for device"
|
||||||
" (logical sector size = %u)", logical_sector_size);
|
" (logical sector size = %u)", logical_sector_size);
|
||||||
brelse(bh);
|
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logical_sector_size > sb->s_blocksize) {
|
if (logical_sector_size > sb->s_blocksize) {
|
||||||
brelse(bh);
|
struct buffer_head *bh_resize;
|
||||||
|
|
||||||
if (!sb_set_blocksize(sb, logical_sector_size)) {
|
if (!sb_set_blocksize(sb, logical_sector_size)) {
|
||||||
fat_msg(sb, KERN_ERR, "unable to set blocksize %u",
|
fat_msg(sb, KERN_ERR, "unable to set blocksize %u",
|
||||||
logical_sector_size);
|
logical_sector_size);
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
bh = sb_bread(sb, 0);
|
|
||||||
if (bh == NULL) {
|
/* Verify that the larger boot sector is fully readable */
|
||||||
|
bh_resize = sb_bread(sb, 0);
|
||||||
|
if (bh_resize == NULL) {
|
||||||
fat_msg(sb, KERN_ERR, "unable to read boot sector"
|
fat_msg(sb, KERN_ERR, "unable to read boot sector"
|
||||||
" (logical sector size = %lu)",
|
" (logical sector size = %lu)",
|
||||||
sb->s_blocksize);
|
sb->s_blocksize);
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
b = (struct fat_boot_sector *) bh->b_data;
|
brelse(bh_resize);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&sbi->s_lock);
|
mutex_init(&sbi->s_lock);
|
||||||
sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus;
|
sbi->cluster_size = sb->s_blocksize * sbi->sec_per_clus;
|
||||||
sbi->cluster_bits = ffs(sbi->cluster_size) - 1;
|
sbi->cluster_bits = ffs(sbi->cluster_size) - 1;
|
||||||
sbi->fats = b->fats;
|
sbi->fats = bpb.fat_fats;
|
||||||
sbi->fat_bits = 0; /* Don't know yet */
|
sbi->fat_bits = 0; /* Don't know yet */
|
||||||
sbi->fat_start = le16_to_cpu(b->reserved);
|
sbi->fat_start = bpb.fat_reserved;
|
||||||
sbi->fat_length = le16_to_cpu(b->fat_length);
|
sbi->fat_length = bpb.fat_fat_length;
|
||||||
sbi->root_cluster = 0;
|
sbi->root_cluster = 0;
|
||||||
sbi->free_clusters = -1; /* Don't know yet */
|
sbi->free_clusters = -1; /* Don't know yet */
|
||||||
sbi->free_clus_valid = 0;
|
sbi->free_clus_valid = 0;
|
||||||
sbi->prev_free = FAT_START_ENT;
|
sbi->prev_free = FAT_START_ENT;
|
||||||
sb->s_maxbytes = 0xffffffff;
|
sb->s_maxbytes = 0xffffffff;
|
||||||
|
|
||||||
if (!sbi->fat_length && b->fat32.length) {
|
if (!sbi->fat_length && bpb.fat32_length) {
|
||||||
struct fat_boot_fsinfo *fsinfo;
|
struct fat_boot_fsinfo *fsinfo;
|
||||||
struct buffer_head *fsinfo_bh;
|
struct buffer_head *fsinfo_bh;
|
||||||
|
|
||||||
/* Must be FAT32 */
|
/* Must be FAT32 */
|
||||||
sbi->fat_bits = 32;
|
sbi->fat_bits = 32;
|
||||||
sbi->fat_length = le32_to_cpu(b->fat32.length);
|
sbi->fat_length = bpb.fat32_length;
|
||||||
sbi->root_cluster = le32_to_cpu(b->fat32.root_cluster);
|
sbi->root_cluster = bpb.fat32_root_cluster;
|
||||||
|
|
||||||
/* MC - if info_sector is 0, don't multiply by 0 */
|
/* MC - if info_sector is 0, don't multiply by 0 */
|
||||||
sbi->fsinfo_sector = le16_to_cpu(b->fat32.info_sector);
|
sbi->fsinfo_sector = bpb.fat32_info_sector;
|
||||||
if (sbi->fsinfo_sector == 0)
|
if (sbi->fsinfo_sector == 0)
|
||||||
sbi->fsinfo_sector = 1;
|
sbi->fsinfo_sector = 1;
|
||||||
|
|
||||||
|
@ -1399,7 +1601,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
if (fsinfo_bh == NULL) {
|
if (fsinfo_bh == NULL) {
|
||||||
fat_msg(sb, KERN_ERR, "bread failed, FSINFO block"
|
fat_msg(sb, KERN_ERR, "bread failed, FSINFO block"
|
||||||
" (sector = %lu)", sbi->fsinfo_sector);
|
" (sector = %lu)", sbi->fsinfo_sector);
|
||||||
brelse(bh);
|
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1422,35 +1623,28 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
|
|
||||||
/* interpret volume ID as a little endian 32 bit integer */
|
/* interpret volume ID as a little endian 32 bit integer */
|
||||||
if (sbi->fat_bits == 32)
|
if (sbi->fat_bits == 32)
|
||||||
sbi->vol_id = (((u32)b->fat32.vol_id[0]) |
|
sbi->vol_id = bpb.fat32_vol_id;
|
||||||
((u32)b->fat32.vol_id[1] << 8) |
|
|
||||||
((u32)b->fat32.vol_id[2] << 16) |
|
|
||||||
((u32)b->fat32.vol_id[3] << 24));
|
|
||||||
else /* fat 16 or 12 */
|
else /* fat 16 or 12 */
|
||||||
sbi->vol_id = (((u32)b->fat16.vol_id[0]) |
|
sbi->vol_id = bpb.fat16_vol_id;
|
||||||
((u32)b->fat16.vol_id[1] << 8) |
|
|
||||||
((u32)b->fat16.vol_id[2] << 16) |
|
|
||||||
((u32)b->fat16.vol_id[3] << 24));
|
|
||||||
|
|
||||||
sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
|
sbi->dir_per_block = sb->s_blocksize / sizeof(struct msdos_dir_entry);
|
||||||
sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
|
sbi->dir_per_block_bits = ffs(sbi->dir_per_block) - 1;
|
||||||
|
|
||||||
sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
|
sbi->dir_start = sbi->fat_start + sbi->fats * sbi->fat_length;
|
||||||
sbi->dir_entries = get_unaligned_le16(&b->dir_entries);
|
sbi->dir_entries = bpb.fat_dir_entries;
|
||||||
if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
|
if (sbi->dir_entries & (sbi->dir_per_block - 1)) {
|
||||||
if (!silent)
|
if (!silent)
|
||||||
fat_msg(sb, KERN_ERR, "bogus directory-entries per block"
|
fat_msg(sb, KERN_ERR, "bogus directory-entries per block"
|
||||||
" (%u)", sbi->dir_entries);
|
" (%u)", sbi->dir_entries);
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
goto out_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
rootdir_sectors = sbi->dir_entries
|
rootdir_sectors = sbi->dir_entries
|
||||||
* sizeof(struct msdos_dir_entry) / sb->s_blocksize;
|
* sizeof(struct msdos_dir_entry) / sb->s_blocksize;
|
||||||
sbi->data_start = sbi->dir_start + rootdir_sectors;
|
sbi->data_start = sbi->dir_start + rootdir_sectors;
|
||||||
total_sectors = get_unaligned_le16(&b->sectors);
|
total_sectors = bpb.fat_sectors;
|
||||||
if (total_sectors == 0)
|
if (total_sectors == 0)
|
||||||
total_sectors = le32_to_cpu(b->total_sect);
|
total_sectors = bpb.fat_total_sect;
|
||||||
|
|
||||||
total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
|
total_clusters = (total_sectors - sbi->data_start) / sbi->sec_per_clus;
|
||||||
|
|
||||||
|
@ -1459,9 +1653,9 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
|
|
||||||
/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */
|
/* some OSes set FAT_STATE_DIRTY and clean it on unmount. */
|
||||||
if (sbi->fat_bits == 32)
|
if (sbi->fat_bits == 32)
|
||||||
sbi->dirty = b->fat32.state & FAT_STATE_DIRTY;
|
sbi->dirty = bpb.fat32_state & FAT_STATE_DIRTY;
|
||||||
else /* fat 16 or 12 */
|
else /* fat 16 or 12 */
|
||||||
sbi->dirty = b->fat16.state & FAT_STATE_DIRTY;
|
sbi->dirty = bpb.fat16_state & FAT_STATE_DIRTY;
|
||||||
|
|
||||||
/* check that FAT table does not overflow */
|
/* check that FAT table does not overflow */
|
||||||
fat_clusters = calc_fat_clusters(sb);
|
fat_clusters = calc_fat_clusters(sb);
|
||||||
|
@ -1470,7 +1664,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
if (!silent)
|
if (!silent)
|
||||||
fat_msg(sb, KERN_ERR, "count of clusters too big (%u)",
|
fat_msg(sb, KERN_ERR, "count of clusters too big (%u)",
|
||||||
total_clusters);
|
total_clusters);
|
||||||
brelse(bh);
|
|
||||||
goto out_invalid;
|
goto out_invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1483,8 +1676,6 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat,
|
||||||
if (sbi->prev_free < FAT_START_ENT)
|
if (sbi->prev_free < FAT_START_ENT)
|
||||||
sbi->prev_free = FAT_START_ENT;
|
sbi->prev_free = FAT_START_ENT;
|
||||||
|
|
||||||
brelse(bh);
|
|
||||||
|
|
||||||
/* set up enough so that it can read an inode */
|
/* set up enough so that it can read an inode */
|
||||||
fat_hash_init(sb);
|
fat_hash_init(sb);
|
||||||
dir_hash_init(sb);
|
dir_hash_init(sb);
|
||||||
|
|
|
@ -76,14 +76,14 @@ EXPORT_SYMBOL_GPL(get_max_files);
|
||||||
* Handle nr_files sysctl
|
* Handle nr_files sysctl
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
|
#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
|
||||||
int proc_nr_files(ctl_table *table, int write,
|
int proc_nr_files(struct ctl_table *table, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
files_stat.nr_files = get_nr_files();
|
files_stat.nr_files = get_nr_files();
|
||||||
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
|
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int proc_nr_files(ctl_table *table, int write,
|
int proc_nr_files(struct ctl_table *table, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
|
|
@ -67,7 +67,7 @@ static int fscache_max_active_sysctl(struct ctl_table *table, int write,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctl_table fscache_sysctls[] = {
|
struct ctl_table fscache_sysctls[] = {
|
||||||
{
|
{
|
||||||
.procname = "object_max_active",
|
.procname = "object_max_active",
|
||||||
.data = &fscache_object_max_active,
|
.data = &fscache_object_max_active,
|
||||||
|
@ -87,7 +87,7 @@ ctl_table fscache_sysctls[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
ctl_table fscache_sysctls_root[] = {
|
struct ctl_table fscache_sysctls_root[] = {
|
||||||
{
|
{
|
||||||
.procname = "fscache",
|
.procname = "fscache",
|
||||||
.mode = 0555,
|
.mode = 0555,
|
||||||
|
|
|
@ -54,14 +54,11 @@ int hfsplus_attr_build_key(struct super_block *sb, hfsplus_btree_key *key,
|
||||||
memset(key, 0, sizeof(struct hfsplus_attr_key));
|
memset(key, 0, sizeof(struct hfsplus_attr_key));
|
||||||
key->attr.cnid = cpu_to_be32(cnid);
|
key->attr.cnid = cpu_to_be32(cnid);
|
||||||
if (name) {
|
if (name) {
|
||||||
len = strlen(name);
|
int res = hfsplus_asc2uni(sb,
|
||||||
if (len > HFSPLUS_ATTR_MAX_STRLEN) {
|
|
||||||
pr_err("invalid xattr name's length\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
hfsplus_asc2uni(sb,
|
|
||||||
(struct hfsplus_unistr *)&key->attr.key_name,
|
(struct hfsplus_unistr *)&key->attr.key_name,
|
||||||
HFSPLUS_ATTR_MAX_STRLEN, name, len);
|
HFSPLUS_ATTR_MAX_STRLEN, name, strlen(name));
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
len = be16_to_cpu(key->attr.key_name.length);
|
len = be16_to_cpu(key->attr.key_name.length);
|
||||||
} else {
|
} else {
|
||||||
key->attr.key_name.length = 0;
|
key->attr.key_name.length = 0;
|
||||||
|
@ -82,31 +79,6 @@ int hfsplus_attr_build_key(struct super_block *sb, hfsplus_btree_key *key,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hfsplus_attr_build_key_uni(hfsplus_btree_key *key,
|
|
||||||
u32 cnid,
|
|
||||||
struct hfsplus_attr_unistr *name)
|
|
||||||
{
|
|
||||||
int ustrlen;
|
|
||||||
|
|
||||||
memset(key, 0, sizeof(struct hfsplus_attr_key));
|
|
||||||
ustrlen = be16_to_cpu(name->length);
|
|
||||||
key->attr.cnid = cpu_to_be32(cnid);
|
|
||||||
key->attr.key_name.length = cpu_to_be16(ustrlen);
|
|
||||||
ustrlen *= 2;
|
|
||||||
memcpy(key->attr.key_name.unicode, name->unicode, ustrlen);
|
|
||||||
|
|
||||||
/* The length of the key, as stored in key_len field, does not include
|
|
||||||
* the size of the key_len field itself.
|
|
||||||
* So, offsetof(hfsplus_attr_key, key_name) is a trick because
|
|
||||||
* it takes into consideration key_len field (__be16) of
|
|
||||||
* hfsplus_attr_key structure instead of length field (__be16) of
|
|
||||||
* hfsplus_attr_unistr structure.
|
|
||||||
*/
|
|
||||||
key->key_len =
|
|
||||||
cpu_to_be16(offsetof(struct hfsplus_attr_key, key_name) +
|
|
||||||
ustrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
hfsplus_attr_entry *hfsplus_alloc_attr_entry(void)
|
hfsplus_attr_entry *hfsplus_alloc_attr_entry(void)
|
||||||
{
|
{
|
||||||
return kmem_cache_alloc(hfsplus_attr_tree_cachep, GFP_KERNEL);
|
return kmem_cache_alloc(hfsplus_attr_tree_cachep, GFP_KERNEL);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue