提交 dfe2c6dc 编写于 作者: L Linus Torvalds

Merge branch 'akpm' (patches from Andrew Morton)

Merge second patch-bomb from Andrew Morton:
 - a few hotfixes
 - drivers/dma updates
 - MAINTAINERS updates
 - Quite a lot of lib/ updates
 - checkpatch updates
 - binfmt updates
 - autofs4
 - drivers/rtc/
 - various small tweaks to less used filesystems
 - ipc/ updates
 - kernel/watchdog.c changes

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (135 commits)
  mm: softdirty: enable write notifications on VMAs after VM_SOFTDIRTY cleared
  kernel/param: consolidate __{start,stop}___param[] in <linux/moduleparam.h>
  ia64: remove duplicate declarations of __per_cpu_start[] and __per_cpu_end[]
  frv: remove unused declarations of __start___ex_table and __stop___ex_table
  kvm: ensure hard lockup detection is disabled by default
  kernel/watchdog.c: control hard lockup detection default
  staging: rtl8192u: use %*pEn to escape buffer
  staging: rtl8192e: use %*pEn to escape buffer
  staging: wlan-ng: use %*pEhp to print SN
  lib80211: remove unused print_ssid()
  wireless: hostap: proc: print properly escaped SSID
  wireless: ipw2x00: print SSID via %*pE
  wireless: libertas: print esaped string via %*pE
  lib/vsprintf: add %*pE[achnops] format specifier
  lib / string_helpers: introduce string_escape_mem()
  lib / string_helpers: refactoring the test suite
  lib / string_helpers: move documentation to c-file
  include/linux: remove strict_strto* definitions
  arch/x86/mm/numa.c: fix boot failure when all nodes are hotpluggable
  fs: check bh blocknr earlier when searching lru
  ...
...@@ -15,39 +15,50 @@ First you must mount binfmt_misc: ...@@ -15,39 +15,50 @@ First you must mount binfmt_misc:
mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
To actually register a new binary type, you have to set up a string looking like To actually register a new binary type, you have to set up a string looking like
:name:type:offset:magic:mask:interpreter:flags (where you can choose the ':' upon :name:type:offset:magic:mask:interpreter:flags (where you can choose the ':'
your needs) and echo it to /proc/sys/fs/binfmt_misc/register. upon your needs) and echo it to /proc/sys/fs/binfmt_misc/register.
Here is what the fields mean: Here is what the fields mean:
- 'name' is an identifier string. A new /proc file will be created with this - 'name' is an identifier string. A new /proc file will be created with this
name below /proc/sys/fs/binfmt_misc name below /proc/sys/fs/binfmt_misc; cannot contain slashes '/' for obvious
reasons.
- 'type' is the type of recognition. Give 'M' for magic and 'E' for extension. - 'type' is the type of recognition. Give 'M' for magic and 'E' for extension.
- 'offset' is the offset of the magic/mask in the file, counted in bytes. This - 'offset' is the offset of the magic/mask in the file, counted in bytes. This
defaults to 0 if you omit it (i.e. you write ':name:type::magic...') defaults to 0 if you omit it (i.e. you write ':name:type::magic...'). Ignored
when using filename extension matching.
- 'magic' is the byte sequence binfmt_misc is matching for. The magic string - 'magic' is the byte sequence binfmt_misc is matching for. The magic string
may contain hex-encoded characters like \x0a or \xA4. In a shell environment may contain hex-encoded characters like \x0a or \xA4. Note that you must
you will have to write \\x0a to prevent the shell from eating your \. escape any NUL bytes; parsing halts at the first one. In a shell environment
you might have to write \\x0a to prevent the shell from eating your \.
If you chose filename extension matching, this is the extension to be If you chose filename extension matching, this is the extension to be
recognised (without the '.', the \x0a specials are not allowed). Extension recognised (without the '.', the \x0a specials are not allowed). Extension
matching is case sensitive! matching is case sensitive, and slashes '/' are not allowed!
- 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some - 'mask' is an (optional, defaults to all 0xff) mask. You can mask out some
bits from matching by supplying a string like magic and as long as magic. bits from matching by supplying a string like magic and as long as magic.
The mask is anded with the byte sequence of the file. The mask is anded with the byte sequence of the file. Note that you must
escape any NUL bytes; parsing halts at the first one. Ignored when using
filename extension matching.
- 'interpreter' is the program that should be invoked with the binary as first - 'interpreter' is the program that should be invoked with the binary as first
argument (specify the full path) argument (specify the full path)
- 'flags' is an optional field that controls several aspects of the invocation - 'flags' is an optional field that controls several aspects of the invocation
of the interpreter. It is a string of capital letters, each controls a certain of the interpreter. It is a string of capital letters, each controls a
aspect. The following flags are supported - certain aspect. The following flags are supported -
'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite
original argv[0] with the full path to the binary. When this flag is the original argv[0] with the full path to the binary. When this
included, binfmt_misc will add an argument to the argument vector for flag is included, binfmt_misc will add an argument to the argument
this purpose, thus preserving the original argv[0]. vector for this purpose, thus preserving the original argv[0].
e.g. If your interp is set to /bin/foo and you run `blah` (which is
in /usr/local/bin), then the kernel will execute /bin/foo with
argv[] set to ["/bin/foo", "/usr/local/bin/blah", "blah"]. The
interp has to be aware of this so it can execute /usr/local/bin/blah
with argv[] set to ["blah"].
'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path
of the binary to the interpreter as an argument. When this flag is of the binary to the interpreter as an argument. When this flag is
included, binfmt_misc will open the file for reading and pass its included, binfmt_misc will open the file for reading and pass its
descriptor as an argument, instead of the full path, thus allowing descriptor as an argument, instead of the full path, thus allowing
the interpreter to execute non-readable binaries. This feature should the interpreter to execute non-readable binaries. This feature
be used with care - the interpreter has to be trusted not to emit should be used with care - the interpreter has to be trusted not to
the contents of the non-readable binary. emit the contents of the non-readable binary.
'C' - credentials. Currently, the behavior of binfmt_misc is to calculate 'C' - credentials. Currently, the behavior of binfmt_misc is to calculate
the credentials and security token of the new process according to the credentials and security token of the new process according to
the interpreter. When this flag is included, these attributes are the interpreter. When this flag is included, these attributes are
...@@ -58,7 +69,7 @@ Here is what the fields mean: ...@@ -58,7 +69,7 @@ Here is what the fields mean:
There are some restrictions: There are some restrictions:
- the whole register string may not exceed 255 characters - the whole register string may not exceed 1920 characters
- the magic must reside in the first 128 bytes of the file, i.e. - the magic must reside in the first 128 bytes of the file, i.e.
offset+size(magic) has to be less than 128 offset+size(magic) has to be less than 128
- the interpreter string may not exceed 127 characters - the interpreter string may not exceed 127 characters
...@@ -110,7 +121,4 @@ passes it the full filename (or the file descriptor) to use. Using $PATH can ...@@ -110,7 +121,4 @@ passes it the full filename (or the file descriptor) to use. Using $PATH can
cause unexpected behaviour and can be a security hazard. cause unexpected behaviour and can be a security hazard.
There is a web page about binfmt_misc at
http://www.tat.physik.uni-tuebingen.de
Richard Günther <rguenth@tat.physik.uni-tuebingen.de> Richard Günther <rguenth@tat.physik.uni-tuebingen.de>
* TI BQ32000 I2C Serial Real-Time Clock
Required properties:
- compatible: Should contain "ti,bq32000".
- reg: I2C address for chip
Optional properties:
- trickle-resistor-ohms : Selected resistor for trickle charger
Values usable are 1120 and 20180
Should be given if trickle charger should be enabled
- trickle-diode-disable : Do not use internal trickle charger diode
Should be given if internal trickle charger diode should be disabled
Example:
bq32000: rtc@68 {
compatible = "ti,bq32000";
trickle-resistor-ohms = <1120>;
reg = <0x68>;
};
...@@ -35,7 +35,6 @@ catalyst,24c32 i2c serial eeprom ...@@ -35,7 +35,6 @@ catalyst,24c32 i2c serial eeprom
cirrus,cs42l51 Cirrus Logic CS42L51 audio codec cirrus,cs42l51 Cirrus Logic CS42L51 audio codec
dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock dallas,ds1307 64 x 8, Serial, I2C Real-Time Clock
dallas,ds1338 I2C RTC with 56-Byte NV RAM dallas,ds1338 I2C RTC with 56-Byte NV RAM
dallas,ds1339 I2C Serial Real-Time Clock
dallas,ds1340 I2C RTC with Trickle Charger dallas,ds1340 I2C RTC with Trickle Charger
dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output dallas,ds1374 I2C, 32-Bit Binary Counter Watchdog RTC with Trickle Charger and Reset Input/Output
dallas,ds1631 High-Precision Digital Thermometer dallas,ds1631 High-Precision Digital Thermometer
......
* Dallas DS1339 I2C Serial Real-Time Clock
Required properties:
- compatible: Should contain "dallas,ds1339".
- reg: I2C address for chip
Optional properties:
- trickle-resistor-ohms : Selected resistor for trickle charger
Values usable for ds1339 are 250, 2000, 4000
Should be given if trickle charger should be enabled
- trickle-diode-disable : Do not use internal trickle charger diode
Should be given if internal trickle charger diode should be disabled
Example:
ds1339: rtc@68 {
compatible = "dallas,ds1339";
trickle-resistor-ohms = <250>;
reg = <0x68>;
};
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
Required properties: Required properties:
- compatible: should be one of the following. - compatible: should be one of the following.
* "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc. * "samsung,s3c2410-rtc" - for controllers compatible with s3c2410 rtc.
* "samsung,s3c2416-rtc" - for controllers compatible with s3c2416 rtc.
* "samsung,s3c2443-rtc" - for controllers compatible with s3c2443 rtc.
* "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc. * "samsung,s3c6410-rtc" - for controllers compatible with s3c6410 rtc.
* "samsung,exynos3250-rtc" - for controllers compatible with exynos3250 rtc.
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- interrupts: Two interrupt numbers to the cpu should be specified. First - interrupts: Two interrupt numbers to the cpu should be specified. First
......
此差异已折叠。
...@@ -70,6 +70,38 @@ DMA addresses types dma_addr_t: ...@@ -70,6 +70,38 @@ DMA addresses types dma_addr_t:
For printing a dma_addr_t type which can vary based on build options, For printing a dma_addr_t type which can vary based on build options,
regardless of the width of the CPU data path. Passed by reference. regardless of the width of the CPU data path. Passed by reference.
Raw buffer as an escaped string:
%*pE[achnops]
For printing raw buffer as an escaped string. For the following buffer
1b 62 20 5c 43 07 22 90 0d 5d
few examples show how the conversion would be done (the result string
without surrounding quotes):
%*pE "\eb \C\a"\220\r]"
%*pEhp "\x1bb \C\x07"\x90\x0d]"
%*pEa "\e\142\040\\\103\a\042\220\r\135"
The conversion rules are applied according to an optional combination
of flags (see string_escape_mem() kernel documentation for the
details):
a - ESCAPE_ANY
c - ESCAPE_SPECIAL
h - ESCAPE_HEX
n - ESCAPE_NULL
o - ESCAPE_OCTAL
p - ESCAPE_NP
s - ESCAPE_SPACE
By default ESCAPE_ANY_NP is used.
ESCAPE_ANY_NP is the sane choice for many cases, in particularly for
printing SSIDs.
If field width is omitted the 1 byte only will be escaped.
Raw buffer as a hex string: Raw buffer as a hex string:
%*ph 00 01 02 ... 3f %*ph 00 01 02 ... 3f
%*phC 00:01:02: ... :3f %*phC 00:01:02: ... :3f
......
...@@ -190,6 +190,8 @@ core_pattern is used to specify a core dumpfile pattern name. ...@@ -190,6 +190,8 @@ core_pattern is used to specify a core dumpfile pattern name.
%% output one '%' %% output one '%'
%p pid %p pid
%P global pid (init PID namespace) %P global pid (init PID namespace)
%i tid
%I global tid (init PID namespace)
%u uid %u uid
%g gid %g gid
%d dump mode, matches PR_SET_DUMPABLE and %d dump mode, matches PR_SET_DUMPABLE and
......
...@@ -1338,8 +1338,7 @@ ARM/SAMSUNG MOBILE MACHINE SUPPORT ...@@ -1338,8 +1338,7 @@ ARM/SAMSUNG MOBILE MACHINE SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: arch/arm/mach-s5pv210/mach-aquila.c F: arch/arm/mach-s5pv210/
F: arch/arm/mach-s5pv210/mach-goni.c
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
...@@ -1550,6 +1549,7 @@ T: git git://git.xilinx.com/linux-xlnx.git ...@@ -1550,6 +1549,7 @@ T: git git://git.xilinx.com/linux-xlnx.git
S: Supported S: Supported
F: arch/arm/mach-zynq/ F: arch/arm/mach-zynq/
F: drivers/cpuidle/cpuidle-zynq.c F: drivers/cpuidle/cpuidle-zynq.c
F: drivers/block/xsysace.c
N: zynq N: zynq
N: xilinx N: xilinx
F: drivers/clocksource/cadence_ttc_timer.c F: drivers/clocksource/cadence_ttc_timer.c
...@@ -1738,6 +1738,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com> ...@@ -1738,6 +1738,12 @@ M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported S: Supported
F: drivers/net/ethernet/cadence/ F: drivers/net/ethernet/cadence/
ATMEL NAND DRIVER
M: Josh Wu <josh.wu@atmel.com>
L: linux-mtd@lists.infradead.org
S: Supported
F: drivers/mtd/nand/atmel_nand*
ATMEL SPI DRIVER ATMEL SPI DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com> M: Nicolas Ferre <nicolas.ferre@atmel.com>
S: Supported S: Supported
...@@ -3048,7 +3054,7 @@ M: Sumit Semwal <sumit.semwal@linaro.org> ...@@ -3048,7 +3054,7 @@ M: Sumit Semwal <sumit.semwal@linaro.org>
S: Maintained S: Maintained
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
L: linaro-mm-sig@lists.linaro.org L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
F: drivers/dma-buf/ F: drivers/dma-buf/
F: include/linux/dma-buf* F: include/linux/dma-buf*
F: include/linux/reservation.h F: include/linux/reservation.h
...@@ -4297,9 +4303,8 @@ S: Maintained ...@@ -4297,9 +4303,8 @@ S: Maintained
F: drivers/media/dvb-frontends/hd29l2* F: drivers/media/dvb-frontends/hd29l2*
HEWLETT-PACKARD SMART2 RAID DRIVER HEWLETT-PACKARD SMART2 RAID DRIVER
M: Chirag Kantharia <chirag.kantharia@hp.com>
L: iss_storagedev@hp.com L: iss_storagedev@hp.com
S: Maintained S: Orphan
F: Documentation/blockdev/cpqarray.txt F: Documentation/blockdev/cpqarray.txt
F: drivers/block/cpqarray.* F: drivers/block/cpqarray.*
...@@ -5300,6 +5305,13 @@ F: include/linux/lockd/ ...@@ -5300,6 +5305,13 @@ F: include/linux/lockd/
F: include/linux/sunrpc/ F: include/linux/sunrpc/
F: include/uapi/linux/sunrpc/ F: include/uapi/linux/sunrpc/
KERNEL SELFTEST FRAMEWORK
M: Shuah Khan <shuahkh@osg.samsung.com>
L: linux-api@vger.kernel.org
T: git git://git.kernel.org/pub/scm/shuah/linux-kselftest
S: Maintained
F: tools/testing/selftests
KERNEL VIRTUAL MACHINE (KVM) KERNEL VIRTUAL MACHINE (KVM)
M: Gleb Natapov <gleb@kernel.org> M: Gleb Natapov <gleb@kernel.org>
M: Paolo Bonzini <pbonzini@redhat.com> M: Paolo Bonzini <pbonzini@redhat.com>
...@@ -5746,11 +5758,8 @@ T: git git://github.com/linux-test-project/ltp.git ...@@ -5746,11 +5758,8 @@ T: git git://github.com/linux-test-project/ltp.git
S: Maintained S: Maintained
M32R ARCHITECTURE M32R ARCHITECTURE
M: Hirokazu Takata <takata@linux-m32r.org>
L: linux-m32r@ml.linux-m32r.org (moderated for non-subscribers)
L: linux-m32r-ja@ml.linux-m32r.org (in Japanese)
W: http://www.linux-m32r.org/ W: http://www.linux-m32r.org/
S: Maintained S: Orphan
F: arch/m32r/ F: arch/m32r/
M68K ARCHITECTURE M68K ARCHITECTURE
...@@ -7974,7 +7983,6 @@ S: Supported ...@@ -7974,7 +7983,6 @@ S: Supported
F: drivers/mfd/sec*.c F: drivers/mfd/sec*.c
F: drivers/regulator/s2m*.c F: drivers/regulator/s2m*.c
F: drivers/regulator/s5m*.c F: drivers/regulator/s5m*.c
F: drivers/rtc/rtc-sec.c
F: include/linux/mfd/samsung/ F: include/linux/mfd/samsung/
SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS SAMSUNG S5P/EXYNOS4 SOC SERIES CAMERA SUBSYSTEM DRIVERS
...@@ -10315,10 +10323,6 @@ M: John Linn <John.Linn@xilinx.com> ...@@ -10315,10 +10323,6 @@ M: John Linn <John.Linn@xilinx.com>
S: Maintained S: Maintained
F: drivers/net/ethernet/xilinx/xilinx_axienet* F: drivers/net/ethernet/xilinx/xilinx_axienet*
XILINX SYSTEMACE DRIVER
S: Orphan
F: drivers/block/xsysace.c
XILINX UARTLITE SERIAL DRIVER XILINX UARTLITE SERIAL DRIVER
M: Peter Korsgaard <jacmet@sunsite.dk> M: Peter Korsgaard <jacmet@sunsite.dk>
L: linux-serial@vger.kernel.org L: linux-serial@vger.kernel.org
......
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
}; };
rtc: rtc@10070000 { rtc: rtc@10070000 {
compatible = "samsung,s3c6410-rtc"; compatible = "samsung,exynos3250-rtc";
reg = <0x10070000 0x100>; reg = <0x10070000 0x100>;
interrupts = <0 73 0>, <0 74 0>; interrupts = <0 73 0>, <0 74 0>;
status = "disabled"; status = "disabled";
......
...@@ -416,17 +416,17 @@ static struct pxafb_mach_info *lpd270_lcd_to_use; ...@@ -416,17 +416,17 @@ static struct pxafb_mach_info *lpd270_lcd_to_use;
static int __init lpd270_set_lcd(char *str) static int __init lpd270_set_lcd(char *str)
{ {
if (!strnicmp(str, "lq057q3dc02", 11)) { if (!strncasecmp(str, "lq057q3dc02", 11)) {
lpd270_lcd_to_use = &sharp_lq057q3dc02; lpd270_lcd_to_use = &sharp_lq057q3dc02;
} else if (!strnicmp(str, "lq121s1dg31", 11)) { } else if (!strncasecmp(str, "lq121s1dg31", 11)) {
lpd270_lcd_to_use = &sharp_lq121s1dg31; lpd270_lcd_to_use = &sharp_lq121s1dg31;
} else if (!strnicmp(str, "lq036q1da01", 11)) { } else if (!strncasecmp(str, "lq036q1da01", 11)) {
lpd270_lcd_to_use = &sharp_lq036q1da01; lpd270_lcd_to_use = &sharp_lq036q1da01;
} else if (!strnicmp(str, "lq64d343", 8)) { } else if (!strncasecmp(str, "lq64d343", 8)) {
lpd270_lcd_to_use = &sharp_lq64d343; lpd270_lcd_to_use = &sharp_lq64d343;
} else if (!strnicmp(str, "lq10d368", 8)) { } else if (!strncasecmp(str, "lq10d368", 8)) {
lpd270_lcd_to_use = &sharp_lq10d368; lpd270_lcd_to_use = &sharp_lq10d368;
} else if (!strnicmp(str, "lq035q7db02-20", 14)) { } else if (!strncasecmp(str, "lq035q7db02-20", 14)) {
lpd270_lcd_to_use = &sharp_lq035q7db02_20; lpd270_lcd_to_use = &sharp_lq035q7db02_20;
} else { } else {
printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str); printk(KERN_INFO "lpd270: unknown lcd panel [%s]\n", str);
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern const struct exception_table_entry __attribute__((aligned(8))) __start___ex_table[];
extern const struct exception_table_entry __attribute__((aligned(8))) __stop___ex_table[];
extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler; extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler;
extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler; extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler;
extern spinlock_t modlist_lock; extern spinlock_t modlist_lock;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
extern char __per_cpu_start[], __per_cpu_end[], __phys_per_cpu_start[]; extern char __phys_per_cpu_start[];
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern char __cpu0_per_cpu[]; extern char __cpu0_per_cpu[];
#endif #endif
......
...@@ -964,6 +964,7 @@ static void vgetcpu_set_mode(void) ...@@ -964,6 +964,7 @@ static void vgetcpu_set_mode(void)
vgetcpu_mode = VGETCPU_LSL; vgetcpu_mode = VGETCPU_LSL;
} }
#ifdef CONFIG_IA32_EMULATION
/* May not be __init: called during resume */ /* May not be __init: called during resume */
static void syscall32_cpu_init(void) static void syscall32_cpu_init(void)
{ {
...@@ -975,7 +976,8 @@ static void syscall32_cpu_init(void) ...@@ -975,7 +976,8 @@ static void syscall32_cpu_init(void)
wrmsrl(MSR_CSTAR, ia32_cstar_target); wrmsrl(MSR_CSTAR, ia32_cstar_target);
} }
#endif #endif /* CONFIG_IA32_EMULATION */
#endif /* CONFIG_X86_64 */
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
void enable_sep_cpu(void) void enable_sep_cpu(void)
......
...@@ -237,7 +237,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced, ...@@ -237,7 +237,7 @@ static void fill_up_crash_elf_data(struct crash_elf_data *ced,
ced->max_nr_ranges++; ced->max_nr_ranges++;
/* If crashk_low_res is not 0, another range split possible */ /* If crashk_low_res is not 0, another range split possible */
if (crashk_low_res.end != 0) if (crashk_low_res.end)
ced->max_nr_ranges++; ced->max_nr_ranges++;
} }
...@@ -335,9 +335,11 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced, ...@@ -335,9 +335,11 @@ static int elf_header_exclude_ranges(struct crash_elf_data *ced,
if (ret) if (ret)
return ret; return ret;
ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end); if (crashk_low_res.end) {
if (ret) ret = exclude_mem_range(cmem, crashk_low_res.start, crashk_low_res.end);
return ret; if (ret)
return ret;
}
/* Exclude GART region */ /* Exclude GART region */
if (ced->gart_end) { if (ced->gart_end) {
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/crash.h> #include <asm/crash.h>
#include <asm/efi.h> #include <asm/efi.h>
#include <asm/kexec-bzimage64.h>
#define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */ #define MAX_ELFCOREHDR_STR_LEN 30 /* elfcorehdr=0x<64bit-value> */
...@@ -267,7 +268,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params, ...@@ -267,7 +268,7 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
return ret; return ret;
} }
int bzImage64_probe(const char *buf, unsigned long len) static int bzImage64_probe(const char *buf, unsigned long len)
{ {
int ret = -ENOEXEC; int ret = -ENOEXEC;
struct setup_header *header; struct setup_header *header;
...@@ -325,10 +326,10 @@ int bzImage64_probe(const char *buf, unsigned long len) ...@@ -325,10 +326,10 @@ int bzImage64_probe(const char *buf, unsigned long len)
return ret; return ret;
} }
void *bzImage64_load(struct kimage *image, char *kernel, static void *bzImage64_load(struct kimage *image, char *kernel,
unsigned long kernel_len, char *initrd, unsigned long kernel_len, char *initrd,
unsigned long initrd_len, char *cmdline, unsigned long initrd_len, char *cmdline,
unsigned long cmdline_len) unsigned long cmdline_len)
{ {
struct setup_header *header; struct setup_header *header;
...@@ -514,7 +515,7 @@ void *bzImage64_load(struct kimage *image, char *kernel, ...@@ -514,7 +515,7 @@ void *bzImage64_load(struct kimage *image, char *kernel,
} }
/* This cleanup function is called after various segments have been loaded */ /* This cleanup function is called after various segments have been loaded */
int bzImage64_cleanup(void *loader_data) static int bzImage64_cleanup(void *loader_data)
{ {
struct bzimage64_data *ldata = loader_data; struct bzimage64_data *ldata = loader_data;
...@@ -528,7 +529,7 @@ int bzImage64_cleanup(void *loader_data) ...@@ -528,7 +529,7 @@ int bzImage64_cleanup(void *loader_data)
} }
#ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG #ifdef CONFIG_KEXEC_BZIMAGE_VERIFY_SIG
int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len) static int bzImage64_verify_sig(const char *kernel, unsigned long kernel_len)
{ {
bool trusted; bool trusted;
int ret; int ret;
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kprobes.h> #include <linux/kprobes.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/nmi.h>
#include <asm/timer.h> #include <asm/timer.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#include <asm/traps.h> #include <asm/traps.h>
...@@ -499,6 +500,13 @@ void __init kvm_guest_init(void) ...@@ -499,6 +500,13 @@ void __init kvm_guest_init(void)
#else #else
kvm_guest_cpu_init(); kvm_guest_cpu_init();
#endif #endif
/*
* Hard lockup detection is enabled by default. Disable it, as guests
* can get false positives too easily, for example if the host is
* overcommitted.
*/
watchdog_enable_hardlockup_detector(false);
} }
static noinline uint32_t __kvm_cpuid_base(void) static noinline uint32_t __kvm_cpuid_base(void)
......
...@@ -86,6 +86,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, ...@@ -86,6 +86,7 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
pgprot_t prot; pgprot_t prot;
int retval; int retval;
void __iomem *ret_addr; void __iomem *ret_addr;
int ram_region;
/* Don't allow wraparound or zero size */ /* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1; last_addr = phys_addr + size - 1;
...@@ -108,12 +109,23 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr, ...@@ -108,12 +109,23 @@ static void __iomem *__ioremap_caller(resource_size_t phys_addr,
/* /*
* Don't allow anybody to remap normal RAM that we're using.. * Don't allow anybody to remap normal RAM that we're using..
*/ */
pfn = phys_addr >> PAGE_SHIFT; /* First check if whole region can be identified as RAM or not */
last_pfn = last_addr >> PAGE_SHIFT; ram_region = region_is_ram(phys_addr, size);
if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL, if (ram_region > 0) {
__ioremap_check_ram) == 1) WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n",
(unsigned long int)phys_addr,
(unsigned long int)last_addr);
return NULL; return NULL;
}
/* If could not be identified(-1), check page by page */
if (ram_region < 0) {
pfn = phys_addr >> PAGE_SHIFT;
last_pfn = last_addr >> PAGE_SHIFT;
if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
__ioremap_check_ram) == 1)
return NULL;
}
/* /*
* Mappings have to be page-aligned * Mappings have to be page-aligned
*/ */
......
...@@ -463,6 +463,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi) ...@@ -463,6 +463,42 @@ static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
return true; return true;
} }
static void __init numa_clear_kernel_node_hotplug(void)
{
int i, nid;
nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
unsigned long start, end;
struct memblock_region *r;
/*
* At this time, all memory regions reserved by memblock are
* used by the kernel. Set the nid in memblock.reserved will
* mark out all the nodes the kernel resides in.
*/
for (i = 0; i < numa_meminfo.nr_blks; i++) {
struct numa_memblk *mb = &numa_meminfo.blk[i];
memblock_set_node(mb->start, mb->end - mb->start,
&memblock.reserved, mb->nid);
}
/* Mark all kernel nodes. */
for_each_memblock(reserved, r)
node_set(r->nid, numa_kernel_nodes);
/* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
for (i = 0; i < numa_meminfo.nr_blks; i++) {
nid = numa_meminfo.blk[i].nid;
if (!node_isset(nid, numa_kernel_nodes))
continue;
start = numa_meminfo.blk[i].start;
end = numa_meminfo.blk[i].end;
memblock_clear_hotplug(start, end - start);
}
}
static int __init numa_register_memblks(struct numa_meminfo *mi) static int __init numa_register_memblks(struct numa_meminfo *mi)
{ {
unsigned long uninitialized_var(pfn_align); unsigned long uninitialized_var(pfn_align);
...@@ -480,6 +516,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi) ...@@ -480,6 +516,15 @@ static int __init numa_register_memblks(struct numa_meminfo *mi)
&memblock.memory, mb->nid); &memblock.memory, mb->nid);
} }
/*
* At very early time, the kernel have to use some memory such as
* loading the kernel image. We cannot prevent this anyway. So any
* node the kernel resides in should be un-hotpluggable.
*
* And when we come here, alloc node data won't fail.
*/
numa_clear_kernel_node_hotplug();
/* /*
* If sections array is gonna be used for pfn -> nid mapping, check * If sections array is gonna be used for pfn -> nid mapping, check
* whether its granularity is fine enough. * whether its granularity is fine enough.
...@@ -548,41 +593,6 @@ static void __init numa_init_array(void) ...@@ -548,41 +593,6 @@ static void __init numa_init_array(void)
} }
} }
static void __init numa_clear_kernel_node_hotplug(void)
{
int i, nid;
nodemask_t numa_kernel_nodes = NODE_MASK_NONE;
unsigned long start, end;
struct memblock_region *r;
/*
* At this time, all memory regions reserved by memblock are
* used by the kernel. Set the nid in memblock.reserved will
* mark out all the nodes the kernel resides in.
*/
for (i = 0; i < numa_meminfo.nr_blks; i++) {
struct numa_memblk *mb = &numa_meminfo.blk[i];
memblock_set_node(mb->start, mb->end - mb->start,
&memblock.reserved, mb->nid);
}
/* Mark all kernel nodes. */
for_each_memblock(reserved, r)
node_set(r->nid, numa_kernel_nodes);
/* Clear MEMBLOCK_HOTPLUG flag for memory in kernel nodes. */
for (i = 0; i < numa_meminfo.nr_blks; i++) {
nid = numa_meminfo.blk[i].nid;
if (!node_isset(nid, numa_kernel_nodes))
continue;
start = numa_meminfo.blk[i].start;
end = numa_meminfo.blk[i].end;
memblock_clear_hotplug(start, end - start);
}
}
static int __init numa_init(int (*init_func)(void)) static int __init numa_init(int (*init_func)(void))
{ {
int i; int i;
...@@ -637,15 +647,6 @@ static int __init numa_init(int (*init_func)(void)) ...@@ -637,15 +647,6 @@ static int __init numa_init(int (*init_func)(void))
} }
numa_init_array(); numa_init_array();
/*
* At very early time, the kernel have to use some memory such as
* loading the kernel image. We cannot prevent this anyway. So any
* node the kernel resides in should be un-hotpluggable.
*
* And when we come here, numa_init() won't fail.
*/
numa_clear_kernel_node_hotplug();
return 0; return 0;
} }
......
...@@ -18,8 +18,9 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE ...@@ -18,8 +18,9 @@ $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
targets += kexec-purgatory.c targets += kexec-purgatory.c
CMD_BIN2C = $(objtree)/scripts/basic/bin2c
quiet_cmd_bin2c = BIN2C $@ quiet_cmd_bin2c = BIN2C $@
cmd_bin2c = cat $(obj)/purgatory.ro | $(objtree)/scripts/basic/bin2c kexec_purgatory > $(obj)/kexec-purgatory.c cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
$(call if_changed,bin2c) $(call if_changed,bin2c)
......
...@@ -14,11 +14,14 @@ struct dma_coherent_mem { ...@@ -14,11 +14,14 @@ struct dma_coherent_mem {
int size; int size;
int flags; int flags;
unsigned long *bitmap; unsigned long *bitmap;
spinlock_t spinlock;
}; };
int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, static int dma_init_coherent_memory(phys_addr_t phys_addr, dma_addr_t device_addr,
dma_addr_t device_addr, size_t size, int flags) size_t size, int flags,
struct dma_coherent_mem **mem)
{ {
struct dma_coherent_mem *dma_mem = NULL;
void __iomem *mem_base = NULL; void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT; int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long); int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
...@@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr, ...@@ -27,40 +30,77 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
goto out; goto out;
if (!size) if (!size)
goto out; goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(phys_addr, size); mem_base = ioremap(phys_addr, size);
if (!mem_base) if (!mem_base)
goto out; goto out;
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL); dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem) if (!dma_mem)
goto out; goto out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL); dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap) if (!dma_mem->bitmap)
goto free1_out; goto out;
dma_mem->virt_base = mem_base;
dma_mem->device_base = device_addr;
dma_mem->pfn_base = PFN_DOWN(phys_addr);
dma_mem->size = pages;
dma_mem->flags = flags;
spin_lock_init(&dma_mem->spinlock);
dev->dma_mem->virt_base = mem_base; *mem = dma_mem;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->pfn_base = PFN_DOWN(phys_addr);
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP) if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP; return DMA_MEMORY_MAP;
return DMA_MEMORY_IO; return DMA_MEMORY_IO;
free1_out: out:
kfree(dev->dma_mem); kfree(dma_mem);
out:
if (mem_base) if (mem_base)
iounmap(mem_base); iounmap(mem_base);
return 0; return 0;
} }
static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
{
if (!mem)
return;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
static int dma_assign_coherent_memory(struct device *dev,
struct dma_coherent_mem *mem)
{
if (dev->dma_mem)
return -EBUSY;
dev->dma_mem = mem;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
return 0;
}
int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
dma_addr_t device_addr, size_t size, int flags)
{
struct dma_coherent_mem *mem;
int ret;
ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags,
&mem);
if (ret == 0)
return 0;
if (dma_assign_coherent_memory(dev, mem) == 0)
return ret;
dma_release_coherent_memory(mem);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory); EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev) void dma_release_declared_memory(struct device *dev)
...@@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev) ...@@ -69,10 +109,8 @@ void dma_release_declared_memory(struct device *dev)
if (!mem) if (!mem)
return; return;
dma_release_coherent_memory(mem);
dev->dma_mem = NULL; dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
} }
EXPORT_SYMBOL(dma_release_declared_memory); EXPORT_SYMBOL(dma_release_declared_memory);
...@@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev, ...@@ -80,6 +118,7 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size) dma_addr_t device_addr, size_t size)
{ {
struct dma_coherent_mem *mem = dev->dma_mem; struct dma_coherent_mem *mem = dev->dma_mem;
unsigned long flags;
int pos, err; int pos, err;
size += device_addr & ~PAGE_MASK; size += device_addr & ~PAGE_MASK;
...@@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev, ...@@ -87,8 +126,11 @@ void *dma_mark_declared_memory_occupied(struct device *dev,
if (!mem) if (!mem)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
spin_lock_irqsave(&mem->spinlock, flags);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT; pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(size)); err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
spin_unlock_irqrestore(&mem->spinlock, flags);
if (err != 0) if (err != 0)
return ERR_PTR(err); return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT); return mem->virt_base + (pos << PAGE_SHIFT);
...@@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, ...@@ -115,6 +157,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
{ {
struct dma_coherent_mem *mem; struct dma_coherent_mem *mem;
int order = get_order(size); int order = get_order(size);
unsigned long flags;
int pageno; int pageno;
if (!dev) if (!dev)
...@@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, ...@@ -124,6 +167,7 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
return 0; return 0;
*ret = NULL; *ret = NULL;
spin_lock_irqsave(&mem->spinlock, flags);
if (unlikely(size > (mem->size << PAGE_SHIFT))) if (unlikely(size > (mem->size << PAGE_SHIFT)))
goto err; goto err;
...@@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size, ...@@ -138,10 +182,12 @@ int dma_alloc_from_coherent(struct device *dev, ssize_t size,
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT); *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
*ret = mem->virt_base + (pageno << PAGE_SHIFT); *ret = mem->virt_base + (pageno << PAGE_SHIFT);
memset(*ret, 0, size); memset(*ret, 0, size);
spin_unlock_irqrestore(&mem->spinlock, flags);
return 1; return 1;
err: err:
spin_unlock_irqrestore(&mem->spinlock, flags);
/* /*
* In the case where the allocation can not be satisfied from the * In the case where the allocation can not be satisfied from the
* per-device area, try to fall back to generic memory if the * per-device area, try to fall back to generic memory if the
...@@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr) ...@@ -171,8 +217,11 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
if (mem && vaddr >= mem->virt_base && vaddr < if (mem && vaddr >= mem->virt_base && vaddr <
(mem->virt_base + (mem->size << PAGE_SHIFT))) { (mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT; int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
unsigned long flags;
spin_lock_irqsave(&mem->spinlock, flags);
bitmap_release_region(mem->bitmap, page, order); bitmap_release_region(mem->bitmap, page, order);
spin_unlock_irqrestore(&mem->spinlock, flags);
return 1; return 1;
} }
return 0; return 0;
...@@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma, ...@@ -218,3 +267,61 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
return 0; return 0;
} }
EXPORT_SYMBOL(dma_mmap_from_coherent); EXPORT_SYMBOL(dma_mmap_from_coherent);
/*
* Support for reserved memory regions defined in device tree
*/
#ifdef CONFIG_OF_RESERVED_MEM
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
{
struct dma_coherent_mem *mem = rmem->priv;
if (!mem &&
dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE,
&mem) != DMA_MEMORY_MAP) {
pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
&rmem->base, (unsigned long)rmem->size / SZ_1M);
return -ENODEV;
}
rmem->priv = mem;
dma_assign_coherent_memory(dev, mem);
return 0;
}
static void rmem_dma_device_release(struct reserved_mem *rmem,
struct device *dev)
{
dev->dma_mem = NULL;
}
static const struct reserved_mem_ops rmem_dma_ops = {
.device_init = rmem_dma_device_init,
.device_release = rmem_dma_device_release,
};
static int __init rmem_dma_setup(struct reserved_mem *rmem)
{
unsigned long node = rmem->fdt_node;
if (of_get_flat_dt_prop(node, "reusable", NULL))
return -EINVAL;
#ifdef CONFIG_ARM
if (!of_get_flat_dt_prop(node, "no-map", NULL)) {
pr_err("Reserved memory: regions without no-map are not yet supported\n");
return -EINVAL;
}
#endif
rmem->ops = &rmem_dma_ops;
pr_info("Reserved memory: created DMA memory pool at %pa, size %ld MiB\n",
&rmem->base, (unsigned long)rmem->size / SZ_1M);
return 0;
}
RESERVEDMEM_OF_DECLARE(dma, "shared-dma-pool", rmem_dma_setup);
#endif
...@@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages, ...@@ -211,3 +211,69 @@ bool dma_release_from_contiguous(struct device *dev, struct page *pages,
{ {
return cma_release(dev_get_cma_area(dev), pages, count); return cma_release(dev_get_cma_area(dev), pages, count);
} }
/*
* Support for reserved memory regions defined in device tree
*/
#ifdef CONFIG_OF_RESERVED_MEM
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
#undef pr_fmt
#define pr_fmt(fmt) fmt
static void rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
{
dev_set_cma_area(dev, rmem->priv);
}
static void rmem_cma_device_release(struct reserved_mem *rmem,
struct device *dev)
{
dev_set_cma_area(dev, NULL);
}
static const struct reserved_mem_ops rmem_cma_ops = {
.device_init = rmem_cma_device_init,
.device_release = rmem_cma_device_release,
};
static int __init rmem_cma_setup(struct reserved_mem *rmem)
{
phys_addr_t align = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
phys_addr_t mask = align - 1;
unsigned long node = rmem->fdt_node;
struct cma *cma;
int err;
if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
of_get_flat_dt_prop(node, "no-map", NULL))
return -EINVAL;
if ((rmem->base & mask) || (rmem->size & mask)) {
pr_err("Reserved memory: incorrect alignment of CMA region\n");
return -EINVAL;
}
err = cma_init_reserved_mem(rmem->base, rmem->size, 0, &cma);
if (err) {
pr_err("Reserved memory: unable to setup CMA region\n");
return err;
}
/* Architecture specific contiguous memory fixup. */
dma_contiguous_early_fixup(rmem->base, rmem->size);
if (of_get_flat_dt_prop(node, "linux,cma-default", NULL))
dma_contiguous_set_default(cma);
rmem->ops = &rmem_cma_ops;
rmem->priv = cma;
pr_info("Reserved memory: created CMA memory pool at %pa, size %ld MiB\n",
&rmem->base, (unsigned long)rmem->size / SZ_1M);
return 0;
}
RESERVEDMEM_OF_DECLARE(cma, "shared-dma-pool", rmem_cma_setup);
#endif
...@@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686 ...@@ -38,6 +38,15 @@ config COMMON_CLK_MAX77686
---help--- ---help---
This driver supports Maxim 77686 crystal oscillator clock. This driver supports Maxim 77686 crystal oscillator clock.
config COMMON_CLK_RK808
tristate "Clock driver for RK808"
depends on MFD_RK808
---help---
This driver supports RK808 crystal oscillator clock. These
multi-function devices have two fixed-rate oscillators,
clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
by control register.
config COMMON_CLK_SI5351 config COMMON_CLK_SI5351
tristate "Clock driver for SiLabs 5351A/B/C" tristate "Clock driver for SiLabs 5351A/B/C"
depends on I2C depends on I2C
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o ...@@ -28,6 +28,7 @@ obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
......
/*
* Clkout driver for Rockchip RK808
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* Author:Chris Zhong <zyw@rock-chips.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/mfd/rk808.h>
#include <linux/i2c.h>
#define RK808_NR_OUTPUT 2
struct rk808_clkout {
struct rk808 *rk808;
struct clk_onecell_data clk_data;
struct clk_hw clkout1_hw;
struct clk_hw clkout2_hw;
};
static unsigned long rk808_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return 32768;
}
static int rk808_clkout2_enable(struct clk_hw *hw, bool enable)
{
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
struct rk808 *rk808 = rk808_clkout->rk808;
return regmap_update_bits(rk808->regmap, RK808_CLK32OUT_REG,
CLK32KOUT2_EN, enable ? CLK32KOUT2_EN : 0);
}
static int rk808_clkout2_prepare(struct clk_hw *hw)
{
return rk808_clkout2_enable(hw, true);
}
static void rk808_clkout2_unprepare(struct clk_hw *hw)
{
rk808_clkout2_enable(hw, false);
}
static int rk808_clkout2_is_prepared(struct clk_hw *hw)
{
struct rk808_clkout *rk808_clkout = container_of(hw,
struct rk808_clkout,
clkout2_hw);
struct rk808 *rk808 = rk808_clkout->rk808;
uint32_t val;
int ret = regmap_read(rk808->regmap, RK808_CLK32OUT_REG, &val);
if (ret < 0)
return ret;
return (val & CLK32KOUT2_EN) ? 1 : 0;
}
static const struct clk_ops rk808_clkout1_ops = {
.recalc_rate = rk808_clkout_recalc_rate,
};
static const struct clk_ops rk808_clkout2_ops = {
.prepare = rk808_clkout2_prepare,
.unprepare = rk808_clkout2_unprepare,
.is_prepared = rk808_clkout2_is_prepared,
.recalc_rate = rk808_clkout_recalc_rate,
};
static int rk808_clkout_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct i2c_client *client = rk808->i2c;
struct device_node *node = client->dev.of_node;
struct clk_init_data init = {};
struct clk **clk_table;
struct rk808_clkout *rk808_clkout;
rk808_clkout = devm_kzalloc(&client->dev,
sizeof(*rk808_clkout), GFP_KERNEL);
if (!rk808_clkout)
return -ENOMEM;
rk808_clkout->rk808 = rk808;
clk_table = devm_kcalloc(&client->dev, RK808_NR_OUTPUT,
sizeof(struct clk *), GFP_KERNEL);
if (!clk_table)
return -ENOMEM;
init.flags = CLK_IS_ROOT;
init.parent_names = NULL;
init.num_parents = 0;
init.name = "rk808-clkout1";
init.ops = &rk808_clkout1_ops;
rk808_clkout->clkout1_hw.init = &init;
/* optional override of the clockname */
of_property_read_string_index(node, "clock-output-names",
0, &init.name);
clk_table[0] = devm_clk_register(&client->dev,
&rk808_clkout->clkout1_hw);
if (IS_ERR(clk_table[0]))
return PTR_ERR(clk_table[0]);
init.name = "rk808-clkout2";
init.ops = &rk808_clkout2_ops;
rk808_clkout->clkout2_hw.init = &init;
/* optional override of the clockname */
of_property_read_string_index(node, "clock-output-names",
1, &init.name);
clk_table[1] = devm_clk_register(&client->dev,
&rk808_clkout->clkout2_hw);
if (IS_ERR(clk_table[1]))
return PTR_ERR(clk_table[1]);
rk808_clkout->clk_data.clks = clk_table;
rk808_clkout->clk_data.clk_num = RK808_NR_OUTPUT;
return of_clk_add_provider(node, of_clk_src_onecell_get,
&rk808_clkout->clk_data);
}
static int rk808_clkout_remove(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct i2c_client *client = rk808->i2c;
struct device_node *node = client->dev.of_node;
of_clk_del_provider(node);
return 0;
}
static struct platform_driver rk808_clkout_driver = {
.probe = rk808_clkout_probe,
.remove = rk808_clkout_remove,
.driver = {
.name = "rk808-clkout",
},
};
module_platform_driver(rk808_clkout_driver);
MODULE_DESCRIPTION("Clkout driver for the rk808 series PMICs");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk808-clkout");
...@@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name) ...@@ -3574,7 +3574,7 @@ static int srpt_parse_i_port_id(u8 i_port_id[16], const char *name)
int ret, rc; int ret, rc;
p = name; p = name;
if (strnicmp(p, "0x", 2) == 0) if (strncasecmp(p, "0x", 2) == 0)
p += 2; p += 2;
ret = -EINVAL; ret = -EINVAL;
len = strlen(p); len = strlen(p);
......
...@@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client, ...@@ -812,7 +812,7 @@ static int edt_ft5x06_ts_identify(struct i2c_client *client,
/* if we find something consistent, stay with that assumption /* if we find something consistent, stay with that assumption
* at least M09 won't send 3 bytes here * at least M09 won't send 3 bytes here
*/ */
if (!(strnicmp(rdbuf + 1, "EP0", 3))) { if (!(strncasecmp(rdbuf + 1, "EP0", 3))) {
tsdata->version = M06; tsdata->version = M06;
/* remove last '$' end marker */ /* remove last '$' end marker */
......
...@@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev) ...@@ -188,6 +188,7 @@ static void r592_host_reset(struct r592_device *dev)
r592_set_mode(dev, dev->parallel_mode); r592_set_mode(dev, dev->parallel_mode);
} }
#ifdef CONFIG_PM_SLEEP
/* Disable all hardware interrupts */ /* Disable all hardware interrupts */
static void r592_clear_interrupts(struct r592_device *dev) static void r592_clear_interrupts(struct r592_device *dev)
{ {
...@@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev) ...@@ -195,6 +196,7 @@ static void r592_clear_interrupts(struct r592_device *dev)
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK); r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK);
r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK); r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK);
} }
#endif
/* Tests if there is an CRC error */ /* Tests if there is an CRC error */
static int r592_test_io_error(struct r592_device *dev) static int r592_test_io_error(struct r592_device *dev)
......
...@@ -454,7 +454,7 @@ static int altera_execute(struct altera_state *astate, ...@@ -454,7 +454,7 @@ static int altera_execute(struct altera_state *astate,
name = &p[str_table + name_id]; name = &p[str_table + name_id];
if (strnicmp(aconf->action, name, strlen(name)) == 0) { if (strncasecmp(aconf->action, name, strlen(name)) == 0) {
action_found = 1; action_found = 1;
current_proc = current_proc =
get_unaligned_be32(&p[action_table + get_unaligned_be32(&p[action_table +
...@@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size, ...@@ -2176,7 +2176,7 @@ static int altera_get_note(u8 *p, s32 program_size,
key_ptr = &p[note_strings + key_ptr = &p[note_strings +
get_unaligned_be32( get_unaligned_be32(
&p[note_table + (8 * i)])]; &p[note_table + (8 * i)])];
if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) && if ((strncasecmp(key, key_ptr, strlen(key_ptr)) == 0) &&
(key != NULL)) { (key != NULL)) {
status = 0; status = 0;
......
...@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) ...@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
local_info_t *local = m->private; local_info_t *local = m->private;
struct list_head *ptr = v; struct list_head *ptr = v;
struct hostap_bss_info *bss; struct hostap_bss_info *bss;
int i;
if (ptr == &local->bss_list) { if (ptr == &local->bss_list) {
seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t" seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t"
...@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) ...@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v)
bss->bssid, bss->last_update, bss->bssid, bss->last_update,
bss->count, bss->capab_info); bss->count, bss->capab_info);
for (i = 0; i < bss->ssid_len; i++) seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid);
seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ?
bss->ssid[i] : '_');
seq_putc(m, '\t'); seq_putc(m, '\t');
seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid); seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid);
......
...@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) ...@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
u32 chan; u32 chan;
char *txratename; char *txratename;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
DECLARE_SSID_BUF(ssid);
/* /*
* TBD: BSSID is usually 00:00:00:00:00:00 here and not * TBD: BSSID is usually 00:00:00:00:00:00 here and not
...@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) ...@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
break; break;
} }
IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n", IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n",
priv->net_dev->name, print_ssid(ssid, essid, essid_len), priv->net_dev->name, essid_len, essid,
txratename, chan, bssid); txratename, chan, bssid);
/* now we copy read ssid into dev */ /* now we copy read ssid into dev */
...@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, ...@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
.host_command_length = ssid_len .host_command_length = ssid_len
}; };
int err; int err;
DECLARE_SSID_BUF(ssid);
IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len)); IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid);
if (ssid_len) if (ssid_len)
memcpy(cmd.host_command_parameters, essid, ssid_len); memcpy(cmd.host_command_parameters, essid, ssid_len);
...@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, ...@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
{ {
DECLARE_SSID_BUF(ssid);
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
"disassociated: '%s' %pM\n", "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid,
print_ssid(ssid, priv->essid, priv->essid_len),
priv->bssid); priv->bssid);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
...@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev, ...@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
char *essid = ""; /* ANY */ char *essid = ""; /* ANY */
int length = 0; int length = 0;
int err = 0; int err = 0;
DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->action_mutex); mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) { if (!(priv->status & STATUS_INITIALIZED)) {
...@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, ...@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
goto done; goto done;
} }
IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length);
print_ssid(ssid, essid, length), length);
priv->essid_len = length; priv->essid_len = length;
memcpy(priv->essid, essid, priv->essid_len); memcpy(priv->essid, essid, priv->essid_len);
...@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev, ...@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
*/ */
struct ipw2100_priv *priv = libipw_priv(dev); struct ipw2100_priv *priv = libipw_priv(dev);
DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically /* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */ * configured ESSID then return that; otherwise return ANY */
if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
IPW_DEBUG_WX("Getting essid: '%s'\n", IPW_DEBUG_WX("Getting essid: '%*pE'\n",
print_ssid(ssid, priv->essid, priv->essid_len)); priv->essid_len, priv->essid);
memcpy(extra, priv->essid, priv->essid_len); memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len; wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */ wrqu->essid.flags = 1; /* active */
......
...@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element ...@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element
*info_element, u16 length, *info_element, u16 length,
struct libipw_network *network) struct libipw_network *network)
{ {
DECLARE_SSID_BUF(ssid);
u8 i; u8 i;
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
char rates_str[64]; char rates_str[64];
...@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element ...@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element
memset(network->ssid + network->ssid_len, 0, memset(network->ssid + network->ssid_len, 0,
IW_ESSID_MAX_SIZE - network->ssid_len); IW_ESSID_MAX_SIZE - network->ssid_len);
LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n",
print_ssid(ssid, network->ssid, network->ssid_len, network->ssid,
network->ssid_len), network->ssid_len);
network->ssid_len);
break; break;
case WLAN_EID_SUPP_RATES: case WLAN_EID_SUPP_RATES:
...@@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r ...@@ -1399,8 +1397,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
struct libipw_network *network, struct libipw_network *network,
struct libipw_rx_stats *stats) struct libipw_rx_stats *stats)
{ {
DECLARE_SSID_BUF(ssid);
network->qos_data.active = 0; network->qos_data.active = 0;
network->qos_data.supported = 0; network->qos_data.supported = 0;
network->qos_data.param_count = 0; network->qos_data.param_count = 0;
...@@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r ...@@ -1447,11 +1443,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r
} }
if (network->mode == 0) { if (network->mode == 0) {
LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' " LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n",
"network.\n", network->ssid_len, network->ssid,
print_ssid(ssid, network->ssid, network->bssid);
network->ssid_len),
network->bssid);
return 1; return 1;
} }
...@@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device ...@@ -1563,11 +1557,9 @@ static void libipw_process_probe_response(struct libipw_device
struct libipw_info_element *info_element = beacon->info_element; struct libipw_info_element *info_element = beacon->info_element;
#endif #endif
unsigned long flags; unsigned long flags;
DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_SCAN("'%s' (%pM" LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
"): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", info_element->len, info_element->data,
print_ssid(ssid, info_element->data, info_element->len),
beacon->header.addr3, beacon->header.addr3,
(beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
(beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
...@@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device ...@@ -1587,12 +1579,11 @@ static void libipw_process_probe_response(struct libipw_device
(beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
if (libipw_network_init(ieee, beacon, &network, stats)) { if (libipw_network_init(ieee, beacon, &network, stats)) {
LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n",
print_ssid(ssid, info_element->data, info_element->len, info_element->data,
info_element->len), beacon->header.addr3,
beacon->header.addr3, is_beacon(beacon->header.frame_ctl) ?
is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE");
"BEACON" : "PROBE RESPONSE");
return; return;
} }
...@@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device ...@@ -1624,11 +1615,9 @@ static void libipw_process_probe_response(struct libipw_device
/* If there are no more slots, expire the oldest */ /* If there are no more slots, expire the oldest */
list_del(&oldest->list); list_del(&oldest->list);
target = oldest; target = oldest;
LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from " LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
"network list.\n", target->ssid_len, target->ssid,
print_ssid(ssid, target->ssid, target->bssid);
target->ssid_len),
target->bssid);
libipw_network_reset(target); libipw_network_reset(target);
} else { } else {
/* Otherwise just pull from the free list */ /* Otherwise just pull from the free list */
...@@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device ...@@ -1638,23 +1627,21 @@ static void libipw_process_probe_response(struct libipw_device
} }
#ifdef CONFIG_LIBIPW_DEBUG #ifdef CONFIG_LIBIPW_DEBUG
LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n",
print_ssid(ssid, network.ssid, network.ssid_len, network.ssid,
network.ssid_len), network.bssid,
network.bssid, is_beacon(beacon->header.frame_ctl) ?
is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE");
"BEACON" : "PROBE RESPONSE");
#endif #endif
memcpy(target, &network, sizeof(*target)); memcpy(target, &network, sizeof(*target));
network.ibss_dfs = NULL; network.ibss_dfs = NULL;
list_add_tail(&target->list, &ieee->network_list); list_add_tail(&target->list, &ieee->network_list);
} else { } else {
LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
print_ssid(ssid, target->ssid, target->ssid_len, target->ssid,
target->ssid_len), target->bssid,
target->bssid, is_beacon(beacon->header.frame_ctl) ?
is_beacon(beacon->header.frame_ctl) ? "BEACON" : "PROBE RESPONSE");
"BEACON" : "PROBE RESPONSE");
update_network(target, &network); update_network(target, &network);
network.ibss_dfs = NULL; network.ibss_dfs = NULL;
} }
......
...@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee, ...@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
char *ev = extra; char *ev = extra;
char *stop = ev + wrqu->data.length; char *stop = ev + wrqu->data.length;
int i = 0; int i = 0;
DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("Getting scan\n"); LIBIPW_DEBUG_WX("Getting scan\n");
...@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee, ...@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee,
ev = libipw_translate_scan(ieee, ev, stop, network, ev = libipw_translate_scan(ieee, ev, stop, network,
info); info);
else { else {
LIBIPW_DEBUG_SCAN("Not showing network '%s (" LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n",
"%pM)' due to age (%ums).\n", network->ssid_len, network->ssid,
print_ssid(ssid, network->ssid, network->bssid,
network->ssid_len), elapsed_jiffies_msecs(
network->bssid,
elapsed_jiffies_msecs(
network->last_scanned)); network->last_scanned));
} }
} }
...@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee, ...@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
int i, key, key_provided, len; int i, key, key_provided, len;
struct lib80211_crypt_data **crypt; struct lib80211_crypt_data **crypt;
int host_crypto = ieee->host_encrypt || ieee->host_decrypt; int host_crypto = ieee->host_encrypt || ieee->host_decrypt;
DECLARE_SSID_BUF(ssid);
LIBIPW_DEBUG_WX("SET_ENCODE\n"); LIBIPW_DEBUG_WX("SET_ENCODE\n");
...@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee, ...@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee,
if (len > erq->length) if (len > erq->length)
memset(sec.keys[key] + erq->length, 0, memset(sec.keys[key] + erq->length, 0,
len - erq->length); len - erq->length);
LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n",
key, print_ssid(ssid, sec.keys[key], len), key, len, sec.keys[key],
erq->length, len); erq->length, len);
sec.key_sizes[key] = len; sec.key_sizes[key] = len;
if (*crypt) if (*crypt)
......
...@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, ...@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
int chan_no = -1; int chan_no = -1;
const u8 *ssid = NULL; const u8 *ssid = NULL;
u8 ssid_len = 0; u8 ssid_len = 0;
DECLARE_SSID_BUF(ssid_buf);
int len = get_unaligned_le16(pos); int len = get_unaligned_le16(pos);
pos += 2; pos += 2;
...@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, ...@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
struct ieee80211_channel *channel = struct ieee80211_channel *channel =
ieee80211_get_channel(wiphy, freq); ieee80211_get_channel(wiphy, freq);
lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, " lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n",
"%d dBm\n", bssid, capa, chan_no, ssid_len, ssid,
bssid, capa, chan_no,
print_ssid(ssid_buf, ssid, ssid_len),
LBS_SCAN_RSSI_TO_MBM(rssi)/100); LBS_SCAN_RSSI_TO_MBM(rssi)/100);
if (channel && if (channel &&
...@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, ...@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
struct lbs_private *priv = wiphy_priv(wiphy); struct lbs_private *priv = wiphy_priv(wiphy);
int ret = 0; int ret = 0;
struct cfg80211_bss *bss; struct cfg80211_bss *bss;
DECLARE_SSID_BUF(ssid_buf);
if (dev == priv->mesh_dev) if (dev == priv->mesh_dev)
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
...@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, ...@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
{ {
struct cmd_ds_mesh_config cmd; struct cmd_ds_mesh_config cmd;
struct mrvl_meshie *ie; struct mrvl_meshie *ie;
DECLARE_SSID_BUF(ssid);
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.channel = cpu_to_le16(chan); cmd.channel = cpu_to_le16(chan);
...@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, ...@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
default: default:
return -1; return -1;
} }
lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n",
action, priv->mesh_tlv, chan, action, priv->mesh_tlv, chan, priv->mesh_ssid_len,
print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); priv->mesh_ssid);
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
} }
......
...@@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data( ...@@ -8878,13 +8878,13 @@ static int __must_check __init get_thinkpad_model_data(
} }
s = dmi_get_system_info(DMI_PRODUCT_VERSION); s = dmi_get_system_info(DMI_PRODUCT_VERSION);
if (s && !(strnicmp(s, "ThinkPad", 8) && strnicmp(s, "Lenovo", 6))) { if (s && !(strncasecmp(s, "ThinkPad", 8) && strncasecmp(s, "Lenovo", 6))) {
tp->model_str = kstrdup(s, GFP_KERNEL); tp->model_str = kstrdup(s, GFP_KERNEL);
if (!tp->model_str) if (!tp->model_str)
return -ENOMEM; return -ENOMEM;
} else { } else {
s = dmi_get_system_info(DMI_BIOS_VENDOR); s = dmi_get_system_info(DMI_BIOS_VENDOR);
if (s && !(strnicmp(s, "Lenovo", 6))) { if (s && !(strncasecmp(s, "Lenovo", 6))) {
tp->model_str = kstrdup(s, GFP_KERNEL); tp->model_str = kstrdup(s, GFP_KERNEL);
if (!tp->model_str) if (!tp->model_str)
return -ENOMEM; return -ENOMEM;
......
...@@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev, ...@@ -346,41 +346,41 @@ static ssize_t resources_store(struct device *dmdev,
} }
buf = skip_spaces(buf); buf = skip_spaces(buf);
if (!strnicmp(buf, "disable", 7)) { if (!strncasecmp(buf, "disable", 7)) {
retval = pnp_disable_dev(dev); retval = pnp_disable_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "activate", 8)) { if (!strncasecmp(buf, "activate", 8)) {
retval = pnp_activate_dev(dev); retval = pnp_activate_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "fill", 4)) { if (!strncasecmp(buf, "fill", 4)) {
if (dev->active) if (dev->active)
goto done; goto done;
retval = pnp_auto_config_dev(dev); retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "auto", 4)) { if (!strncasecmp(buf, "auto", 4)) {
if (dev->active) if (dev->active)
goto done; goto done;
pnp_init_resources(dev); pnp_init_resources(dev);
retval = pnp_auto_config_dev(dev); retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "clear", 5)) { if (!strncasecmp(buf, "clear", 5)) {
if (dev->active) if (dev->active)
goto done; goto done;
pnp_init_resources(dev); pnp_init_resources(dev);
goto done; goto done;
} }
if (!strnicmp(buf, "get", 3)) { if (!strncasecmp(buf, "get", 3)) {
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
if (pnp_can_read(dev)) if (pnp_can_read(dev))
dev->protocol->get(dev); dev->protocol->get(dev);
mutex_unlock(&pnp_res_mutex); mutex_unlock(&pnp_res_mutex);
goto done; goto done;
} }
if (!strnicmp(buf, "set", 3)) { if (!strncasecmp(buf, "set", 3)) {
resource_size_t start; resource_size_t start;
resource_size_t end; resource_size_t end;
unsigned long flags; unsigned long flags;
...@@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev, ...@@ -392,31 +392,31 @@ static ssize_t resources_store(struct device *dmdev,
mutex_lock(&pnp_res_mutex); mutex_lock(&pnp_res_mutex);
while (1) { while (1) {
buf = skip_spaces(buf); buf = skip_spaces(buf);
if (!strnicmp(buf, "io", 2)) { if (!strncasecmp(buf, "io", 2)) {
buf = pnp_get_resource_value(buf + 2, buf = pnp_get_resource_value(buf + 2,
IORESOURCE_IO, IORESOURCE_IO,
&start, &end, &start, &end,
&flags); &flags);
pnp_add_io_resource(dev, start, end, flags); pnp_add_io_resource(dev, start, end, flags);
} else if (!strnicmp(buf, "mem", 3)) { } else if (!strncasecmp(buf, "mem", 3)) {
buf = pnp_get_resource_value(buf + 3, buf = pnp_get_resource_value(buf + 3,
IORESOURCE_MEM, IORESOURCE_MEM,
&start, &end, &start, &end,
&flags); &flags);
pnp_add_mem_resource(dev, start, end, flags); pnp_add_mem_resource(dev, start, end, flags);
} else if (!strnicmp(buf, "irq", 3)) { } else if (!strncasecmp(buf, "irq", 3)) {
buf = pnp_get_resource_value(buf + 3, buf = pnp_get_resource_value(buf + 3,
IORESOURCE_IRQ, IORESOURCE_IRQ,
&start, NULL, &start, NULL,
&flags); &flags);
pnp_add_irq_resource(dev, start, flags); pnp_add_irq_resource(dev, start, flags);
} else if (!strnicmp(buf, "dma", 3)) { } else if (!strncasecmp(buf, "dma", 3)) {
buf = pnp_get_resource_value(buf + 3, buf = pnp_get_resource_value(buf + 3,
IORESOURCE_DMA, IORESOURCE_DMA,
&start, NULL, &start, NULL,
&flags); &flags);
pnp_add_dma_resource(dev, start, flags); pnp_add_dma_resource(dev, start, flags);
} else if (!strnicmp(buf, "bus", 3)) { } else if (!strncasecmp(buf, "bus", 3)) {
buf = pnp_get_resource_value(buf + 3, buf = pnp_get_resource_value(buf + 3,
IORESOURCE_BUS, IORESOURCE_BUS,
&start, &end, &start, &end,
......
...@@ -288,6 +288,26 @@ config RTC_DRV_MAX77686 ...@@ -288,6 +288,26 @@ config RTC_DRV_MAX77686
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-max77686. will be called rtc-max77686.
config RTC_DRV_RK808
tristate "Rockchip RK808 RTC"
depends on MFD_RK808
help
If you say yes here you will get support for the
RTC of RK808 PMIC.
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
config RTC_DRV_MAX77802
tristate "Maxim 77802 RTC"
depends on MFD_MAX77686
help
If you say yes here you will get support for the
RTC of Maxim MAX77802 PMIC.
This driver can also be built as a module. If so, the module
will be called rtc-max77802.
config RTC_DRV_RS5C372 config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help help
...@@ -732,6 +752,7 @@ config RTC_DRV_DS1216 ...@@ -732,6 +752,7 @@ config RTC_DRV_DS1216
config RTC_DRV_DS1286 config RTC_DRV_DS1286
tristate "Dallas DS1286" tristate "Dallas DS1286"
depends on HAS_IOMEM
help help
If you say yes here you get support for the Dallas DS1286 RTC chips. If you say yes here you get support for the Dallas DS1286 RTC chips.
...@@ -743,6 +764,7 @@ config RTC_DRV_DS1302 ...@@ -743,6 +764,7 @@ config RTC_DRV_DS1302
config RTC_DRV_DS1511 config RTC_DRV_DS1511
tristate "Dallas DS1511" tristate "Dallas DS1511"
depends on HAS_IOMEM
help help
If you say yes here you get support for the If you say yes here you get support for the
Dallas DS1511 timekeeping/watchdog chip. Dallas DS1511 timekeeping/watchdog chip.
...@@ -752,6 +774,7 @@ config RTC_DRV_DS1511 ...@@ -752,6 +774,7 @@ config RTC_DRV_DS1511
config RTC_DRV_DS1553 config RTC_DRV_DS1553
tristate "Maxim/Dallas DS1553" tristate "Maxim/Dallas DS1553"
depends on HAS_IOMEM
help help
If you say yes here you get support for the If you say yes here you get support for the
Maxim/Dallas DS1553 timekeeping chip. Maxim/Dallas DS1553 timekeeping chip.
...@@ -761,6 +784,7 @@ config RTC_DRV_DS1553 ...@@ -761,6 +784,7 @@ config RTC_DRV_DS1553
config RTC_DRV_DS1742 config RTC_DRV_DS1742
tristate "Maxim/Dallas DS1742/1743" tristate "Maxim/Dallas DS1742/1743"
depends on HAS_IOMEM
help help
If you say yes here you get support for the If you say yes here you get support for the
Maxim/Dallas DS1742/1743 timekeeping chip. Maxim/Dallas DS1742/1743 timekeeping chip.
...@@ -816,6 +840,7 @@ config RTC_DRV_EFI ...@@ -816,6 +840,7 @@ config RTC_DRV_EFI
config RTC_DRV_STK17TA8 config RTC_DRV_STK17TA8
tristate "Simtek STK17TA8" tristate "Simtek STK17TA8"
depends on HAS_IOMEM
help help
If you say yes here you get support for the If you say yes here you get support for the
Simtek STK17TA8 timekeeping chip. Simtek STK17TA8 timekeeping chip.
...@@ -834,6 +859,7 @@ config RTC_DRV_M48T86 ...@@ -834,6 +859,7 @@ config RTC_DRV_M48T86
config RTC_DRV_M48T35 config RTC_DRV_M48T35
tristate "ST M48T35" tristate "ST M48T35"
depends on HAS_IOMEM
help help
If you say Y here you will get support for the If you say Y here you will get support for the
ST M48T35 RTC chip. ST M48T35 RTC chip.
...@@ -843,6 +869,7 @@ config RTC_DRV_M48T35 ...@@ -843,6 +869,7 @@ config RTC_DRV_M48T35
config RTC_DRV_M48T59 config RTC_DRV_M48T59
tristate "ST M48T59/M48T08/M48T02" tristate "ST M48T59/M48T08/M48T02"
depends on HAS_IOMEM
help help
If you say Y here you will get support for the If you say Y here you will get support for the
ST M48T59 RTC chip and compatible ST M48T08 and M48T02. ST M48T59 RTC chip and compatible ST M48T08 and M48T02.
...@@ -855,6 +882,7 @@ config RTC_DRV_M48T59 ...@@ -855,6 +882,7 @@ config RTC_DRV_M48T59
config RTC_DRV_MSM6242 config RTC_DRV_MSM6242
tristate "Oki MSM6242" tristate "Oki MSM6242"
depends on HAS_IOMEM
help help
If you say yes here you get support for the Oki MSM6242 If you say yes here you get support for the Oki MSM6242
timekeeping chip. It is used in some Amiga models (e.g. A2000). timekeeping chip. It is used in some Amiga models (e.g. A2000).
...@@ -864,6 +892,7 @@ config RTC_DRV_MSM6242 ...@@ -864,6 +892,7 @@ config RTC_DRV_MSM6242
config RTC_DRV_BQ4802 config RTC_DRV_BQ4802
tristate "TI BQ4802" tristate "TI BQ4802"
depends on HAS_IOMEM
help help
If you say Y here you will get support for the TI If you say Y here you will get support for the TI
BQ4802 RTC chip. BQ4802 RTC chip.
...@@ -873,6 +902,7 @@ config RTC_DRV_BQ4802 ...@@ -873,6 +902,7 @@ config RTC_DRV_BQ4802
config RTC_DRV_RP5C01 config RTC_DRV_RP5C01
tristate "Ricoh RP5C01" tristate "Ricoh RP5C01"
depends on HAS_IOMEM
help help
If you say yes here you get support for the Ricoh RP5C01 If you say yes here you get support for the Ricoh RP5C01
timekeeping chip. It is used in some Amiga models (e.g. A3000 timekeeping chip. It is used in some Amiga models (e.g. A3000
...@@ -1374,6 +1404,7 @@ config RTC_DRV_MOXART ...@@ -1374,6 +1404,7 @@ config RTC_DRV_MOXART
config RTC_DRV_XGENE config RTC_DRV_XGENE
tristate "APM X-Gene RTC" tristate "APM X-Gene RTC"
depends on HAS_IOMEM
help help
If you say yes here you get support for the APM X-Gene SoC real time If you say yes here you get support for the APM X-Gene SoC real time
clock. clock.
......
...@@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o ...@@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o 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_MAX77802) += rtc-max77802.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_MCP795) += rtc-mcp795.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
...@@ -109,6 +110,7 @@ obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o ...@@ -109,6 +110,7 @@ obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o
obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o
obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o
obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o
obj-$(CONFIG_RTC_DRV_RK808) += rtc-rk808.o
obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o
obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o
obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o
......
...@@ -2,10 +2,14 @@ ...@@ -2,10 +2,14 @@
* Driver for TI BQ32000 RTC. * Driver for TI BQ32000 RTC.
* *
* Copyright (C) 2009 Semihalf. * Copyright (C) 2009 Semihalf.
* Copyright (C) 2014 Pavel Machek <pavel@denx.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*
* You can get hardware description at
* http://www.ti.com/lit/ds/symlink/bq32000.pdf
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -27,6 +31,10 @@ ...@@ -27,6 +31,10 @@
#define BQ32K_CENT 0x40 /* Century flag */ #define BQ32K_CENT 0x40 /* Century flag */
#define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */
#define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */
#define BQ32K_TCH2 0x08 /* Trickle charge enable */
#define BQ32K_CFG2 0x09 /* Trickle charger control */
struct bq32k_regs { struct bq32k_regs {
uint8_t seconds; uint8_t seconds;
uint8_t minutes; uint8_t minutes;
...@@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = { ...@@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = {
.set_time = bq32k_rtc_set_time, .set_time = bq32k_rtc_set_time,
}; };
static int trickle_charger_of_init(struct device *dev, struct device_node *node)
{
unsigned char reg;
int error;
u32 ohms = 0;
if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms))
return 0;
switch (ohms) {
case 180+940:
/*
* TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging
* over diode and 940ohm resistor)
*/
if (of_property_read_bool(node, "trickle-diode-disable")) {
dev_err(dev, "diode and resistor mismatch\n");
return -EINVAL;
}
reg = 0x05;
break;
case 180+20000:
/* diode disabled */
if (!of_property_read_bool(node, "trickle-diode-disable")) {
dev_err(dev, "bq32k: diode and resistor mismatch\n");
return -EINVAL;
}
reg = 0x25;
break;
default:
dev_err(dev, "invalid resistor value (%d)\n", ohms);
return -EINVAL;
}
error = bq32k_write(dev, &reg, BQ32K_CFG2, 1);
if (error)
return error;
reg = 0x20;
error = bq32k_write(dev, &reg, BQ32K_TCH2, 1);
if (error)
return error;
dev_info(dev, "Enabled trickle RTC battery charge.\n");
return 0;
}
static int bq32k_probe(struct i2c_client *client, static int bq32k_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client, ...@@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client,
if (error) if (error)
return error; return error;
if (client && client->dev.of_node)
trickle_charger_of_init(dev, client->dev.of_node);
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
&bq32k_rtc_ops, THIS_MODULE); &bq32k_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
......
...@@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev) ...@@ -856,7 +856,7 @@ static void __exit cmos_do_remove(struct device *dev)
cmos->dev = NULL; cmos->dev = NULL;
} }
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM
static int cmos_suspend(struct device *dev) static int cmos_suspend(struct device *dev)
{ {
...@@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev) ...@@ -907,6 +907,8 @@ static inline int cmos_poweroff(struct device *dev)
return cmos_suspend(dev); return cmos_suspend(dev);
} }
#ifdef CONFIG_PM_SLEEP
static int cmos_resume(struct device *dev) static int cmos_resume(struct device *dev)
{ {
struct cmos_rtc *cmos = dev_get_drvdata(dev); struct cmos_rtc *cmos = dev_get_drvdata(dev);
...@@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev) ...@@ -954,6 +956,7 @@ static int cmos_resume(struct device *dev)
return 0; return 0;
} }
#endif
#else #else
static inline int cmos_poweroff(struct device *dev) static inline int cmos_poweroff(struct device *dev)
......
...@@ -126,9 +126,14 @@ struct chip_desc { ...@@ -126,9 +126,14 @@ struct chip_desc {
u16 nvram_offset; u16 nvram_offset;
u16 nvram_size; u16 nvram_size;
u16 trickle_charger_reg; u16 trickle_charger_reg;
u8 trickle_charger_setup;
u8 (*do_trickle_setup)(struct i2c_client *, uint32_t, bool);
}; };
static const struct chip_desc chips[last_ds_type] = { static u8 do_trickle_setup_ds1339(struct i2c_client *,
uint32_t ohms, bool diode);
static struct chip_desc chips[last_ds_type] = {
[ds_1307] = { [ds_1307] = {
.nvram_offset = 8, .nvram_offset = 8,
.nvram_size = 56, .nvram_size = 56,
...@@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -143,6 +148,7 @@ static const struct chip_desc chips[last_ds_type] = {
[ds_1339] = { [ds_1339] = {
.alarm = 1, .alarm = 1,
.trickle_charger_reg = 0x10, .trickle_charger_reg = 0x10,
.do_trickle_setup = &do_trickle_setup_ds1339,
}, },
[ds_1340] = { [ds_1340] = {
.trickle_charger_reg = 0x08, .trickle_charger_reg = 0x08,
...@@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -833,15 +839,58 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
return count; return count;
} }
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static u8 do_trickle_setup_ds1339(struct i2c_client *client,
uint32_t ohms, bool diode)
{
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
DS1307_TRICKLE_CHARGER_NO_DIODE;
switch (ohms) {
case 250:
setup |= DS1307_TRICKLE_CHARGER_250_OHM;
break;
case 2000:
setup |= DS1307_TRICKLE_CHARGER_2K_OHM;
break;
case 4000:
setup |= DS1307_TRICKLE_CHARGER_4K_OHM;
break;
default:
dev_warn(&client->dev,
"Unsupported ohm value %u in dt\n", ohms);
return 0;
}
return setup;
}
static void ds1307_trickle_of_init(struct i2c_client *client,
struct chip_desc *chip)
{
uint32_t ohms = 0;
bool diode = true;
if (!chip->do_trickle_setup)
goto out;
if (of_property_read_u32(client->dev.of_node, "trickle-resistor-ohms" , &ohms))
goto out;
if (of_property_read_bool(client->dev.of_node, "trickle-diode-disable"))
diode = false;
chip->trickle_charger_setup = chip->do_trickle_setup(client,
ohms, diode);
out:
return;
}
static int ds1307_probe(struct i2c_client *client, static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct ds1307 *ds1307; struct ds1307 *ds1307;
int err = -ENODEV; int err = -ENODEV;
int tmp; int tmp;
const struct chip_desc *chip = &chips[id->driver_data]; struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false; bool want_irq = false;
unsigned char *buf; unsigned char *buf;
...@@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -866,9 +915,19 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->client = client; ds1307->client = client;
ds1307->type = id->driver_data; ds1307->type = id->driver_data;
if (pdata && pdata->trickle_charger_setup && chip->trickle_charger_reg) if (!pdata && client->dev.of_node)
ds1307_trickle_of_init(client, chip);
else if (pdata && pdata->trickle_charger_setup)
chip->trickle_charger_setup = pdata->trickle_charger_setup;
if (chip->trickle_charger_setup && chip->trickle_charger_reg) {
dev_dbg(&client->dev, "writing trickle charger info 0x%x to 0x%x\n",
DS13XX_TRICKLE_CHARGER_MAGIC | chip->trickle_charger_setup,
chip->trickle_charger_reg);
i2c_smbus_write_byte_data(client, chip->trickle_charger_reg, i2c_smbus_write_byte_data(client, chip->trickle_charger_reg,
DS13XX_TRICKLE_CHARGER_MAGIC | pdata->trickle_charger_setup); DS13XX_TRICKLE_CHARGER_MAGIC |
chip->trickle_charger_setup);
}
buf = ds1307->regs; buf = ds1307->regs;
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
......
...@@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client, ...@@ -274,7 +274,7 @@ static int isl12022_probe(struct i2c_client *client,
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id isl12022_dt_match[] = { static const struct of_device_id isl12022_dt_match[] = {
{ .compatible = "isl,isl12022" }, { .compatible = "isl,isl12022" },
{ }, { },
}; };
......
...@@ -32,15 +32,6 @@ ...@@ -32,15 +32,6 @@
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT) #define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
#define RTC_RBUDR_SHIFT 4 #define RTC_RBUDR_SHIFT 4
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT) #define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
/* WTSR and SMPL Register */
#define WTSRT_SHIFT 0
#define SMPLT_SHIFT 2
#define WTSR_EN_SHIFT 6
#define SMPL_EN_SHIFT 7
#define WTSRT_MASK (3 << WTSRT_SHIFT)
#define SMPLT_MASK (3 << SMPLT_SHIFT)
#define WTSR_EN_MASK (1 << WTSR_EN_SHIFT)
#define SMPL_EN_MASK (1 << SMPL_EN_SHIFT)
/* RTC Hour register */ /* RTC Hour register */
#define HOUR_PM_SHIFT 6 #define HOUR_PM_SHIFT 6
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT) #define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
...@@ -49,7 +40,6 @@ ...@@ -49,7 +40,6 @@
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT) #define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
#define MAX77686_RTC_UPDATE_DELAY 16 #define MAX77686_RTC_UPDATE_DELAY 16
#undef MAX77686_RTC_WTSR_SMPL
enum { enum {
RTC_SEC = 0, RTC_SEC = 0,
...@@ -80,16 +70,6 @@ enum MAX77686_RTC_OP { ...@@ -80,16 +70,6 @@ enum MAX77686_RTC_OP {
MAX77686_RTC_READ, MAX77686_RTC_READ,
}; };
static inline int max77686_rtc_calculate_wday(u8 shifted)
{
int counter = -1;
while (shifted) {
shifted >>= 1;
counter++;
}
return counter;
}
static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode) int rtc_24hr_mode)
{ {
...@@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm, ...@@ -103,7 +83,8 @@ static void max77686_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
tm->tm_hour += 12; tm->tm_hour += 12;
} }
tm->tm_wday = max77686_rtc_calculate_wday(data[RTC_WEEKDAY] & 0x7f); /* Only a single bit is set in data[], so fls() would be equivalent */
tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0x7f) - 1;
tm->tm_mday = data[RTC_DATE] & 0x1f; tm->tm_mday = data[RTC_DATE] & 0x1f;
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1; tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100; tm->tm_year = (data[RTC_YEAR] & 0x7f) + 100;
...@@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = { ...@@ -412,64 +393,6 @@ static const struct rtc_class_ops max77686_rtc_ops = {
.alarm_irq_enable = max77686_rtc_alarm_irq_enable, .alarm_irq_enable = max77686_rtc_alarm_irq_enable,
}; };
#ifdef MAX77686_RTC_WTSR_SMPL
static void max77686_rtc_enable_wtsr(struct max77686_rtc_info *info, bool enable)
{
int ret;
unsigned int val, mask;
if (enable)
val = (1 << WTSR_EN_SHIFT) | (3 << WTSRT_SHIFT);
else
val = 0;
mask = WTSR_EN_MASK | WTSRT_MASK;
dev_info(info->dev, "%s: %s WTSR\n", __func__,
enable ? "enable" : "disable");
ret = regmap_update_bits(info->max77686->rtc_regmap,
MAX77686_WTSR_SMPL_CNTL, mask, val);
if (ret < 0) {
dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
__func__, ret);
return;
}
max77686_rtc_update(info, MAX77686_RTC_WRITE);
}
static void max77686_rtc_enable_smpl(struct max77686_rtc_info *info, bool enable)
{
int ret;
unsigned int val, mask;
if (enable)
val = (1 << SMPL_EN_SHIFT) | (0 << SMPLT_SHIFT);
else
val = 0;
mask = SMPL_EN_MASK | SMPLT_MASK;
dev_info(info->dev, "%s: %s SMPL\n", __func__,
enable ? "enable" : "disable");
ret = regmap_update_bits(info->max77686->rtc_regmap,
MAX77686_WTSR_SMPL_CNTL, mask, val);
if (ret < 0) {
dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
__func__, ret);
return;
}
max77686_rtc_update(info, MAX77686_RTC_WRITE);
val = 0;
regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
dev_info(info->dev, "%s: WTSR_SMPL(0x%02x)\n", __func__, val);
}
#endif /* MAX77686_RTC_WTSR_SMPL */
static int max77686_rtc_init_reg(struct max77686_rtc_info *info) static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
{ {
u8 data[2]; u8 data[2];
...@@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev) ...@@ -519,19 +442,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
goto err_rtc; goto err_rtc;
} }
#ifdef MAX77686_RTC_WTSR_SMPL
max77686_rtc_enable_wtsr(info, true);
max77686_rtc_enable_smpl(info, true);
#endif
device_init_wakeup(&pdev->dev, 1); device_init_wakeup(&pdev->dev, 1);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc", info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77686-rtc",
&max77686_rtc_ops, THIS_MODULE); &max77686_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc_dev)) { if (IS_ERR(info->rtc_dev)) {
dev_info(&pdev->dev, "%s: fail\n", __func__);
ret = PTR_ERR(info->rtc_dev); ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
if (ret == 0) if (ret == 0)
...@@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev) ...@@ -539,6 +455,12 @@ static int max77686_rtc_probe(struct platform_device *pdev)
goto err_rtc; goto err_rtc;
} }
if (!max77686->rtc_irq_data) {
ret = -EINVAL;
dev_err(&pdev->dev, "%s: no RTC regmap IRQ chip\n", __func__);
goto err_rtc;
}
info->virq = regmap_irq_get_virq(max77686->rtc_irq_data, info->virq = regmap_irq_get_virq(max77686->rtc_irq_data,
MAX77686_RTCIRQ_RTCA1); MAX77686_RTCIRQ_RTCA1);
if (!info->virq) { if (!info->virq) {
...@@ -556,33 +478,33 @@ static int max77686_rtc_probe(struct platform_device *pdev) ...@@ -556,33 +478,33 @@ static int max77686_rtc_probe(struct platform_device *pdev)
return ret; return ret;
} }
static void max77686_rtc_shutdown(struct platform_device *pdev) #ifdef CONFIG_PM_SLEEP
static int max77686_rtc_suspend(struct device *dev)
{ {
#ifdef MAX77686_RTC_WTSR_SMPL if (device_may_wakeup(dev)) {
struct max77686_rtc_info *info = platform_get_drvdata(pdev); struct max77686_rtc_info *info = dev_get_drvdata(dev);
int i;
u8 val = 0; return enable_irq_wake(info->virq);
for (i = 0; i < 3; i++) {
max77686_rtc_enable_wtsr(info, false);
regmap_read(info->max77686->rtc_regmap, MAX77686_WTSR_SMPL_CNTL, &val);
dev_info(info->dev, "%s: WTSR_SMPL reg(0x%02x)\n", __func__,
val);
if (val & WTSR_EN_MASK) {
dev_emerg(info->dev, "%s: fail to disable WTSR\n",
__func__);
} else {
dev_info(info->dev, "%s: success to disable WTSR\n",
__func__);
break;
}
} }
/* Disable SMPL when power off */ return 0;
max77686_rtc_enable_smpl(info, false);
#endif /* MAX77686_RTC_WTSR_SMPL */
} }
static int max77686_rtc_resume(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct max77686_rtc_info *info = dev_get_drvdata(dev);
return disable_irq_wake(info->virq);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max77686_rtc_pm_ops,
max77686_rtc_suspend, max77686_rtc_resume);
static const struct platform_device_id rtc_id[] = { static const struct platform_device_id rtc_id[] = {
{ "max77686-rtc", 0 }, { "max77686-rtc", 0 },
{}, {},
...@@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = { ...@@ -592,9 +514,9 @@ static struct platform_driver max77686_rtc_driver = {
.driver = { .driver = {
.name = "max77686-rtc", .name = "max77686-rtc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &max77686_rtc_pm_ops,
}, },
.probe = max77686_rtc_probe, .probe = max77686_rtc_probe,
.shutdown = max77686_rtc_shutdown,
.id_table = rtc_id, .id_table = rtc_id,
}; };
......
/*
* RTC driver for Maxim MAX77802
*
* Copyright (C) 2013 Google, Inc
*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
*
* based on rtc-max8997.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/slab.h>
#include <linux/rtc.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/max77686-private.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
/* RTC Control Register */
#define BCD_EN_SHIFT 0
#define BCD_EN_MASK (1 << BCD_EN_SHIFT)
#define MODEL24_SHIFT 1
#define MODEL24_MASK (1 << MODEL24_SHIFT)
/* RTC Update Register1 */
#define RTC_UDR_SHIFT 0
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
#define RTC_RBUDR_SHIFT 4
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
/* RTC Hour register */
#define HOUR_PM_SHIFT 6
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
/* RTC Alarm Enable */
#define ALARM_ENABLE_SHIFT 7
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
/* For the RTCAE1 register, we write this value to enable the alarm */
#define ALARM_ENABLE_VALUE 0x77
#define MAX77802_RTC_UPDATE_DELAY_US 200
enum {
RTC_SEC = 0,
RTC_MIN,
RTC_HOUR,
RTC_WEEKDAY,
RTC_MONTH,
RTC_YEAR,
RTC_DATE,
RTC_NR_TIME
};
struct max77802_rtc_info {
struct device *dev;
struct max77686_dev *max77802;
struct i2c_client *rtc;
struct rtc_device *rtc_dev;
struct mutex lock;
struct regmap *regmap;
int virq;
int rtc_24hr_mode;
};
enum MAX77802_RTC_OP {
MAX77802_RTC_WRITE,
MAX77802_RTC_READ,
};
static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
tm->tm_sec = data[RTC_SEC] & 0xff;
tm->tm_min = data[RTC_MIN] & 0xff;
if (rtc_24hr_mode)
tm->tm_hour = data[RTC_HOUR] & 0x1f;
else {
tm->tm_hour = data[RTC_HOUR] & 0x0f;
if (data[RTC_HOUR] & HOUR_PM_MASK)
tm->tm_hour += 12;
}
/* Only a single bit is set in data[], so fls() would be equivalent */
tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
tm->tm_mday = data[RTC_DATE] & 0x1f;
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
tm->tm_year = data[RTC_YEAR] & 0xff;
tm->tm_yday = 0;
tm->tm_isdst = 0;
}
static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
{
data[RTC_SEC] = tm->tm_sec;
data[RTC_MIN] = tm->tm_min;
data[RTC_HOUR] = tm->tm_hour;
data[RTC_WEEKDAY] = 1 << tm->tm_wday;
data[RTC_DATE] = tm->tm_mday;
data[RTC_MONTH] = tm->tm_mon + 1;
data[RTC_YEAR] = tm->tm_year;
return 0;
}
static int max77802_rtc_update(struct max77802_rtc_info *info,
enum MAX77802_RTC_OP op)
{
int ret;
unsigned int data;
if (op == MAX77802_RTC_WRITE)
data = 1 << RTC_UDR_SHIFT;
else
data = 1 << RTC_RBUDR_SHIFT;
ret = regmap_update_bits(info->max77802->regmap,
MAX77802_RTC_UPDATE0, data, data);
if (ret < 0)
dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
__func__, ret, data);
else {
/* Minimum delay required before RTC update. */
usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
MAX77802_RTC_UPDATE_DELAY_US * 2);
}
return ret;
}
static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
mutex_lock(&info->lock);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_bulk_read(info->max77802->regmap,
MAX77802_RTC_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
ret);
goto out;
}
max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
ret = rtc_valid_tm(tm);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
ret = max77802_rtc_tm_to_data(tm, data);
if (ret < 0)
return ret;
mutex_lock(&info->lock);
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_RTC_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
unsigned int val;
int ret;
mutex_lock(&info->lock);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_bulk_read(info->max77802->regmap,
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}
max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
alrm->enabled = 0;
ret = regmap_read(info->max77802->regmap,
MAX77802_RTC_AE1, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
__func__, __LINE__, ret);
goto out;
}
if (val)
alrm->enabled = 1;
alrm->pending = 0;
ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}
if (val & (1 << 2)) /* RTCA1 */
alrm->pending = 1;
out:
mutex_unlock(&info->lock);
return 0;
}
static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
{
int ret;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_write(info->max77802->regmap,
MAX77802_RTC_AE1, 0);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
return ret;
}
static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
{
int ret;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n",
__func__);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_write(info->max77802->regmap,
MAX77802_RTC_AE1,
ALARM_ENABLE_VALUE);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
return ret;
}
static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
ret = max77802_rtc_tm_to_data(&alrm->time, data);
if (ret < 0)
return ret;
mutex_lock(&info->lock);
ret = max77802_rtc_stop_alarm(info);
if (ret < 0)
goto out;
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
if (ret < 0)
goto out;
if (alrm->enabled)
ret = max77802_rtc_start_alarm(info);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
int ret;
mutex_lock(&info->lock);
if (enabled)
ret = max77802_rtc_start_alarm(info);
else
ret = max77802_rtc_stop_alarm(info);
mutex_unlock(&info->lock);
return ret;
}
static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
{
struct max77802_rtc_info *info = data;
dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops max77802_rtc_ops = {
.read_time = max77802_rtc_read_time,
.set_time = max77802_rtc_set_time,
.read_alarm = max77802_rtc_read_alarm,
.set_alarm = max77802_rtc_set_alarm,
.alarm_irq_enable = max77802_rtc_alarm_irq_enable,
};
static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
{
u8 data[2];
int ret;
max77802_rtc_update(info, MAX77802_RTC_READ);
/* Set RTC control register : Binary mode, 24hour mdoe */
data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
info->rtc_24hr_mode = 1;
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
if (ret < 0) {
dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
__func__, ret);
return ret;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
return ret;
}
static int max77802_rtc_probe(struct platform_device *pdev)
{
struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
struct max77802_rtc_info *info;
int ret;
dev_dbg(&pdev->dev, "%s\n", __func__);
info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
mutex_init(&info->lock);
info->dev = &pdev->dev;
info->max77802 = max77802;
info->rtc = max77802->i2c;
platform_set_drvdata(pdev, info);
ret = max77802_rtc_init_reg(info);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
return ret;
}
device_init_wakeup(&pdev->dev, 1);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
&max77802_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc_dev)) {
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
if (ret == 0)
ret = -EINVAL;
return ret;
}
if (!max77802->rtc_irq_data) {
dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
return -EINVAL;
}
info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
MAX77686_RTCIRQ_RTCA1);
if (info->virq <= 0) {
dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
MAX77686_RTCIRQ_RTCA1);
return -EINVAL;
}
ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
max77802_rtc_alarm_irq, 0, "rtc-alarm1",
info);
if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->virq, ret);
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int max77802_rtc_suspend(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct max77802_rtc_info *info = dev_get_drvdata(dev);
return enable_irq_wake(info->virq);
}
return 0;
}
static int max77802_rtc_resume(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct max77802_rtc_info *info = dev_get_drvdata(dev);
return disable_irq_wake(info->virq);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
max77802_rtc_suspend, max77802_rtc_resume);
static const struct platform_device_id rtc_id[] = {
{ "max77802-rtc", 0 },
{},
};
static struct platform_driver max77802_rtc_driver = {
.driver = {
.name = "max77802-rtc",
.owner = THIS_MODULE,
.pm = &max77802_rtc_pm_ops,
},
.probe = max77802_rtc_probe,
.id_table = rtc_id,
};
module_platform_driver(max77802_rtc_driver);
MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
MODULE_LICENSE("GPL");
...@@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op) ...@@ -401,7 +401,7 @@ static int mpc5121_rtc_remove(struct platform_device *op)
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id mpc5121_rtc_match[] = { static const struct of_device_id mpc5121_rtc_match[] = {
{ .compatible = "fsl,mpc5121-rtc", }, { .compatible = "fsl,mpc5121-rtc", },
{ .compatible = "fsl,mpc5200-rtc", }, { .compatible = "fsl,mpc5200-rtc", },
{}, {},
......
...@@ -167,8 +167,8 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id) ...@@ -167,8 +167,8 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
char pending; char pending;
err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending); err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
if (err < 0) if (err)
return err; return IRQ_NONE;
if (pending) { if (pending) {
rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF); rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
......
...@@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -176,7 +176,11 @@ static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
unsigned char ctrl, year[2]; unsigned char ctrl, year[2];
struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year }; struct rtc_mem mem = {
.loc = CMOS_YEAR,
.nr = sizeof(year),
.data = year
};
int real_year, year_offset, err; int real_year, year_offset, err;
/* /*
...@@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -222,8 +226,16 @@ static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct i2c_client *client = to_i2c_client(dev);
unsigned char year[2], chk; unsigned char year[2], chk;
struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; struct rtc_mem cmos_year = {
struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; .loc = CMOS_YEAR,
.nr = sizeof(year),
.data = year
};
struct rtc_mem cmos_check = {
.loc = CMOS_CHECKSUM,
.nr = 1,
.data = &chk
};
unsigned int proper_year = tm->tm_year + 1900; unsigned int proper_year = tm->tm_year + 1900;
int ret; int ret;
......
/*
* RTC driver for Rockchip RK808
*
* Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
*
* Author: Chris Zhong <zyw@rock-chips.com>
* Author: Zhang Qing <zhangqing@rock-chips.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/mfd/rk808.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
/* RTC_CTRL_REG bitfields */
#define BIT_RTC_CTRL_REG_STOP_RTC_M BIT(0)
/* RK808 has a shadowed register for saving a "frozen" RTC time.
* When user setting "GET_TIME" to 1, the time will save in this shadowed
* register. If set "READSEL" to 1, user read rtc time register, actually
* get the time of that moment. If we need the real time, clr this bit.
*/
#define BIT_RTC_CTRL_REG_RTC_GET_TIME BIT(6)
#define BIT_RTC_CTRL_REG_RTC_READSEL_M BIT(7)
#define BIT_RTC_INTERRUPTS_REG_IT_ALARM_M BIT(3)
#define RTC_STATUS_MASK 0xFE
#define SECONDS_REG_MSK 0x7F
#define MINUTES_REG_MAK 0x7F
#define HOURS_REG_MSK 0x3F
#define DAYS_REG_MSK 0x3F
#define MONTHS_REG_MSK 0x1F
#define YEARS_REG_MSK 0xFF
#define WEEKS_REG_MSK 0x7
/* REG_SECONDS_REG through REG_YEARS_REG is how many registers? */
#define NUM_TIME_REGS (RK808_WEEKS_REG - RK808_SECONDS_REG + 1)
#define NUM_ALARM_REGS (RK808_ALARM_YEARS_REG - RK808_ALARM_SECONDS_REG + 1)
struct rk808_rtc {
struct rk808 *rk808;
struct rtc_device *rtc;
int irq;
};
/* Read current time and date in RTC */
static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
{
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
struct rk808 *rk808 = rk808_rtc->rk808;
u8 rtc_data[NUM_TIME_REGS];
int ret;
/* Force an update of the shadowed registers right now */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
BIT_RTC_CTRL_REG_RTC_GET_TIME,
0);
if (ret) {
dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
return ret;
}
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
BIT_RTC_CTRL_REG_RTC_GET_TIME,
BIT_RTC_CTRL_REG_RTC_GET_TIME);
if (ret) {
dev_err(dev, "Failed to update bits rtc_ctrl: %d\n", ret);
return ret;
}
ret = regmap_bulk_read(rk808->regmap, RK808_SECONDS_REG,
rtc_data, NUM_TIME_REGS);
if (ret) {
dev_err(dev, "Failed to bulk read rtc_data: %d\n", ret);
return ret;
}
tm->tm_sec = bcd2bin(rtc_data[0] & SECONDS_REG_MSK);
tm->tm_min = bcd2bin(rtc_data[1] & MINUTES_REG_MAK);
tm->tm_hour = bcd2bin(rtc_data[2] & HOURS_REG_MSK);
tm->tm_mday = bcd2bin(rtc_data[3] & DAYS_REG_MSK);
tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
return ret;
}
/* Set current time and date in RTC */
static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
struct rk808 *rk808 = rk808_rtc->rk808;
u8 rtc_data[NUM_TIME_REGS];
int ret;
rtc_data[0] = bin2bcd(tm->tm_sec);
rtc_data[1] = bin2bcd(tm->tm_min);
rtc_data[2] = bin2bcd(tm->tm_hour);
rtc_data[3] = bin2bcd(tm->tm_mday);
rtc_data[4] = bin2bcd(tm->tm_mon + 1);
rtc_data[5] = bin2bcd(tm->tm_year - 100);
rtc_data[6] = bin2bcd(tm->tm_wday);
dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
/* Stop RTC while updating the RTC registers */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
BIT_RTC_CTRL_REG_STOP_RTC_M,
BIT_RTC_CTRL_REG_STOP_RTC_M);
if (ret) {
dev_err(dev, "Failed to update RTC control: %d\n", ret);
return ret;
}
ret = regmap_bulk_write(rk808->regmap, RK808_SECONDS_REG,
rtc_data, NUM_TIME_REGS);
if (ret) {
dev_err(dev, "Failed to bull write rtc_data: %d\n", ret);
return ret;
}
/* Start RTC again */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
BIT_RTC_CTRL_REG_STOP_RTC_M, 0);
if (ret) {
dev_err(dev, "Failed to update RTC control: %d\n", ret);
return ret;
}
return 0;
}
/* Read alarm time and date in RTC */
static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
struct rk808 *rk808 = rk808_rtc->rk808;
u8 alrm_data[NUM_ALARM_REGS];
uint32_t int_reg;
int ret;
ret = regmap_bulk_read(rk808->regmap, RK808_ALARM_SECONDS_REG,
alrm_data, NUM_ALARM_REGS);
alrm->time.tm_sec = bcd2bin(alrm_data[0] & SECONDS_REG_MSK);
alrm->time.tm_min = bcd2bin(alrm_data[1] & MINUTES_REG_MAK);
alrm->time.tm_hour = bcd2bin(alrm_data[2] & HOURS_REG_MSK);
alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
if (ret) {
dev_err(dev, "Failed to read RTC INT REG: %d\n", ret);
return ret;
}
dev_dbg(dev, "alrm read RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
alrm->time.tm_min, alrm->time.tm_sec);
alrm->enabled = (int_reg & BIT_RTC_INTERRUPTS_REG_IT_ALARM_M) ? 1 : 0;
return 0;
}
static int rk808_rtc_stop_alarm(struct rk808_rtc *rk808_rtc)
{
struct rk808 *rk808 = rk808_rtc->rk808;
int ret;
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M, 0);
return ret;
}
static int rk808_rtc_start_alarm(struct rk808_rtc *rk808_rtc)
{
struct rk808 *rk808 = rk808_rtc->rk808;
int ret;
ret = regmap_update_bits(rk808->regmap, RK808_RTC_INT_REG,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M,
BIT_RTC_INTERRUPTS_REG_IT_ALARM_M);
return ret;
}
static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
struct rk808 *rk808 = rk808_rtc->rk808;
u8 alrm_data[NUM_ALARM_REGS];
int ret;
ret = rk808_rtc_stop_alarm(rk808_rtc);
if (ret) {
dev_err(dev, "Failed to stop alarm: %d\n", ret);
return ret;
}
dev_dbg(dev, "alrm set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
1900 + alrm->time.tm_year, alrm->time.tm_mon + 1,
alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
alrm->time.tm_min, alrm->time.tm_sec);
alrm_data[0] = bin2bcd(alrm->time.tm_sec);
alrm_data[1] = bin2bcd(alrm->time.tm_min);
alrm_data[2] = bin2bcd(alrm->time.tm_hour);
alrm_data[3] = bin2bcd(alrm->time.tm_mday);
alrm_data[4] = bin2bcd(alrm->time.tm_mon + 1);
alrm_data[5] = bin2bcd(alrm->time.tm_year - 100);
ret = regmap_bulk_write(rk808->regmap, RK808_ALARM_SECONDS_REG,
alrm_data, NUM_ALARM_REGS);
if (ret) {
dev_err(dev, "Failed to bulk write: %d\n", ret);
return ret;
}
if (alrm->enabled) {
ret = rk808_rtc_start_alarm(rk808_rtc);
if (ret) {
dev_err(dev, "Failed to start alarm: %d\n", ret);
return ret;
}
}
return 0;
}
static int rk808_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct rk808_rtc *rk808_rtc = dev_get_drvdata(dev);
if (enabled)
return rk808_rtc_start_alarm(rk808_rtc);
return rk808_rtc_stop_alarm(rk808_rtc);
}
/*
* We will just handle setting the frequency and make use the framework for
* reading the periodic interupts.
*
* @freq: Current periodic IRQ freq:
* bit 0: every second
* bit 1: every minute
* bit 2: every hour
* bit 3: every day
*/
static irqreturn_t rk808_alarm_irq(int irq, void *data)
{
struct rk808_rtc *rk808_rtc = data;
struct rk808 *rk808 = rk808_rtc->rk808;
struct i2c_client *client = rk808->i2c;
int ret;
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
RTC_STATUS_MASK);
if (ret) {
dev_err(&client->dev,
"%s:Failed to update RTC status: %d\n", __func__, ret);
return ret;
}
rtc_update_irq(rk808_rtc->rtc, 1, RTC_IRQF | RTC_AF);
dev_dbg(&client->dev,
"%s:irq=%d\n", __func__, irq);
return IRQ_HANDLED;
}
static const struct rtc_class_ops rk808_rtc_ops = {
.read_time = rk808_rtc_readtime,
.set_time = rk808_rtc_set_time,
.read_alarm = rk808_rtc_readalarm,
.set_alarm = rk808_rtc_setalarm,
.alarm_irq_enable = rk808_rtc_alarm_irq_enable,
};
#ifdef CONFIG_PM_SLEEP
/* Turn off the alarm if it should not be a wake source. */
static int rk808_rtc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
if (device_may_wakeup(dev))
enable_irq_wake(rk808_rtc->irq);
return 0;
}
/* Enable the alarm if it should be enabled (in case it was disabled to
* prevent use as a wake source).
*/
static int rk808_rtc_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct rk808_rtc *rk808_rtc = dev_get_drvdata(&pdev->dev);
if (device_may_wakeup(dev))
disable_irq_wake(rk808_rtc->irq);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(rk808_rtc_pm_ops,
rk808_rtc_suspend, rk808_rtc_resume);
static int rk808_rtc_probe(struct platform_device *pdev)
{
struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
struct rk808_rtc *rk808_rtc;
struct rtc_time tm;
int ret;
rk808_rtc = devm_kzalloc(&pdev->dev, sizeof(*rk808_rtc), GFP_KERNEL);
if (rk808_rtc == NULL)
return -ENOMEM;
platform_set_drvdata(pdev, rk808_rtc);
rk808_rtc->rk808 = rk808;
/* start rtc running by default, and use shadowed timer. */
ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
BIT_RTC_CTRL_REG_STOP_RTC_M |
BIT_RTC_CTRL_REG_RTC_READSEL_M,
BIT_RTC_CTRL_REG_RTC_READSEL_M);
if (ret) {
dev_err(&pdev->dev,
"Failed to update RTC control: %d\n", ret);
return ret;
}
ret = regmap_write(rk808->regmap, RK808_RTC_STATUS_REG,
RTC_STATUS_MASK);
if (ret) {
dev_err(&pdev->dev,
"Failed to write RTC status: %d\n", ret);
return ret;
}
/* set init time */
ret = rk808_rtc_readtime(&pdev->dev, &tm);
if (ret) {
dev_err(&pdev->dev, "Failed to read RTC time\n");
return ret;
}
ret = rtc_valid_tm(&tm);
if (ret)
dev_warn(&pdev->dev, "invalid date/time\n");
device_init_wakeup(&pdev->dev, 1);
rk808_rtc->rtc = devm_rtc_device_register(&pdev->dev, "rk808-rtc",
&rk808_rtc_ops, THIS_MODULE);
if (IS_ERR(rk808_rtc->rtc)) {
ret = PTR_ERR(rk808_rtc->rtc);
return ret;
}
rk808_rtc->irq = platform_get_irq(pdev, 0);
if (rk808_rtc->irq < 0) {
if (rk808_rtc->irq != -EPROBE_DEFER)
dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n",
rk808_rtc->irq);
return rk808_rtc->irq;
}
/* request alarm irq of rk808 */
ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL,
rk808_alarm_irq, 0,
"RTC alarm", rk808_rtc);
if (ret) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
rk808_rtc->irq, ret);
}
return ret;
}
static struct platform_driver rk808_rtc_driver = {
.probe = rk808_rtc_probe,
.driver = {
.name = "rk808-rtc",
.pm = &rk808_rtc_pm_ops,
},
};
module_platform_driver(rk808_rtc_driver);
MODULE_DESCRIPTION("RTC driver for the rk808 series PMICs");
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
MODULE_AUTHOR("Zhang Qing <zhangqing@rock-chips.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:rk808-rtc");
...@@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) ...@@ -142,12 +142,11 @@ static int rs5c_get_regs(struct rs5c372 *rs5c)
} }
dev_dbg(&client->dev, dev_dbg(&client->dev,
"%02x %02x %02x (%02x) %02x %02x %02x (%02x), " "%3ph (%02x) %3ph (%02x), %3ph, %3ph; %02x %02x\n",
"%02x %02x %02x, %02x %02x %02x; %02x %02x\n", rs5c->regs + 0, rs5c->regs[3],
rs5c->regs[0], rs5c->regs[1], rs5c->regs[2], rs5c->regs[3], rs5c->regs + 4, rs5c->regs[7],
rs5c->regs[4], rs5c->regs[5], rs5c->regs[6], rs5c->regs[7], rs5c->regs + 8, rs5c->regs + 11,
rs5c->regs[8], rs5c->regs[9], rs5c->regs[10], rs5c->regs[11], rs5c->regs[14], rs5c->regs[15]);
rs5c->regs[12], rs5c->regs[13], rs5c->regs[14], rs5c->regs[15]);
return 0; return 0;
} }
......
此差异已折叠。
...@@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev, ...@@ -257,11 +257,11 @@ static ssize_t chp_status_write(struct device *dev,
if (!num_args) if (!num_args)
return count; return count;
if (!strnicmp(cmd, "on", 2) || !strcmp(cmd, "1")) { if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) {
mutex_lock(&cp->lock); mutex_lock(&cp->lock);
error = s390_vary_chpid(cp->chpid, 1); error = s390_vary_chpid(cp->chpid, 1);
mutex_unlock(&cp->lock); mutex_unlock(&cp->lock);
} else if (!strnicmp(cmd, "off", 3) || !strcmp(cmd, "0")) { } else if (!strncasecmp(cmd, "off", 3) || !strcmp(cmd, "0")) {
mutex_lock(&cp->lock); mutex_lock(&cp->lock);
error = s390_vary_chpid(cp->chpid, 0); error = s390_vary_chpid(cp->chpid, 0);
mutex_unlock(&cp->lock); mutex_unlock(&cp->lock);
......
...@@ -528,7 +528,7 @@ ips_setup(char *ips_str) ...@@ -528,7 +528,7 @@ ips_setup(char *ips_str)
* Update the variables * Update the variables
*/ */
for (i = 0; i < ARRAY_SIZE(options); i++) { for (i = 0; i < ARRAY_SIZE(options); i++) {
if (strnicmp if (strncasecmp
(key, options[i].option_name, (key, options[i].option_name,
strlen(options[i].option_name)) == 0) { strlen(options[i].option_name)) == 0) {
if (value) if (value)
......
...@@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, ...@@ -3371,7 +3371,7 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf,
char work[20]; char work[20];
if (1 == sscanf(buf, "%10s", work)) { if (1 == sscanf(buf, "%10s", work)) {
if (0 == strnicmp(work,"0x", 2)) { if (0 == strncasecmp(work,"0x", 2)) {
if (1 == sscanf(&work[2], "%x", &opts)) if (1 == sscanf(&work[2], "%x", &opts))
goto opts_done; goto opts_done;
} else { } else {
......
...@@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr) ...@@ -79,7 +79,7 @@ int rtw_android_cmdstr_to_num(char *cmdstr)
{ {
int cmd_num; int cmd_num;
for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++) for (cmd_num = 0; cmd_num < ANDROID_WIFI_CMD_MAX; cmd_num++)
if (0 == strnicmp(cmdstr , android_wifi_cmd_str[cmd_num], if (0 == strncasecmp(cmdstr , android_wifi_cmd_str[cmd_num],
strlen(android_wifi_cmd_str[cmd_num]))) strlen(android_wifi_cmd_str[cmd_num])))
break; break;
return cmd_num; return cmd_num;
......
...@@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee) ...@@ -2957,25 +2957,13 @@ extern inline int rtllib_get_scans(struct rtllib_device *ieee)
static inline const char *escape_essid(const char *essid, u8 essid_len) static inline const char *escape_essid(const char *essid, u8 essid_len)
{ {
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
const char *s = essid;
char *d = escaped;
if (rtllib_is_empty_essid(essid, essid_len)) { if (rtllib_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>")); memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped; return escaped;
} }
essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
while (essid_len--) {
if (*s == '\0') {
*d++ = '\\';
*d++ = '0';
s++;
} else {
*d++ = *s++;
}
}
*d = '\0';
return escaped; return escaped;
} }
......
...@@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee) ...@@ -2593,25 +2593,13 @@ static inline int ieee80211_get_scans(struct ieee80211_device *ieee)
static inline const char *escape_essid(const char *essid, u8 essid_len) { static inline const char *escape_essid(const char *essid, u8 essid_len) {
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
const char *s = essid;
char *d = escaped;
if (ieee80211_is_empty_essid(essid, essid_len)) { if (ieee80211_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>")); memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped; return escaped;
} }
essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); snprintf(escaped, sizeof(escaped), "%*pEn", essid_len, essid);
while (essid_len--) {
if (*s == '\0') {
*d++ = '\\';
*d++ = '0';
s++;
} else {
*d++ = *s++;
}
}
*d = '\0';
return escaped; return escaped;
} }
......
...@@ -60,7 +60,6 @@ ...@@ -60,7 +60,6 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/byteorder/generic.h> #include <linux/byteorder/generic.h>
#include <linux/ctype.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -81,27 +80,6 @@ ...@@ -81,27 +80,6 @@
#include "hfa384x.h" #include "hfa384x.h"
#include "prism2mgmt.h" #include "prism2mgmt.h"
/* Create a string of printable chars from something that might not be */
/* It's recommended that the str be 4*len + 1 bytes long */
#define wlan_mkprintstr(buf, buflen, str, strlen) \
{ \
int i = 0; \
int j = 0; \
memset(str, 0, (strlen)); \
for (i = 0; i < (buflen); i++) { \
if (isprint((buf)[i])) { \
(str)[j] = (buf)[i]; \
j++; \
} else { \
(str)[j] = '\\'; \
(str)[j+1] = 'x'; \
(str)[j+2] = hex_asc_hi((buf)[i]); \
(str)[j+3] = hex_asc_lo((buf)[i]); \
j += 4; \
} \
} \
}
static char *dev_info = "prism2_usb"; static char *dev_info = "prism2_usb";
static wlandevice_t *create_wlan(void); static wlandevice_t *create_wlan(void);
...@@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) ...@@ -607,7 +585,6 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
hfa384x_t *hw = (hfa384x_t *) wlandev->priv; hfa384x_t *hw = (hfa384x_t *) wlandev->priv;
u16 temp; u16 temp;
u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN]; u8 snum[HFA384x_RID_NICSERIALNUMBER_LEN];
char pstr[(HFA384x_RID_NICSERIALNUMBER_LEN * 4) + 1];
/* Collect version and compatibility info */ /* Collect version and compatibility info */
/* Some are critical, some are not */ /* Some are critical, some are not */
...@@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev) ...@@ -862,9 +839,8 @@ static int prism2sta_getcardinfo(wlandevice_t *wlandev)
result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER, result = hfa384x_drvr_getconfig(hw, HFA384x_RID_NICSERIALNUMBER,
snum, HFA384x_RID_NICSERIALNUMBER_LEN); snum, HFA384x_RID_NICSERIALNUMBER_LEN);
if (!result) { if (!result) {
wlan_mkprintstr(snum, HFA384x_RID_NICSERIALNUMBER_LEN, netdev_info(wlandev->netdev, "Prism2 card SN: %*pEhp\n",
pstr, sizeof(pstr)); HFA384x_RID_NICSERIALNUMBER_LEN, snum);
netdev_info(wlandev->netdev, "Prism2 card SN: %s\n", pstr);
} else { } else {
netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n"); netdev_err(wlandev->netdev, "Failed to retrieve Prism2 Card SN\n");
goto failed; goto failed;
......
...@@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name) ...@@ -66,7 +66,7 @@ static struct thermal_governor *__find_governor(const char *name)
return def_governor; return def_governor;
list_for_each_entry(pos, &thermal_governor_list, governor_list) list_for_each_entry(pos, &thermal_governor_list, governor_list)
if (!strnicmp(name, pos->name, THERMAL_NAME_LENGTH)) if (!strncasecmp(name, pos->name, THERMAL_NAME_LENGTH))
return pos; return pos;
return NULL; return NULL;
...@@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor) ...@@ -104,7 +104,7 @@ int thermal_register_governor(struct thermal_governor *governor)
name = pos->tzp->governor_name; name = pos->tzp->governor_name;
if (!strnicmp(name, governor->name, THERMAL_NAME_LENGTH)) if (!strncasecmp(name, governor->name, THERMAL_NAME_LENGTH))
pos->governor = governor; pos->governor = governor;
} }
...@@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor) ...@@ -129,7 +129,7 @@ void thermal_unregister_governor(struct thermal_governor *governor)
mutex_lock(&thermal_list_lock); mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node) { list_for_each_entry(pos, &thermal_tz_list, node) {
if (!strnicmp(pos->governor->name, governor->name, if (!strncasecmp(pos->governor->name, governor->name,
THERMAL_NAME_LENGTH)) THERMAL_NAME_LENGTH))
pos->governor = NULL; pos->governor = NULL;
} }
...@@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name) ...@@ -1665,7 +1665,7 @@ struct thermal_zone_device *thermal_zone_get_zone_by_name(const char *name)
mutex_lock(&thermal_list_lock); mutex_lock(&thermal_list_lock);
list_for_each_entry(pos, &thermal_tz_list, node) list_for_each_entry(pos, &thermal_tz_list, node)
if (!strnicmp(name, pos->type, THERMAL_NAME_LENGTH)) { if (!strncasecmp(name, pos->type, THERMAL_NAME_LENGTH)) {
found++; found++;
ref = pos; ref = pos;
} }
......
...@@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, ...@@ -1001,7 +1001,7 @@ static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val,
for (i = 0 ; i < size ; i++ ) { for (i = 0 ; i < size ; i++ ) {
if (s != NULL) { if (s != NULL) {
if (!strnicmp(p[i].name, s, strlen(s))) if (!strncasecmp(p[i].name, s, strlen(s)))
return p[i].val; return p[i].val;
} else { } else {
if (p[i].val == val) if (p[i].val == val)
......
...@@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev, ...@@ -601,12 +601,12 @@ static int s3c2410fb_debug_store(struct device *dev,
if (len < 1) if (len < 1)
return -EINVAL; return -EINVAL;
if (strnicmp(buf, "on", 2) == 0 || if (strncasecmp(buf, "on", 2) == 0 ||
strnicmp(buf, "1", 1) == 0) { strncasecmp(buf, "1", 1) == 0) {
debug = 1; debug = 1;
dev_dbg(dev, "s3c2410fb: Debug On"); dev_dbg(dev, "s3c2410fb: Debug On");
} else if (strnicmp(buf, "off", 3) == 0 || } else if (strncasecmp(buf, "off", 3) == 0 ||
strnicmp(buf, "0", 1) == 0) { strncasecmp(buf, "0", 1) == 0) {
debug = 0; debug = 0;
dev_dbg(dev, "s3c2410fb: Debug Off"); dev_dbg(dev, "s3c2410fb: Debug Off");
} else { } else {
......
...@@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet) ...@@ -162,7 +162,7 @@ static void sisfb_search_mode(char *name, bool quiet)
return; return;
} }
if(!strnicmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) { if(!strncasecmp(name, sisbios_mode[MODE_INDEX_NONE].name, strlen(name))) {
if(!quiet) if(!quiet)
printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n"); printk(KERN_ERR "sisfb: Mode 'none' not supported anymore. Using default.\n");
...@@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet) ...@@ -201,7 +201,7 @@ static void sisfb_search_mode(char *name, bool quiet)
i = 0; j = 0; i = 0; j = 0;
while(sisbios_mode[i].mode_no[0] != 0) { while(sisbios_mode[i].mode_no[0] != 0) {
if(!strnicmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) { if(!strncasecmp(nameptr, sisbios_mode[i++].name, strlen(nameptr))) {
if(sisfb_fstn) { if(sisfb_fstn) {
if(sisbios_mode[i-1].mode_no[1] == 0x50 || if(sisbios_mode[i-1].mode_no[1] == 0x50 ||
sisbios_mode[i-1].mode_no[1] == 0x56 || sisbios_mode[i-1].mode_no[1] == 0x56 ||
...@@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name) ...@@ -262,7 +262,7 @@ sisfb_search_crt2type(const char *name)
if(name == NULL) return; if(name == NULL) return;
while(sis_crt2type[i].type_no != -1) { while(sis_crt2type[i].type_no != -1) {
if(!strnicmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) { if(!strncasecmp(name, sis_crt2type[i].name, strlen(sis_crt2type[i].name))) {
sisfb_crt2type = sis_crt2type[i].type_no; sisfb_crt2type = sis_crt2type[i].type_no;
sisfb_tvplug = sis_crt2type[i].tvplug_no; sisfb_tvplug = sis_crt2type[i].tvplug_no;
sisfb_crt2flags = sis_crt2type[i].flags; sisfb_crt2flags = sis_crt2type[i].flags;
...@@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name) ...@@ -289,7 +289,7 @@ sisfb_search_tvstd(const char *name)
return; return;
while(sis_tvtype[i].type_no != -1) { while(sis_tvtype[i].type_no != -1) {
if(!strnicmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) { if(!strncasecmp(name, sis_tvtype[i].name, strlen(sis_tvtype[i].name))) {
sisfb_tvstd = sis_tvtype[i].type_no; sisfb_tvstd = sis_tvtype[i].type_no;
break; break;
} }
...@@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name) ...@@ -308,12 +308,12 @@ sisfb_search_specialtiming(const char *name)
if(name == NULL) if(name == NULL)
return; return;
if(!strnicmp(name, "none", 4)) { if(!strncasecmp(name, "none", 4)) {
sisfb_specialtiming = CUT_FORCENONE; sisfb_specialtiming = CUT_FORCENONE;
printk(KERN_DEBUG "sisfb: Special timing disabled\n"); printk(KERN_DEBUG "sisfb: Special timing disabled\n");
} else { } else {
while(mycustomttable[i].chipID != 0) { while(mycustomttable[i].chipID != 0) {
if(!strnicmp(name,mycustomttable[i].optionName, if(!strncasecmp(name,mycustomttable[i].optionName,
strlen(mycustomttable[i].optionName))) { strlen(mycustomttable[i].optionName))) {
sisfb_specialtiming = mycustomttable[i].SpecialID; sisfb_specialtiming = mycustomttable[i].SpecialID;
found = true; found = true;
...@@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options) ...@@ -3952,68 +3952,68 @@ static int __init sisfb_setup(char *options)
if(!(*this_opt)) continue; if(!(*this_opt)) continue;
if(!strnicmp(this_opt, "off", 3)) { if(!strncasecmp(this_opt, "off", 3)) {
sisfb_off = 1; sisfb_off = 1;
} else if(!strnicmp(this_opt, "forcecrt2type:", 14)) { } else if(!strncasecmp(this_opt, "forcecrt2type:", 14)) {
/* Need to check crt2 type first for fstn/dstn */ /* Need to check crt2 type first for fstn/dstn */
sisfb_search_crt2type(this_opt + 14); sisfb_search_crt2type(this_opt + 14);
} else if(!strnicmp(this_opt, "tvmode:",7)) { } else if(!strncasecmp(this_opt, "tvmode:",7)) {
sisfb_search_tvstd(this_opt + 7); sisfb_search_tvstd(this_opt + 7);
} else if(!strnicmp(this_opt, "tvstandard:",11)) { } else if(!strncasecmp(this_opt, "tvstandard:",11)) {
sisfb_search_tvstd(this_opt + 11); sisfb_search_tvstd(this_opt + 11);
} else if(!strnicmp(this_opt, "mode:", 5)) { } else if(!strncasecmp(this_opt, "mode:", 5)) {
sisfb_search_mode(this_opt + 5, false); sisfb_search_mode(this_opt + 5, false);
} else if(!strnicmp(this_opt, "vesa:", 5)) { } else if(!strncasecmp(this_opt, "vesa:", 5)) {
sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false); sisfb_search_vesamode(simple_strtoul(this_opt + 5, NULL, 0), false);
} else if(!strnicmp(this_opt, "rate:", 5)) { } else if(!strncasecmp(this_opt, "rate:", 5)) {
sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0); sisfb_parm_rate = simple_strtoul(this_opt + 5, NULL, 0);
} else if(!strnicmp(this_opt, "forcecrt1:", 10)) { } else if(!strncasecmp(this_opt, "forcecrt1:", 10)) {
sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0); sisfb_forcecrt1 = (int)simple_strtoul(this_opt + 10, NULL, 0);
} else if(!strnicmp(this_opt, "mem:",4)) { } else if(!strncasecmp(this_opt, "mem:",4)) {
sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0); sisfb_parm_mem = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc:", 4)) { } else if(!strncasecmp(this_opt, "pdc:", 4)) {
sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0); sisfb_pdc = simple_strtoul(this_opt + 4, NULL, 0);
} else if(!strnicmp(this_opt, "pdc1:", 5)) { } else if(!strncasecmp(this_opt, "pdc1:", 5)) {
sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0); sisfb_pdca = simple_strtoul(this_opt + 5, NULL, 0);
} else if(!strnicmp(this_opt, "noaccel", 7)) { } else if(!strncasecmp(this_opt, "noaccel", 7)) {
sisfb_accel = 0; sisfb_accel = 0;
} else if(!strnicmp(this_opt, "accel", 5)) { } else if(!strncasecmp(this_opt, "accel", 5)) {
sisfb_accel = -1; sisfb_accel = -1;
} else if(!strnicmp(this_opt, "noypan", 6)) { } else if(!strncasecmp(this_opt, "noypan", 6)) {
sisfb_ypan = 0; sisfb_ypan = 0;
} else if(!strnicmp(this_opt, "ypan", 4)) { } else if(!strncasecmp(this_opt, "ypan", 4)) {
sisfb_ypan = -1; sisfb_ypan = -1;
} else if(!strnicmp(this_opt, "nomax", 5)) { } else if(!strncasecmp(this_opt, "nomax", 5)) {
sisfb_max = 0; sisfb_max = 0;
} else if(!strnicmp(this_opt, "max", 3)) { } else if(!strncasecmp(this_opt, "max", 3)) {
sisfb_max = -1; sisfb_max = -1;
} else if(!strnicmp(this_opt, "userom:", 7)) { } else if(!strncasecmp(this_opt, "userom:", 7)) {
sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0); sisfb_userom = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "useoem:", 7)) { } else if(!strncasecmp(this_opt, "useoem:", 7)) {
sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0); sisfb_useoem = (int)simple_strtoul(this_opt + 7, NULL, 0);
} else if(!strnicmp(this_opt, "nocrt2rate", 10)) { } else if(!strncasecmp(this_opt, "nocrt2rate", 10)) {
sisfb_nocrt2rate = 1; sisfb_nocrt2rate = 1;
} else if(!strnicmp(this_opt, "scalelcd:", 9)) { } else if(!strncasecmp(this_opt, "scalelcd:", 9)) {
unsigned long temp = 2; unsigned long temp = 2;
temp = simple_strtoul(this_opt + 9, NULL, 0); temp = simple_strtoul(this_opt + 9, NULL, 0);
if((temp == 0) || (temp == 1)) { if((temp == 0) || (temp == 1)) {
sisfb_scalelcd = temp ^ 1; sisfb_scalelcd = temp ^ 1;
} }
} else if(!strnicmp(this_opt, "tvxposoffset:", 13)) { } else if(!strncasecmp(this_opt, "tvxposoffset:", 13)) {
int temp = 0; int temp = 0;
temp = (int)simple_strtol(this_opt + 13, NULL, 0); temp = (int)simple_strtol(this_opt + 13, NULL, 0);
if((temp >= -32) && (temp <= 32)) { if((temp >= -32) && (temp <= 32)) {
sisfb_tvxposoffset = temp; sisfb_tvxposoffset = temp;
} }
} else if(!strnicmp(this_opt, "tvyposoffset:", 13)) { } else if(!strncasecmp(this_opt, "tvyposoffset:", 13)) {
int temp = 0; int temp = 0;
temp = (int)simple_strtol(this_opt + 13, NULL, 0); temp = (int)simple_strtol(this_opt + 13, NULL, 0);
if((temp >= -32) && (temp <= 32)) { if((temp >= -32) && (temp <= 32)) {
sisfb_tvyposoffset = temp; sisfb_tvyposoffset = temp;
} }
} else if(!strnicmp(this_opt, "specialtiming:", 14)) { } else if(!strncasecmp(this_opt, "specialtiming:", 14)) {
sisfb_search_specialtiming(this_opt + 14); sisfb_search_specialtiming(this_opt + 14);
} else if(!strnicmp(this_opt, "lvdshl:", 7)) { } else if(!strncasecmp(this_opt, "lvdshl:", 7)) {
int temp = 4; int temp = 4;
temp = simple_strtoul(this_opt + 7, NULL, 0); temp = simple_strtoul(this_opt + 7, NULL, 0);
if((temp >= 0) && (temp <= 3)) { if((temp >= 0) && (temp <= 3)) {
...@@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options) ...@@ -4022,9 +4022,9 @@ static int __init sisfb_setup(char *options)
} else if(this_opt[0] >= '0' && this_opt[0] <= '9') { } else if(this_opt[0] >= '0' && this_opt[0] <= '9') {
sisfb_search_mode(this_opt, true); sisfb_search_mode(this_opt, true);
#if !defined(__i386__) && !defined(__x86_64__) #if !defined(__i386__) && !defined(__x86_64__)
} else if(!strnicmp(this_opt, "resetcard", 9)) { } else if(!strncasecmp(this_opt, "resetcard", 9)) {
sisfb_resetcard = 1; sisfb_resetcard = 1;
} else if(!strnicmp(this_opt, "videoram:", 9)) { } else if(!strncasecmp(this_opt, "videoram:", 9)) {
sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0); sisfb_videoram = simple_strtoul(this_opt + 9, NULL, 0);
#endif #endif
} else { } else {
......
...@@ -1187,9 +1187,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev, ...@@ -1187,9 +1187,9 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
if (len < 1) if (len < 1)
return -EINVAL; return -EINVAL;
if (strnicmp(buf, "crt", 3) == 0) if (strncasecmp(buf, "crt", 3) == 0)
head = HEAD_CRT; head = HEAD_CRT;
else if (strnicmp(buf, "panel", 5) == 0) else if (strncasecmp(buf, "panel", 5) == 0)
head = HEAD_PANEL; head = HEAD_PANEL;
else else
return -EINVAL; return -EINVAL;
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include "affs.h" #include "affs.h"
extern struct timezone sys_tz;
static char ErrorBuffer[256]; static char ErrorBuffer[256];
/* /*
......
...@@ -584,11 +584,14 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize) ...@@ -584,11 +584,14 @@ affs_extent_file_ofs(struct inode *inode, u32 newsize)
bh->b_state &= ~(1UL << BH_New); bh->b_state &= ~(1UL << BH_New);
mark_buffer_dirty_inode(bh, inode); mark_buffer_dirty_inode(bh, inode);
if (prev_bh) { if (prev_bh) {
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
if (tmp)
affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp); if (tmp_next)
affs_warning(sb, "extent_file_ofs",
"next block already set for %d (%d)",
bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode); mark_buffer_dirty_inode(prev_bh, inode);
affs_brelse(prev_bh); affs_brelse(prev_bh);
} }
...@@ -727,11 +730,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -727,11 +730,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
AFFS_DATA_HEAD(bh)->next = 0; AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New); bh->b_state &= ~(1UL << BH_New);
if (prev_bh) { if (prev_bh) {
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
if (tmp)
affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp); if (tmp_next)
affs_warning(sb, "commit_write_ofs",
"next block already set for %d (%d)",
bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode); mark_buffer_dirty_inode(prev_bh, inode);
} }
} }
...@@ -758,11 +764,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping, ...@@ -758,11 +764,14 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
AFFS_DATA_HEAD(bh)->next = 0; AFFS_DATA_HEAD(bh)->next = 0;
bh->b_state &= ~(1UL << BH_New); bh->b_state &= ~(1UL << BH_New);
if (prev_bh) { if (prev_bh) {
u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next); u32 tmp_next = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
if (tmp)
affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp); if (tmp_next)
affs_warning(sb, "commit_write_ofs",
"next block already set for %d (%d)",
bidx, tmp_next);
AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr); AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp); affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp_next);
mark_buffer_dirty_inode(prev_bh, inode); mark_buffer_dirty_inode(prev_bh, inode);
} }
} else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp) } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
...@@ -842,12 +851,12 @@ affs_truncate(struct inode *inode) ...@@ -842,12 +851,12 @@ affs_truncate(struct inode *inode)
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
struct page *page; struct page *page;
void *fsdata; void *fsdata;
loff_t size = inode->i_size; loff_t isize = inode->i_size;
int res; int res;
res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); res = mapping->a_ops->write_begin(NULL, mapping, isize, 0, 0, &page, &fsdata);
if (!res) if (!res)
res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); res = mapping->a_ops->write_end(NULL, mapping, isize, 0, 0, page, fsdata);
else else
inode->i_size = AFFS_I(inode)->mmu_private; inode->i_size = AFFS_I(inode)->mmu_private;
mark_inode_dirty(inode); mark_inode_dirty(inode);
......
...@@ -14,13 +14,11 @@ ...@@ -14,13 +14,11 @@
#include "affs.h" #include "affs.h"
extern const struct inode_operations affs_symlink_inode_operations; extern const struct inode_operations affs_symlink_inode_operations;
extern struct timezone sys_tz;
struct inode *affs_iget(struct super_block *sb, unsigned long ino) struct inode *affs_iget(struct super_block *sb, unsigned long ino)
{ {
struct affs_sb_info *sbi = AFFS_SB(sb); struct affs_sb_info *sbi = AFFS_SB(sb);
struct buffer_head *bh; struct buffer_head *bh;
struct affs_head *head;
struct affs_tail *tail; struct affs_tail *tail;
struct inode *inode; struct inode *inode;
u32 block; u32 block;
...@@ -49,7 +47,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) ...@@ -49,7 +47,6 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
goto bad_inode; goto bad_inode;
} }
head = AFFS_HEAD(bh);
tail = AFFS_TAIL(sb, bh); tail = AFFS_TAIL(sb, bh);
prot = be32_to_cpu(tail->protect); prot = be32_to_cpu(tail->protect);
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <linux/writeback.h> #include <linux/writeback.h>
#include "affs.h" #include "affs.h"
extern struct timezone sys_tz;
static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
static int affs_remount (struct super_block *sb, int *flags, char *data); static int affs_remount (struct super_block *sb, int *flags, char *data);
...@@ -308,7 +306,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -308,7 +306,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
u32 chksum; u32 chksum;
int num_bm; int num_bm;
int i, j; int i, j;
s32 key;
kuid_t uid; kuid_t uid;
kgid_t gid; kgid_t gid;
int reserved; int reserved;
...@@ -367,7 +364,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -367,7 +364,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
i = j = blocksize; i = j = blocksize;
size = size / (blocksize / 512); size = size / (blocksize / 512);
} }
for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { for (blocksize = i; blocksize <= j; blocksize <<= 1, size >>= 1) {
sbi->s_root_block = root_block; 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;
...@@ -399,7 +396,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -399,7 +396,6 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) { be32_to_cpu(AFFS_ROOT_TAIL(sb, root_bh)->stype) == ST_ROOT) {
sbi->s_hashsize = blocksize / 4 - 56; sbi->s_hashsize = blocksize / 4 - 56;
sbi->s_root_block += num_bm; sbi->s_root_block += num_bm;
key = 1;
goto got_root; goto got_root;
} }
affs_brelse(root_bh); affs_brelse(root_bh);
......
...@@ -79,6 +79,10 @@ struct autofs_info { ...@@ -79,6 +79,10 @@ struct autofs_info {
}; };
#define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */ #define AUTOFS_INF_EXPIRING (1<<0) /* dentry is in the process of expiring */
#define AUTOFS_INF_NO_RCU (1<<1) /* the dentry is being considered
* for expiry, so RCU_walk is
* not permitted
*/
#define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */ #define AUTOFS_INF_PENDING (1<<2) /* dentry pending mount */
struct autofs_wait_queue { struct autofs_wait_queue {
...@@ -148,7 +152,7 @@ void autofs4_free_ino(struct autofs_info *); ...@@ -148,7 +152,7 @@ void autofs4_free_ino(struct autofs_info *);
/* Expiration */ /* Expiration */
int is_autofs4_dentry(struct dentry *); int is_autofs4_dentry(struct dentry *);
int autofs4_expire_wait(struct dentry *dentry); int autofs4_expire_wait(struct dentry *dentry, int rcu_walk);
int autofs4_expire_run(struct super_block *, struct vfsmount *, int autofs4_expire_run(struct super_block *, struct vfsmount *,
struct autofs_sb_info *, struct autofs_sb_info *,
struct autofs_packet_expire __user *); struct autofs_packet_expire __user *);
......
...@@ -450,7 +450,7 @@ static int autofs_dev_ioctl_requester(struct file *fp, ...@@ -450,7 +450,7 @@ static int autofs_dev_ioctl_requester(struct file *fp,
ino = autofs4_dentry_ino(path.dentry); ino = autofs4_dentry_ino(path.dentry);
if (ino) { if (ino) {
err = 0; err = 0;
autofs4_expire_wait(path.dentry); autofs4_expire_wait(path.dentry, 0);
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid); param->requester.uid = from_kuid_munged(current_user_ns(), ino->uid);
param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid); param->requester.gid = from_kgid_munged(current_user_ns(), ino->gid);
......
...@@ -30,12 +30,6 @@ static inline int autofs4_can_expire(struct dentry *dentry, ...@@ -30,12 +30,6 @@ static inline int autofs4_can_expire(struct dentry *dentry,
/* Too young to die */ /* Too young to die */
if (!timeout || time_after(ino->last_used + timeout, now)) if (!timeout || time_after(ino->last_used + timeout, now))
return 0; return 0;
/* update last_used here :-
- obviously makes sense if it is in use now
- less obviously, prevents rapid-fire expire
attempts if expire fails the first time */
ino->last_used = now;
} }
return 1; return 1;
} }
...@@ -327,10 +321,19 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, ...@@ -327,10 +321,19 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
if (ino->flags & AUTOFS_INF_PENDING) if (ino->flags & AUTOFS_INF_PENDING)
goto out; goto out;
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) { if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
ino->flags |= AUTOFS_INF_EXPIRING; ino->flags |= AUTOFS_INF_NO_RCU;
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
return root; synchronize_rcu();
spin_lock(&sbi->fs_lock);
if (!autofs4_direct_busy(mnt, root, timeout, do_now)) {
ino->flags |= AUTOFS_INF_EXPIRING;
smp_mb();
ino->flags &= ~AUTOFS_INF_NO_RCU;
init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock);
return root;
}
ino->flags &= ~AUTOFS_INF_NO_RCU;
} }
out: out:
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
...@@ -339,6 +342,89 @@ struct dentry *autofs4_expire_direct(struct super_block *sb, ...@@ -339,6 +342,89 @@ struct dentry *autofs4_expire_direct(struct super_block *sb,
return NULL; return NULL;
} }
/* Check if 'dentry' should expire, or return a nearby
* dentry that is suitable.
* If returned dentry is different from arg dentry,
* then a dget() reference was taken, else not.
*/
static struct dentry *should_expire(struct dentry *dentry,
struct vfsmount *mnt,
unsigned long timeout,
int how)
{
int do_now = how & AUTOFS_EXP_IMMEDIATE;
int exp_leaves = how & AUTOFS_EXP_LEAVES;
struct autofs_info *ino = autofs4_dentry_ino(dentry);
unsigned int ino_count;
/* No point expiring a pending mount */
if (ino->flags & AUTOFS_INF_PENDING)
return NULL;
/*
* Case 1: (i) indirect mount or top level pseudo direct mount
* (autofs-4.1).
* (ii) indirect mount with offset mount, check the "/"
* offset (autofs-5.0+).
*/
if (d_mountpoint(dentry)) {
DPRINTK("checking mountpoint %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
/* Can we umount this guy */
if (autofs4_mount_busy(mnt, dentry))
return NULL;
/* Can we expire this guy */
if (autofs4_can_expire(dentry, timeout, do_now))
return dentry;
return NULL;
}
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) {
DPRINTK("checking symlink %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
/*
* A symlink can't be "busy" in the usual sense so
* just check last used for expire timeout.
*/
if (autofs4_can_expire(dentry, timeout, do_now))
return dentry;
return NULL;
}
if (simple_empty(dentry))
return NULL;
/* Case 2: tree mount, expire iff entire tree is not busy */
if (!exp_leaves) {
/* Path walk currently on this dentry? */
ino_count = atomic_read(&ino->count) + 1;
if (d_count(dentry) > ino_count)
return NULL;
if (!autofs4_tree_busy(mnt, dentry, timeout, do_now))
return dentry;
/*
* Case 3: pseudo direct mount, expire individual leaves
* (autofs-4.1).
*/
} else {
/* Path walk currently on this dentry? */
struct dentry *expired;
ino_count = atomic_read(&ino->count) + 1;
if (d_count(dentry) > ino_count)
return NULL;
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
if (expired) {
if (expired == dentry)
dput(dentry);
return expired;
}
}
return NULL;
}
/* /*
* Find an eligible tree to time-out * Find an eligible tree to time-out
* A tree is eligible if :- * A tree is eligible if :-
...@@ -353,11 +439,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ...@@ -353,11 +439,8 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
unsigned long timeout; unsigned long timeout;
struct dentry *root = sb->s_root; struct dentry *root = sb->s_root;
struct dentry *dentry; struct dentry *dentry;
struct dentry *expired = NULL; struct dentry *expired;
int do_now = how & AUTOFS_EXP_IMMEDIATE;
int exp_leaves = how & AUTOFS_EXP_LEAVES;
struct autofs_info *ino; struct autofs_info *ino;
unsigned int ino_count;
if (!root) if (!root)
return NULL; return NULL;
...@@ -369,77 +452,28 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ...@@ -369,77 +452,28 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
while ((dentry = get_next_positive_subdir(dentry, root))) { while ((dentry = get_next_positive_subdir(dentry, root))) {
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry); ino = autofs4_dentry_ino(dentry);
/* No point expiring a pending mount */ if (ino->flags & AUTOFS_INF_NO_RCU)
if (ino->flags & AUTOFS_INF_PENDING) expired = NULL;
goto next; else
expired = should_expire(dentry, mnt, timeout, how);
/* if (!expired) {
* Case 1: (i) indirect mount or top level pseudo direct mount spin_unlock(&sbi->fs_lock);
* (autofs-4.1). continue;
* (ii) indirect mount with offset mount, check the "/"
* offset (autofs-5.0+).
*/
if (d_mountpoint(dentry)) {
DPRINTK("checking mountpoint %p %.*s",
dentry, (int)dentry->d_name.len, dentry->d_name.name);
/* Can we umount this guy */
if (autofs4_mount_busy(mnt, dentry))
goto next;
/* Can we expire this guy */
if (autofs4_can_expire(dentry, timeout, do_now)) {
expired = dentry;
goto found;
}
goto next;
} }
ino = autofs4_dentry_ino(expired);
if (dentry->d_inode && S_ISLNK(dentry->d_inode->i_mode)) { ino->flags |= AUTOFS_INF_NO_RCU;
DPRINTK("checking symlink %p %.*s", spin_unlock(&sbi->fs_lock);
dentry, (int)dentry->d_name.len, dentry->d_name.name); synchronize_rcu();
/* spin_lock(&sbi->fs_lock);
* A symlink can't be "busy" in the usual sense so if (should_expire(expired, mnt, timeout, how)) {
* just check last used for expire timeout. if (expired != dentry)
*/
if (autofs4_can_expire(dentry, timeout, do_now)) {
expired = dentry;
goto found;
}
goto next;
}
if (simple_empty(dentry))
goto next;
/* Case 2: tree mount, expire iff entire tree is not busy */
if (!exp_leaves) {
/* Path walk currently on this dentry? */
ino_count = atomic_read(&ino->count) + 1;
if (d_count(dentry) > ino_count)
goto next;
if (!autofs4_tree_busy(mnt, dentry, timeout, do_now)) {
expired = dentry;
goto found;
}
/*
* Case 3: pseudo direct mount, expire individual leaves
* (autofs-4.1).
*/
} else {
/* Path walk currently on this dentry? */
ino_count = atomic_read(&ino->count) + 1;
if (d_count(dentry) > ino_count)
goto next;
expired = autofs4_check_leaves(mnt, dentry, timeout, do_now);
if (expired) {
dput(dentry); dput(dentry);
goto found; goto found;
}
} }
next:
ino->flags &= ~AUTOFS_INF_NO_RCU;
if (expired != dentry)
dput(expired);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
} }
return NULL; return NULL;
...@@ -447,8 +481,9 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ...@@ -447,8 +481,9 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
found: found:
DPRINTK("returning %p %.*s", DPRINTK("returning %p %.*s",
expired, (int)expired->d_name.len, expired->d_name.name); expired, (int)expired->d_name.len, expired->d_name.name);
ino = autofs4_dentry_ino(expired);
ino->flags |= AUTOFS_INF_EXPIRING; ino->flags |= AUTOFS_INF_EXPIRING;
smp_mb();
ino->flags &= ~AUTOFS_INF_NO_RCU;
init_completion(&ino->expire_complete); init_completion(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
spin_lock(&sbi->lookup_lock); spin_lock(&sbi->lookup_lock);
...@@ -461,13 +496,18 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb, ...@@ -461,13 +496,18 @@ struct dentry *autofs4_expire_indirect(struct super_block *sb,
return expired; return expired;
} }
int autofs4_expire_wait(struct dentry *dentry) int autofs4_expire_wait(struct dentry *dentry, int rcu_walk)
{ {
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
struct autofs_info *ino = autofs4_dentry_ino(dentry); struct autofs_info *ino = autofs4_dentry_ino(dentry);
int status; int status;
/* Block on any pending expire */ /* Block on any pending expire */
if (!(ino->flags & (AUTOFS_INF_EXPIRING | AUTOFS_INF_NO_RCU)))
return 0;
if (rcu_walk)
return -ECHILD;
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
if (ino->flags & AUTOFS_INF_EXPIRING) { if (ino->flags & AUTOFS_INF_EXPIRING) {
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
...@@ -519,6 +559,8 @@ int autofs4_expire_run(struct super_block *sb, ...@@ -519,6 +559,8 @@ int autofs4_expire_run(struct super_block *sb,
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
ino = autofs4_dentry_ino(dentry); ino = autofs4_dentry_ino(dentry);
/* avoid rapid-fire expire attempts if expiry fails */
ino->last_used = now;
ino->flags &= ~AUTOFS_INF_EXPIRING; ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete); complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
...@@ -545,6 +587,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt, ...@@ -545,6 +587,8 @@ int autofs4_do_expire_multi(struct super_block *sb, struct vfsmount *mnt,
ret = autofs4_wait(sbi, dentry, NFY_EXPIRE); ret = autofs4_wait(sbi, dentry, NFY_EXPIRE);
spin_lock(&sbi->fs_lock); spin_lock(&sbi->fs_lock);
/* avoid rapid-fire expire attempts if expiry fails */
ino->last_used = now;
ino->flags &= ~AUTOFS_INF_EXPIRING; ino->flags &= ~AUTOFS_INF_EXPIRING;
complete_all(&ino->expire_complete); complete_all(&ino->expire_complete);
spin_unlock(&sbi->fs_lock); spin_unlock(&sbi->fs_lock);
......
此差异已折叠。
此差异已折叠。
...@@ -62,7 +62,22 @@ static struct file_system_type bm_fs_type; ...@@ -62,7 +62,22 @@ static struct file_system_type bm_fs_type;
static struct vfsmount *bm_mnt; static struct vfsmount *bm_mnt;
static int entry_count; static int entry_count;
/* /*
* Max length of the register string. Determined by:
* - 7 delimiters
* - name: ~50 bytes
* - type: 1 byte
* - offset: 3 bytes (has to be smaller than BINPRM_BUF_SIZE)
* - magic: 128 bytes (512 in escaped form)
* - mask: 128 bytes (512 in escaped form)
* - interp: ~50 bytes
* - flags: 5 bytes
* Round that up a bit, and then back off to hold the internal data
* (like struct Node).
*/
#define MAX_REGISTER_LENGTH 1920
/*
* Check if we support the binfmt * Check if we support the binfmt
* if we do, return the node, else NULL * if we do, return the node, else NULL
* locking is done in load_misc_binary * locking is done in load_misc_binary
...@@ -279,7 +294,7 @@ static Node *create_entry(const char __user *buffer, size_t count) ...@@ -279,7 +294,7 @@ static Node *create_entry(const char __user *buffer, size_t count)
/* some sanity checks */ /* some sanity checks */
err = -EINVAL; err = -EINVAL;
if ((count < 11) || (count > 256)) if ((count < 11) || (count > MAX_REGISTER_LENGTH))
goto out; goto out;
err = -ENOMEM; err = -ENOMEM;
...@@ -396,12 +411,12 @@ static int parse_command(const char __user *buffer, size_t count) ...@@ -396,12 +411,12 @@ static int parse_command(const char __user *buffer, size_t count)
{ {
char s[4]; char s[4];
if (!count)
return 0;
if (count > 3) if (count > 3)
return -EINVAL; return -EINVAL;
if (copy_from_user(s, buffer, count)) if (copy_from_user(s, buffer, count))
return -EFAULT; return -EFAULT;
if (!count)
return 0;
if (s[count-1] == '\n') if (s[count-1] == '\n')
count--; count--;
if (count == 1 && s[0] == '0') if (count == 1 && s[0] == '0')
......
...@@ -1331,8 +1331,8 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size) ...@@ -1331,8 +1331,8 @@ lookup_bh_lru(struct block_device *bdev, sector_t block, unsigned size)
for (i = 0; i < BH_LRU_SIZE; i++) { for (i = 0; i < BH_LRU_SIZE; i++) {
struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]); struct buffer_head *bh = __this_cpu_read(bh_lrus.bhs[i]);
if (bh && bh->b_bdev == bdev && if (bh && bh->b_blocknr == block && bh->b_bdev == bdev &&
bh->b_blocknr == block && bh->b_size == size) { bh->b_size == size) {
if (i) { if (i) {
while (i) { while (i) {
__this_cpu_write(bh_lrus.bhs[i], __this_cpu_write(bh_lrus.bhs[i],
......
...@@ -195,15 +195,15 @@ char *cifs_compose_mount_options(const char *sb_mountdata, ...@@ -195,15 +195,15 @@ char *cifs_compose_mount_options(const char *sb_mountdata,
else else
noff = tkn_e - (sb_mountdata + off) + 1; noff = tkn_e - (sb_mountdata + off) + 1;
if (strnicmp(sb_mountdata + off, "unc=", 4) == 0) { if (strncasecmp(sb_mountdata + off, "unc=", 4) == 0) {
off += noff; off += noff;
continue; continue;
} }
if (strnicmp(sb_mountdata + off, "ip=", 3) == 0) { if (strncasecmp(sb_mountdata + off, "ip=", 3) == 0) {
off += noff; off += noff;
continue; continue;
} }
if (strnicmp(sb_mountdata + off, "prefixpath=", 11) == 0) { if (strncasecmp(sb_mountdata + off, "prefixpath=", 11) == 0) {
off += noff; off += noff;
continue; continue;
} }
......
...@@ -1718,7 +1718,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1718,7 +1718,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
goto cifs_parse_mount_err; goto cifs_parse_mount_err;
} }
if (strnicmp(string, "default", 7) != 0) { if (strncasecmp(string, "default", 7) != 0) {
vol->iocharset = kstrdup(string, vol->iocharset = kstrdup(string,
GFP_KERNEL); GFP_KERNEL);
if (!vol->iocharset) { if (!vol->iocharset) {
...@@ -1790,7 +1790,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1790,7 +1790,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (string == NULL) if (string == NULL)
goto out_nomem; goto out_nomem;
if (strnicmp(string, "1", 1) == 0) { if (strncasecmp(string, "1", 1) == 0) {
/* This is the default */ /* This is the default */
break; break;
} }
......
此差异已折叠。
...@@ -164,8 +164,6 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) ...@@ -164,8 +164,6 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
return 0; return 0;
} }
extern struct timezone sys_tz;
/* /*
* The epoch of FAT timestamp is 1980. * The epoch of FAT timestamp is 1980.
* : bits : value * : bits : value
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册