提交 f7dce82d 编写于 作者: T Thomas Gleixner

Merge commit 'v3.9-rc2' into timers/core

Fold in upstream fixes.
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
...@@ -953,11 +953,11 @@ S: Blacksburg, Virginia 24061 ...@@ -953,11 +953,11 @@ S: Blacksburg, Virginia 24061
S: USA S: USA
N: Randy Dunlap N: Randy Dunlap
E: rdunlap@xenotime.net E: rdunlap@infradead.org
W: http://www.xenotime.net/linux/linux.html W: http://www.infradead.org/~rdunlap/
W: http://www.linux-usb.org
D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
D: x86 SMP, ACPI, bootflag hacking D: x86 SMP, ACPI, bootflag hacking
D: documentation, builds
S: (ask for current address) S: (ask for current address)
S: USA S: USA
......
...@@ -60,8 +60,7 @@ own source tree. For example: ...@@ -60,8 +60,7 @@ own source tree. For example:
"dontdiff" is a list of files which are generated by the kernel during "dontdiff" is a list of files which are generated by the kernel during
the build process, and should be ignored in any diff(1)-generated the build process, and should be ignored in any diff(1)-generated
patch. The "dontdiff" file is included in the kernel tree in patch. The "dontdiff" file is included in the kernel tree in
2.6.12 and later. For earlier kernel versions, you can get it 2.6.12 and later.
from <http://www.xenotime.net/linux/doc/dontdiff>.
Make sure your patch does not include any extra files which do not Make sure your patch does not include any extra files which do not
belong in a patch submission. Make sure to review your patch -after- belong in a patch submission. Make sure to review your patch -after-
......
...@@ -30,6 +30,7 @@ The target is named "raid" and it accepts the following parameters: ...@@ -30,6 +30,7 @@ The target is named "raid" and it accepts the following parameters:
raid10 Various RAID10 inspired algorithms chosen by additional params raid10 Various RAID10 inspired algorithms chosen by additional params
- RAID10: Striped Mirrors (aka 'Striping on top of mirrors') - RAID10: Striped Mirrors (aka 'Striping on top of mirrors')
- RAID1E: Integrated Adjacent Stripe Mirroring - RAID1E: Integrated Adjacent Stripe Mirroring
- RAID1E: Integrated Offset Stripe Mirroring
- and other similar RAID10 variants - and other similar RAID10 variants
Reference: Chapter 4 of Reference: Chapter 4 of
...@@ -64,15 +65,15 @@ The target is named "raid" and it accepts the following parameters: ...@@ -64,15 +65,15 @@ The target is named "raid" and it accepts the following parameters:
synchronisation state for each region. synchronisation state for each region.
[raid10_copies <# copies>] [raid10_copies <# copies>]
[raid10_format near] [raid10_format <near|far|offset>]
These two options are used to alter the default layout of These two options are used to alter the default layout of
a RAID10 configuration. The number of copies is can be a RAID10 configuration. The number of copies is can be
specified, but the default is 2. There are other variations specified, but the default is 2. There are also three
to how the copies are laid down - the default and only current variations to how the copies are laid down - the default
option is "near". Near copies are what most people think of is "near". Near copies are what most people think of with
with respect to mirroring. If these options are left respect to mirroring. If these options are left unspecified,
unspecified, or 'raid10_copies 2' and/or 'raid10_format near' or 'raid10_copies 2' and/or 'raid10_format near' are given,
are given, then the layouts for 2, 3 and 4 devices are: then the layouts for 2, 3 and 4 devices are:
2 drives 3 drives 4 drives 2 drives 3 drives 4 drives
-------- ---------- -------------- -------- ---------- --------------
A1 A1 A1 A1 A2 A1 A1 A2 A2 A1 A1 A1 A1 A2 A1 A1 A2 A2
...@@ -85,6 +86,33 @@ The target is named "raid" and it accepts the following parameters: ...@@ -85,6 +86,33 @@ The target is named "raid" and it accepts the following parameters:
3-device layout is what might be called a 'RAID1E - Integrated 3-device layout is what might be called a 'RAID1E - Integrated
Adjacent Stripe Mirroring'. Adjacent Stripe Mirroring'.
If 'raid10_copies 2' and 'raid10_format far', then the layouts
for 2, 3 and 4 devices are:
2 drives 3 drives 4 drives
-------- -------------- --------------------
A1 A2 A1 A2 A3 A1 A2 A3 A4
A3 A4 A4 A5 A6 A5 A6 A7 A8
A5 A6 A7 A8 A9 A9 A10 A11 A12
.. .. .. .. .. .. .. .. ..
A2 A1 A3 A1 A2 A2 A1 A4 A3
A4 A3 A6 A4 A5 A6 A5 A8 A7
A6 A5 A9 A7 A8 A10 A9 A12 A11
.. .. .. .. .. .. .. .. ..
If 'raid10_copies 2' and 'raid10_format offset', then the
layouts for 2, 3 and 4 devices are:
2 drives 3 drives 4 drives
-------- ------------ -----------------
A1 A2 A1 A2 A3 A1 A2 A3 A4
A2 A1 A3 A1 A2 A2 A1 A4 A3
A3 A4 A4 A5 A6 A5 A6 A7 A8
A4 A3 A6 A4 A5 A6 A5 A8 A7
A5 A6 A7 A8 A9 A9 A10 A11 A12
A6 A5 A9 A7 A8 A10 A9 A12 A11
.. .. .. .. .. .. .. .. ..
Here we see layouts closely akin to 'RAID1E - Integrated
Offset Stripe Mirroring'.
<#raid_devs>: The number of devices composing the array. <#raid_devs>: The number of devices composing the array.
Each device consists of two entries. The first is the device Each device consists of two entries. The first is the device
containing the metadata (if any); the second is the one containing the containing the metadata (if any); the second is the one containing the
...@@ -142,3 +170,5 @@ Version History ...@@ -142,3 +170,5 @@ Version History
1.3.0 Added support for RAID 10 1.3.0 Added support for RAID 10
1.3.1 Allow device replacement/rebuild for RAID 10 1.3.1 Allow device replacement/rebuild for RAID 10
1.3.2 Fix/improve redundancy checking for RAID10 1.3.2 Fix/improve redundancy checking for RAID10
1.4.0 Non-functional change. Removes arg from mapping function.
1.4.1 Add RAID10 "far" and "offset" algorithm support.
...@@ -15,7 +15,7 @@ Supported chips: ...@@ -15,7 +15,7 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1276.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -4,9 +4,14 @@ Kernel driver adt7410 ...@@ -4,9 +4,14 @@ Kernel driver adt7410
Supported chips: Supported chips:
* Analog Devices ADT7410 * Analog Devices ADT7410
Prefix: 'adt7410' Prefix: 'adt7410'
Addresses scanned: I2C 0x48 - 0x4B Addresses scanned: None
Datasheet: Publicly available at the Analog Devices website Datasheet: Publicly available at the Analog Devices website
http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf
* Analog Devices ADT7420
Prefix: 'adt7420'
Addresses scanned: None
Datasheet: Publicly available at the Analog Devices website
http://www.analog.com/static/imported-files/data_sheets/ADT7420.pdf
Author: Hartmut Knaack <knaack.h@gmx.de> Author: Hartmut Knaack <knaack.h@gmx.de>
...@@ -27,6 +32,10 @@ value per second or even justget one sample on demand for power saving. ...@@ -27,6 +32,10 @@ value per second or even justget one sample on demand for power saving.
Besides, it can completely power down its ADC, if power management is Besides, it can completely power down its ADC, if power management is
required. required.
The ADT7420 is register compatible, the only differences being the package,
a slightly narrower operating temperature range (-40°C to +150°C), and a
better accuracy (0.25°C instead of 0.50°C.)
Configuration Notes Configuration Notes
------------------- -------------------
......
...@@ -49,7 +49,7 @@ Supported chips: ...@@ -49,7 +49,7 @@ Supported chips:
Addresses scanned: I2C 0x18 - 0x1f Addresses scanned: I2C 0x18 - 0x1f
Author: Author:
Guenter Roeck <guenter.roeck@ericsson.com> Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -8,7 +8,7 @@ Supported devices: ...@@ -8,7 +8,7 @@ Supported devices:
Documentation: Documentation:
http://www.lineagepower.com/oem/pdf/CPLI2C.pdf http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -19,7 +19,7 @@ Supported chips: ...@@ -19,7 +19,7 @@ Supported chips:
Datasheet: Datasheet:
http://www.national.com/pf/LM/LM5066.html http://www.national.com/pf/LM/LM5066.html
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -5,13 +5,13 @@ Supported chips: ...@@ -5,13 +5,13 @@ Supported chips:
* Linear Technology LTC2978 * Linear Technology LTC2978
Prefix: 'ltc2978' Prefix: 'ltc2978'
Addresses scanned: - Addresses scanned: -
Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf Datasheet: http://www.linear.com/product/ltc2978
* Linear Technology LTC3880 * Linear Technology LTC3880
Prefix: 'ltc3880' Prefix: 'ltc3880'
Addresses scanned: - Addresses scanned: -
Datasheet: http://cds.linear.com/docs/Datasheet/3880f.pdf Datasheet: http://www.linear.com/product/ltc3880
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -8,7 +8,7 @@ Supported chips: ...@@ -8,7 +8,7 @@ Supported chips:
Datasheet: Datasheet:
http://cds.linear.com/docs/Datasheet/42612fb.pdf http://cds.linear.com/docs/Datasheet/42612fb.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -7,7 +7,7 @@ Supported chips: ...@@ -7,7 +7,7 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -24,7 +24,7 @@ Supported chips: ...@@ -24,7 +24,7 @@ Supported chips:
http://datasheets.maxim-ic.com/en/ds/MAX16070-MAX16071.pdf http://datasheets.maxim-ic.com/en/ds/MAX16070-MAX16071.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -27,7 +27,7 @@ Supported chips: ...@@ -27,7 +27,7 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34461.pdf Datasheet: http://datasheets.maximintegrated.com/en/ds/MAX34461.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -7,7 +7,7 @@ Supported chips: ...@@ -7,7 +7,7 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -34,7 +34,7 @@ Supported chips: ...@@ -34,7 +34,7 @@ Supported chips:
Addresses scanned: - Addresses scanned: -
Datasheet: n.a. Datasheet: n.a.
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -29,7 +29,7 @@ Supported chips: ...@@ -29,7 +29,7 @@ Supported chips:
http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf http://www.summitmicro.com/prod_select/summary/SMM766/SMM766_2086.pdf
http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Module Parameters Module Parameters
......
...@@ -11,7 +11,7 @@ Supported chips: ...@@ -11,7 +11,7 @@ Supported chips:
http://focus.ti.com/lit/ds/symlink/ucd9090.pdf http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
http://focus.ti.com/lit/ds/symlink/ucd90910.pdf http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -15,7 +15,7 @@ Supported chips: ...@@ -15,7 +15,7 @@ Supported chips:
http://focus.ti.com/lit/ds/symlink/ucd9246.pdf http://focus.ti.com/lit/ds/symlink/ucd9246.pdf
http://focus.ti.com/lit/ds/symlink/ucd9248.pdf http://focus.ti.com/lit/ds/symlink/ucd9248.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
...@@ -54,7 +54,7 @@ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146401 ...@@ -54,7 +54,7 @@ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146401
http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146256 http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146256
Author: Guenter Roeck <guenter.roeck@ericsson.com> Author: Guenter Roeck <linux@roeck-us.net>
Description Description
......
*=============* Operating Performance Points (OPP) Library
* OPP Library * ==========================================
*=============*
(C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated (C) 2009-2010 Nishanth Menon <nm@ti.com>, Texas Instruments Incorporated
...@@ -16,15 +15,31 @@ Contents ...@@ -16,15 +15,31 @@ Contents
1. Introduction 1. Introduction
=============== ===============
1.1 What is an Operating Performance Point (OPP)?
Complex SoCs of today consists of a multiple sub-modules working in conjunction. Complex SoCs of today consists of a multiple sub-modules working in conjunction.
In an operational system executing varied use cases, not all modules in the SoC In an operational system executing varied use cases, not all modules in the SoC
need to function at their highest performing frequency all the time. To need to function at their highest performing frequency all the time. To
facilitate this, sub-modules in a SoC are grouped into domains, allowing some facilitate this, sub-modules in a SoC are grouped into domains, allowing some
domains to run at lower voltage and frequency while other domains are loaded domains to run at lower voltage and frequency while other domains run at
more. The set of discrete tuples consisting of frequency and voltage pairs that voltage/frequency pairs that are higher.
The set of discrete tuples consisting of frequency and voltage pairs that
the device will support per domain are called Operating Performance Points or the device will support per domain are called Operating Performance Points or
OPPs. OPPs.
As an example:
Let us consider an MPU device which supports the following:
{300MHz at minimum voltage of 1V}, {800MHz at minimum voltage of 1.2V},
{1GHz at minimum voltage of 1.3V}
We can represent these as three OPPs as the following {Hz, uV} tuples:
{300000000, 1000000}
{800000000, 1200000}
{1000000000, 1300000}
1.2 Operating Performance Points Library
OPP library provides a set of helper functions to organize and query the OPP OPP library provides a set of helper functions to organize and query the OPP
information. The library is located in drivers/base/power/opp.c and the header information. The library is located in drivers/base/power/opp.c and the header
is located in include/linux/opp.h. OPP library can be enabled by enabling is located in include/linux/opp.h. OPP library can be enabled by enabling
......
...@@ -170,5 +170,5 @@ Reminder: sizeof() result is of type size_t. ...@@ -170,5 +170,5 @@ Reminder: sizeof() result is of type size_t.
Thank you for your cooperation and attention. Thank you for your cooperation and attention.
By Randy Dunlap <rdunlap@xenotime.net> and By Randy Dunlap <rdunlap@infradead.org> and
Andrew Murray <amurray@mpc-data.co.uk> Andrew Murray <amurray@mpc-data.co.uk>
...@@ -114,12 +114,6 @@ Maintainers List (try to look for most precise areas first) ...@@ -114,12 +114,6 @@ Maintainers List (try to look for most precise areas first)
----------------------------------- -----------------------------------
3C505 NETWORK DRIVER
M: Philip Blundell <philb@gnu.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/i825xx/3c505*
3C59X NETWORK DRIVER 3C59X NETWORK DRIVER
M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de> M: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
L: netdev@vger.kernel.org L: netdev@vger.kernel.org
...@@ -2361,12 +2355,6 @@ W: http://www.arm.linux.org.uk/ ...@@ -2361,12 +2355,6 @@ W: http://www.arm.linux.org.uk/
S: Maintained S: Maintained
F: drivers/video/cyber2000fb.* F: drivers/video/cyber2000fb.*
CYCLADES 2X SYNC CARD DRIVER
M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
W: http://oops.ghostprotocols.net:81/blog
S: Maintained
F: drivers/net/wan/cycx*
CYCLADES ASYNC MUX DRIVER CYCLADES ASYNC MUX DRIVER
W: http://www.cyclades.com/ W: http://www.cyclades.com/
S: Orphan S: Orphan
...@@ -3067,12 +3055,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git ...@@ -3067,12 +3055,6 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
F: drivers/video/s1d13xxxfb.c F: drivers/video/s1d13xxxfb.c
F: include/video/s1d13xxxfb.h F: include/video/s1d13xxxfb.h
ETHEREXPRESS-16 NETWORK DRIVER
M: Philip Blundell <philb@gnu.org>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/i825xx/eexpress.*
ETHERNET BRIDGE ETHERNET BRIDGE
M: Stephen Hemminger <stephen@networkplumber.org> M: Stephen Hemminger <stephen@networkplumber.org>
L: bridge@lists.linux-foundation.org L: bridge@lists.linux-foundation.org
......
VERSION = 3 VERSION = 3
PATCHLEVEL = 9 PATCHLEVEL = 9
SUBLEVEL = 0 SUBLEVEL = 0
EXTRAVERSION = -rc1 EXTRAVERSION = -rc2
NAME = Unicycling Gorilla NAME = Unicycling Gorilla
# *DOCUMENTATION* # *DOCUMENTATION*
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* initial bootloader stuff.. * initial bootloader stuff..
*/ */
#include <asm/pal.h>
.set noreorder .set noreorder
.globl __start .globl __start
......
...@@ -120,7 +120,7 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS) ...@@ -120,7 +120,7 @@ ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
endif endif
ccflags-y := -fpic -fno-builtin -I$(obj) ccflags-y := -fpic -mno-single-pic-base -fno-builtin -I$(obj)
asflags-y := -Wa,-march=all -DZIMAGE asflags-y := -Wa,-march=all -DZIMAGE
# Supply kernel BSS size to the decompressor via a linker symbol. # Supply kernel BSS size to the decompressor via a linker symbol.
......
...@@ -5,15 +5,15 @@ ...@@ -5,15 +5,15 @@
typedef struct { typedef struct {
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
u64 id; atomic64_t id;
#endif #endif
unsigned int vmalloc_seq; unsigned int vmalloc_seq;
} mm_context_t; } mm_context_t;
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
#define ASID_BITS 8 #define ASID_BITS 8
#define ASID_MASK ((~0ULL) << ASID_BITS) #define ASID_MASK ((~0ULL) << ASID_BITS)
#define ASID(mm) ((mm)->context.id & ~ASID_MASK) #define ASID(mm) ((mm)->context.id.counter & ~ASID_MASK)
#else #else
#define ASID(mm) (0) #define ASID(mm) (0)
#endif #endif
...@@ -26,7 +26,7 @@ typedef struct { ...@@ -26,7 +26,7 @@ typedef struct {
* modified for 2.6 by Hyok S. Choi <hyok.choi@samsung.com> * modified for 2.6 by Hyok S. Choi <hyok.choi@samsung.com>
*/ */
typedef struct { typedef struct {
unsigned long end_brk; unsigned long end_brk;
} mm_context_t; } mm_context_t;
#endif #endif
......
...@@ -25,7 +25,7 @@ void __check_vmalloc_seq(struct mm_struct *mm); ...@@ -25,7 +25,7 @@ void __check_vmalloc_seq(struct mm_struct *mm);
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk); void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
#define init_new_context(tsk,mm) ({ mm->context.id = 0; }) #define init_new_context(tsk,mm) ({ atomic64_set(&mm->context.id, 0); 0; })
#else /* !CONFIG_CPU_HAS_ASID */ #else /* !CONFIG_CPU_HAS_ASID */
......
...@@ -34,10 +34,13 @@ ...@@ -34,10 +34,13 @@
#define TLB_V6_D_ASID (1 << 17) #define TLB_V6_D_ASID (1 << 17)
#define TLB_V6_I_ASID (1 << 18) #define TLB_V6_I_ASID (1 << 18)
#define TLB_V6_BP (1 << 19)
/* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */ /* Unified Inner Shareable TLB operations (ARMv7 MP extensions) */
#define TLB_V7_UIS_PAGE (1 << 19) #define TLB_V7_UIS_PAGE (1 << 20)
#define TLB_V7_UIS_FULL (1 << 20) #define TLB_V7_UIS_FULL (1 << 21)
#define TLB_V7_UIS_ASID (1 << 21) #define TLB_V7_UIS_ASID (1 << 22)
#define TLB_V7_UIS_BP (1 << 23)
#define TLB_BARRIER (1 << 28) #define TLB_BARRIER (1 << 28)
#define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */ #define TLB_L2CLEAN_FR (1 << 29) /* Feroceon */
...@@ -150,7 +153,8 @@ ...@@ -150,7 +153,8 @@
#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \ #define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V6_I_FULL | TLB_V6_D_FULL | \ TLB_V6_I_FULL | TLB_V6_D_FULL | \
TLB_V6_I_PAGE | TLB_V6_D_PAGE | \ TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
TLB_V6_I_ASID | TLB_V6_D_ASID) TLB_V6_I_ASID | TLB_V6_D_ASID | \
TLB_V6_BP)
#ifdef CONFIG_CPU_TLB_V6 #ifdef CONFIG_CPU_TLB_V6
# define v6wbi_possible_flags v6wbi_tlb_flags # define v6wbi_possible_flags v6wbi_tlb_flags
...@@ -166,9 +170,11 @@ ...@@ -166,9 +170,11 @@
#endif #endif
#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \ #define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID) TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | \
TLB_V7_UIS_ASID | TLB_V7_UIS_BP)
#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \ #define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BARRIER | \
TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID) TLB_V6_U_FULL | TLB_V6_U_PAGE | \
TLB_V6_U_ASID | TLB_V6_BP)
#ifdef CONFIG_CPU_TLB_V7 #ifdef CONFIG_CPU_TLB_V7
...@@ -430,6 +436,20 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr) ...@@ -430,6 +436,20 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
} }
} }
static inline void local_flush_bp_all(void)
{
const int zero = 0;
const unsigned int __tlb_flag = __cpu_tlb_flags;
if (tlb_flag(TLB_V7_UIS_BP))
asm("mcr p15, 0, %0, c7, c1, 6" : : "r" (zero));
else if (tlb_flag(TLB_V6_BP))
asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero));
if (tlb_flag(TLB_BARRIER))
isb();
}
/* /*
* flush_pmd_entry * flush_pmd_entry
* *
...@@ -480,6 +500,7 @@ static inline void clean_pmd_entry(void *pmd) ...@@ -480,6 +500,7 @@ static inline void clean_pmd_entry(void *pmd)
#define flush_tlb_kernel_page local_flush_tlb_kernel_page #define flush_tlb_kernel_page local_flush_tlb_kernel_page
#define flush_tlb_range local_flush_tlb_range #define flush_tlb_range local_flush_tlb_range
#define flush_tlb_kernel_range local_flush_tlb_kernel_range #define flush_tlb_kernel_range local_flush_tlb_kernel_range
#define flush_bp_all local_flush_bp_all
#else #else
extern void flush_tlb_all(void); extern void flush_tlb_all(void);
extern void flush_tlb_mm(struct mm_struct *mm); extern void flush_tlb_mm(struct mm_struct *mm);
...@@ -487,6 +508,7 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr); ...@@ -487,6 +508,7 @@ extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr);
extern void flush_tlb_kernel_page(unsigned long kaddr); extern void flush_tlb_kernel_page(unsigned long kaddr);
extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
extern void flush_bp_all(void);
#endif #endif
/* /*
......
...@@ -404,7 +404,7 @@ ...@@ -404,7 +404,7 @@
#define __NR_setns (__NR_SYSCALL_BASE+375) #define __NR_setns (__NR_SYSCALL_BASE+375)
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376) #define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377) #define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
/* 378 for kcmp */ #define __NR_kcmp (__NR_SYSCALL_BASE+378)
#define __NR_finit_module (__NR_SYSCALL_BASE+379) #define __NR_finit_module (__NR_SYSCALL_BASE+379)
/* /*
......
...@@ -110,7 +110,7 @@ int main(void) ...@@ -110,7 +110,7 @@ int main(void)
BLANK(); BLANK();
#endif #endif
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id)); DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id.counter));
BLANK(); BLANK();
#endif #endif
DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
......
...@@ -387,7 +387,7 @@ ...@@ -387,7 +387,7 @@
/* 375 */ CALL(sys_setns) /* 375 */ CALL(sys_setns)
CALL(sys_process_vm_readv) CALL(sys_process_vm_readv)
CALL(sys_process_vm_writev) CALL(sys_process_vm_writev)
CALL(sys_ni_syscall) /* reserved for sys_kcmp */ CALL(sys_kcmp)
CALL(sys_finit_module) CALL(sys_finit_module)
#ifndef syscalls_counted #ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
......
...@@ -184,13 +184,22 @@ __create_page_tables: ...@@ -184,13 +184,22 @@ __create_page_tables:
orr r3, r3, #3 @ PGD block type orr r3, r3, #3 @ PGD block type
mov r6, #4 @ PTRS_PER_PGD mov r6, #4 @ PTRS_PER_PGD
mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER
1: str r3, [r0], #4 @ set bottom PGD entry bits 1:
#ifdef CONFIG_CPU_ENDIAN_BE8
str r7, [r0], #4 @ set top PGD entry bits str r7, [r0], #4 @ set top PGD entry bits
str r3, [r0], #4 @ set bottom PGD entry bits
#else
str r3, [r0], #4 @ set bottom PGD entry bits
str r7, [r0], #4 @ set top PGD entry bits
#endif
add r3, r3, #0x1000 @ next PMD table add r3, r3, #0x1000 @ next PMD table
subs r6, r6, #1 subs r6, r6, #1
bne 1b bne 1b
add r4, r4, #0x1000 @ point to the PMD tables add r4, r4, #0x1000 @ point to the PMD tables
#ifdef CONFIG_CPU_ENDIAN_BE8
add r4, r4, #4 @ we only write the bottom word
#endif
#endif #endif
ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
...@@ -258,6 +267,11 @@ __create_page_tables: ...@@ -258,6 +267,11 @@ __create_page_tables:
addne r6, r6, #1 << SECTION_SHIFT addne r6, r6, #1 << SECTION_SHIFT
strne r6, [r3] strne r6, [r3]
#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
sub r4, r4, #4 @ Fixup page table pointer
@ for 64-bit descriptors
#endif
#ifdef CONFIG_DEBUG_LL #ifdef CONFIG_DEBUG_LL
#if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING)
/* /*
...@@ -276,13 +290,17 @@ __create_page_tables: ...@@ -276,13 +290,17 @@ __create_page_tables:
orr r3, r7, r3, lsl #SECTION_SHIFT orr r3, r7, r3, lsl #SECTION_SHIFT
#ifdef CONFIG_ARM_LPAE #ifdef CONFIG_ARM_LPAE
mov r7, #1 << (54 - 32) @ XN mov r7, #1 << (54 - 32) @ XN
#ifdef CONFIG_CPU_ENDIAN_BE8
str r7, [r0], #4
str r3, [r0], #4
#else #else
orr r3, r3, #PMD_SECT_XN
#endif
str r3, [r0], #4 str r3, [r0], #4
#ifdef CONFIG_ARM_LPAE
str r7, [r0], #4 str r7, [r0], #4
#endif #endif
#else
orr r3, r3, #PMD_SECT_XN
str r3, [r0], #4
#endif
#else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */ #else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */
/* we don't need any serial debugging mappings */ /* we don't need any serial debugging mappings */
......
...@@ -1023,7 +1023,7 @@ static void reset_ctrl_regs(void *unused) ...@@ -1023,7 +1023,7 @@ static void reset_ctrl_regs(void *unused)
static int __cpuinit dbg_reset_notify(struct notifier_block *self, static int __cpuinit dbg_reset_notify(struct notifier_block *self,
unsigned long action, void *cpu) unsigned long action, void *cpu)
{ {
if (action == CPU_ONLINE) if ((action & ~CPU_TASKS_FROZEN) == CPU_ONLINE)
smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1); smp_call_function_single((int)cpu, reset_ctrl_regs, NULL, 1);
return NOTIFY_OK; return NOTIFY_OK;
......
...@@ -400,7 +400,7 @@ __hw_perf_event_init(struct perf_event *event) ...@@ -400,7 +400,7 @@ __hw_perf_event_init(struct perf_event *event)
} }
if (event->group_leader != event) { if (event->group_leader != event) {
if (validate_group(event) != 0); if (validate_group(event) != 0)
return -EINVAL; return -EINVAL;
} }
...@@ -484,7 +484,7 @@ const struct dev_pm_ops armpmu_dev_pm_ops = { ...@@ -484,7 +484,7 @@ const struct dev_pm_ops armpmu_dev_pm_ops = {
SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL) SET_RUNTIME_PM_OPS(armpmu_runtime_suspend, armpmu_runtime_resume, NULL)
}; };
static void __init armpmu_init(struct arm_pmu *armpmu) static void armpmu_init(struct arm_pmu *armpmu)
{ {
atomic_set(&armpmu->active_events, 0); atomic_set(&armpmu->active_events, 0);
mutex_init(&armpmu->reserve_mutex); mutex_init(&armpmu->reserve_mutex);
......
...@@ -774,7 +774,7 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] ...@@ -774,7 +774,7 @@ static const unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
/* /*
* PMXEVTYPER: Event selection reg * PMXEVTYPER: Event selection reg
*/ */
#define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ #define ARMV7_EVTYPE_MASK 0xc80000ff /* Mask for writable bits */
#define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ #define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */
/* /*
......
...@@ -285,6 +285,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) ...@@ -285,6 +285,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
* switch away from it before attempting any exclusive accesses. * switch away from it before attempting any exclusive accesses.
*/ */
cpu_switch_mm(mm->pgd, mm); cpu_switch_mm(mm->pgd, mm);
local_flush_bp_all();
enter_lazy_tlb(mm, current); enter_lazy_tlb(mm, current);
local_flush_tlb_all(); local_flush_tlb_all();
......
...@@ -64,6 +64,11 @@ static inline void ipi_flush_tlb_kernel_range(void *arg) ...@@ -64,6 +64,11 @@ static inline void ipi_flush_tlb_kernel_range(void *arg)
local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end); local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
} }
static inline void ipi_flush_bp_all(void *ignored)
{
local_flush_bp_all();
}
void flush_tlb_all(void) void flush_tlb_all(void)
{ {
if (tlb_ops_need_broadcast()) if (tlb_ops_need_broadcast())
...@@ -127,3 +132,10 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) ...@@ -127,3 +132,10 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
local_flush_tlb_kernel_range(start, end); local_flush_tlb_kernel_range(start, end);
} }
void flush_bp_all(void)
{
if (tlb_ops_need_broadcast())
on_each_cpu(ipi_flush_bp_all, NULL, 1);
else
local_flush_bp_all();
}
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <asm/smp_plat.h>
#include <asm/smp_twd.h> #include <asm/smp_twd.h>
#include <asm/localtimer.h> #include <asm/localtimer.h>
...@@ -373,6 +374,9 @@ void __init twd_local_timer_of_register(void) ...@@ -373,6 +374,9 @@ void __init twd_local_timer_of_register(void)
struct device_node *np; struct device_node *np;
int err; int err;
if (!is_smp() || !setup_max_cpus)
return;
np = of_find_matching_node(NULL, twd_of_match); np = of_find_matching_node(NULL, twd_of_match);
if (!np) if (!np)
return; return;
......
...@@ -68,6 +68,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long)) ...@@ -68,6 +68,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
ret = __cpu_suspend(arg, fn); ret = __cpu_suspend(arg, fn);
if (ret == 0) { if (ret == 0) {
cpu_switch_mm(mm->pgd, mm); cpu_switch_mm(mm->pgd, mm);
local_flush_bp_all();
local_flush_tlb_all(); local_flush_tlb_all();
} }
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
1: subs r2, r2, #4 @ 1 do we have enough 1: subs r2, r2, #4 @ 1 do we have enough
blt 5f @ 1 bytes to align with? blt 5f @ 1 bytes to align with?
cmp r3, #2 @ 1 cmp r3, #2 @ 1
strltb r1, [r0], #1 @ 1 strltb r1, [ip], #1 @ 1
strleb r1, [r0], #1 @ 1 strleb r1, [ip], #1 @ 1
strb r1, [r0], #1 @ 1 strb r1, [ip], #1 @ 1
add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3))
/* /*
* The pointer is now aligned and the length is adjusted. Try doing the * The pointer is now aligned and the length is adjusted. Try doing the
...@@ -29,10 +29,14 @@ ...@@ -29,10 +29,14 @@
*/ */
ENTRY(memset) ENTRY(memset)
ands r3, r0, #3 @ 1 unaligned? /*
* Preserve the contents of r0 for the return value.
*/
mov ip, r0
ands r3, ip, #3 @ 1 unaligned?
bne 1b @ 1 bne 1b @ 1
/* /*
* we know that the pointer in r0 is aligned to a word boundary. * we know that the pointer in ip is aligned to a word boundary.
*/ */
orr r1, r1, r1, lsl #8 orr r1, r1, r1, lsl #8
orr r1, r1, r1, lsl #16 orr r1, r1, r1, lsl #16
...@@ -43,29 +47,28 @@ ENTRY(memset) ...@@ -43,29 +47,28 @@ ENTRY(memset)
#if ! CALGN(1)+0 #if ! CALGN(1)+0
/* /*
* We need an extra register for this loop - save the return address and * We need 2 extra registers for this loop - use r8 and the LR
* use the LR
*/ */
str lr, [sp, #-4]! stmfd sp!, {r8, lr}
mov ip, r1 mov r8, r1
mov lr, r1 mov lr, r1
2: subs r2, r2, #64 2: subs r2, r2, #64
stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time.
stmgeia r0!, {r1, r3, ip, lr} stmgeia ip!, {r1, r3, r8, lr}
stmgeia r0!, {r1, r3, ip, lr} stmgeia ip!, {r1, r3, r8, lr}
stmgeia r0!, {r1, r3, ip, lr} stmgeia ip!, {r1, r3, r8, lr}
bgt 2b bgt 2b
ldmeqfd sp!, {pc} @ Now <64 bytes to go. ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go.
/* /*
* No need to correct the count; we're only testing bits from now on * No need to correct the count; we're only testing bits from now on
*/ */
tst r2, #32 tst r2, #32
stmneia r0!, {r1, r3, ip, lr} stmneia ip!, {r1, r3, r8, lr}
stmneia r0!, {r1, r3, ip, lr} stmneia ip!, {r1, r3, r8, lr}
tst r2, #16 tst r2, #16
stmneia r0!, {r1, r3, ip, lr} stmneia ip!, {r1, r3, r8, lr}
ldr lr, [sp], #4 ldmfd sp!, {r8, lr}
#else #else
...@@ -74,54 +77,54 @@ ENTRY(memset) ...@@ -74,54 +77,54 @@ ENTRY(memset)
* whole cache lines at once. * whole cache lines at once.
*/ */
stmfd sp!, {r4-r7, lr} stmfd sp!, {r4-r8, lr}
mov r4, r1 mov r4, r1
mov r5, r1 mov r5, r1
mov r6, r1 mov r6, r1
mov r7, r1 mov r7, r1
mov ip, r1 mov r8, r1
mov lr, r1 mov lr, r1
cmp r2, #96 cmp r2, #96
tstgt r0, #31 tstgt ip, #31
ble 3f ble 3f
and ip, r0, #31 and r8, ip, #31
rsb ip, ip, #32 rsb r8, r8, #32
sub r2, r2, ip sub r2, r2, r8
movs ip, ip, lsl #(32 - 4) movs r8, r8, lsl #(32 - 4)
stmcsia r0!, {r4, r5, r6, r7} stmcsia ip!, {r4, r5, r6, r7}
stmmiia r0!, {r4, r5} stmmiia ip!, {r4, r5}
tst ip, #(1 << 30) tst r8, #(1 << 30)
mov ip, r1 mov r8, r1
strne r1, [r0], #4 strne r1, [ip], #4
3: subs r2, r2, #64 3: subs r2, r2, #64
stmgeia r0!, {r1, r3-r7, ip, lr} stmgeia ip!, {r1, r3-r8, lr}
stmgeia r0!, {r1, r3-r7, ip, lr} stmgeia ip!, {r1, r3-r8, lr}
bgt 3b bgt 3b
ldmeqfd sp!, {r4-r7, pc} ldmeqfd sp!, {r4-r8, pc}
tst r2, #32 tst r2, #32
stmneia r0!, {r1, r3-r7, ip, lr} stmneia ip!, {r1, r3-r8, lr}
tst r2, #16 tst r2, #16
stmneia r0!, {r4-r7} stmneia ip!, {r4-r7}
ldmfd sp!, {r4-r7, lr} ldmfd sp!, {r4-r8, lr}
#endif #endif
4: tst r2, #8 4: tst r2, #8
stmneia r0!, {r1, r3} stmneia ip!, {r1, r3}
tst r2, #4 tst r2, #4
strne r1, [r0], #4 strne r1, [ip], #4
/* /*
* When we get here, we've got less than 4 bytes to zero. We * When we get here, we've got less than 4 bytes to zero. We
* may have an unaligned pointer as well. * may have an unaligned pointer as well.
*/ */
5: tst r2, #2 5: tst r2, #2
strneb r1, [r0], #1 strneb r1, [ip], #1
strneb r1, [r0], #1 strneb r1, [ip], #1
tst r2, #1 tst r2, #1
strneb r1, [r0], #1 strneb r1, [ip], #1
mov pc, lr mov pc, lr
ENDPROC(memset) ENDPROC(memset)
...@@ -168,7 +168,7 @@ void __init netx_init_irq(void) ...@@ -168,7 +168,7 @@ void __init netx_init_irq(void)
{ {
int irq; int irq;
vic_init(io_p2v(NETX_PA_VIC), 0, ~0, 0); vic_init(io_p2v(NETX_PA_VIC), NETX_IRQ_VIC_START, ~0, 0);
for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
irq_set_chip_and_handler(irq, &netx_hif_chip, irq_set_chip_and_handler(irq, &netx_hif_chip,
......
...@@ -17,42 +17,42 @@ ...@@ -17,42 +17,42 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define NETX_IRQ_VIC_START 0 #define NETX_IRQ_VIC_START 64
#define NETX_IRQ_SOFTINT 0 #define NETX_IRQ_SOFTINT (NETX_IRQ_VIC_START + 0)
#define NETX_IRQ_TIMER0 1 #define NETX_IRQ_TIMER0 (NETX_IRQ_VIC_START + 1)
#define NETX_IRQ_TIMER1 2 #define NETX_IRQ_TIMER1 (NETX_IRQ_VIC_START + 2)
#define NETX_IRQ_TIMER2 3 #define NETX_IRQ_TIMER2 (NETX_IRQ_VIC_START + 3)
#define NETX_IRQ_SYSTIME_NS 4 #define NETX_IRQ_SYSTIME_NS (NETX_IRQ_VIC_START + 4)
#define NETX_IRQ_SYSTIME_S 5 #define NETX_IRQ_SYSTIME_S (NETX_IRQ_VIC_START + 5)
#define NETX_IRQ_GPIO_15 6 #define NETX_IRQ_GPIO_15 (NETX_IRQ_VIC_START + 6)
#define NETX_IRQ_WATCHDOG 7 #define NETX_IRQ_WATCHDOG (NETX_IRQ_VIC_START + 7)
#define NETX_IRQ_UART0 8 #define NETX_IRQ_UART0 (NETX_IRQ_VIC_START + 8)
#define NETX_IRQ_UART1 9 #define NETX_IRQ_UART1 (NETX_IRQ_VIC_START + 9)
#define NETX_IRQ_UART2 10 #define NETX_IRQ_UART2 (NETX_IRQ_VIC_START + 10)
#define NETX_IRQ_USB 11 #define NETX_IRQ_USB (NETX_IRQ_VIC_START + 11)
#define NETX_IRQ_SPI 12 #define NETX_IRQ_SPI (NETX_IRQ_VIC_START + 12)
#define NETX_IRQ_I2C 13 #define NETX_IRQ_I2C (NETX_IRQ_VIC_START + 13)
#define NETX_IRQ_LCD 14 #define NETX_IRQ_LCD (NETX_IRQ_VIC_START + 14)
#define NETX_IRQ_HIF 15 #define NETX_IRQ_HIF (NETX_IRQ_VIC_START + 15)
#define NETX_IRQ_GPIO_0_14 16 #define NETX_IRQ_GPIO_0_14 (NETX_IRQ_VIC_START + 16)
#define NETX_IRQ_XPEC0 17 #define NETX_IRQ_XPEC0 (NETX_IRQ_VIC_START + 17)
#define NETX_IRQ_XPEC1 18 #define NETX_IRQ_XPEC1 (NETX_IRQ_VIC_START + 18)
#define NETX_IRQ_XPEC2 19 #define NETX_IRQ_XPEC2 (NETX_IRQ_VIC_START + 19)
#define NETX_IRQ_XPEC3 20 #define NETX_IRQ_XPEC3 (NETX_IRQ_VIC_START + 20)
#define NETX_IRQ_XPEC(no) (17 + (no)) #define NETX_IRQ_XPEC(no) (NETX_IRQ_VIC_START + 17 + (no))
#define NETX_IRQ_MSYNC0 21 #define NETX_IRQ_MSYNC0 (NETX_IRQ_VIC_START + 21)
#define NETX_IRQ_MSYNC1 22 #define NETX_IRQ_MSYNC1 (NETX_IRQ_VIC_START + 22)
#define NETX_IRQ_MSYNC2 23 #define NETX_IRQ_MSYNC2 (NETX_IRQ_VIC_START + 23)
#define NETX_IRQ_MSYNC3 24 #define NETX_IRQ_MSYNC3 (NETX_IRQ_VIC_START + 24)
#define NETX_IRQ_IRQ_PHY 25 #define NETX_IRQ_IRQ_PHY (NETX_IRQ_VIC_START + 25)
#define NETX_IRQ_ISO_AREA 26 #define NETX_IRQ_ISO_AREA (NETX_IRQ_VIC_START + 26)
/* int 27 is reserved */ /* int 27 is reserved */
/* int 28 is reserved */ /* int 28 is reserved */
#define NETX_IRQ_TIMER3 29 #define NETX_IRQ_TIMER3 (NETX_IRQ_VIC_START + 29)
#define NETX_IRQ_TIMER4 30 #define NETX_IRQ_TIMER4 (NETX_IRQ_VIC_START + 30)
/* int 31 is reserved */ /* int 31 is reserved */
#define NETX_IRQS 32 #define NETX_IRQS (NETX_IRQ_VIC_START + 32)
/* for multiplexed irqs on gpio 0..14 */ /* for multiplexed irqs on gpio 0..14 */
#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x)) #define NETX_IRQ_GPIO(x) (NETX_IRQS + (x))
......
...@@ -152,9 +152,9 @@ static int is_reserved_asid(u64 asid) ...@@ -152,9 +152,9 @@ static int is_reserved_asid(u64 asid)
return 0; return 0;
} }
static void new_context(struct mm_struct *mm, unsigned int cpu) static u64 new_context(struct mm_struct *mm, unsigned int cpu)
{ {
u64 asid = mm->context.id; u64 asid = atomic64_read(&mm->context.id);
u64 generation = atomic64_read(&asid_generation); u64 generation = atomic64_read(&asid_generation);
if (asid != 0 && is_reserved_asid(asid)) { if (asid != 0 && is_reserved_asid(asid)) {
...@@ -181,13 +181,14 @@ static void new_context(struct mm_struct *mm, unsigned int cpu) ...@@ -181,13 +181,14 @@ static void new_context(struct mm_struct *mm, unsigned int cpu)
cpumask_clear(mm_cpumask(mm)); cpumask_clear(mm_cpumask(mm));
} }
mm->context.id = asid; return asid;
} }
void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
{ {
unsigned long flags; unsigned long flags;
unsigned int cpu = smp_processor_id(); unsigned int cpu = smp_processor_id();
u64 asid;
if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq)) if (unlikely(mm->context.vmalloc_seq != init_mm.context.vmalloc_seq))
__check_vmalloc_seq(mm); __check_vmalloc_seq(mm);
...@@ -198,20 +199,26 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk) ...@@ -198,20 +199,26 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
*/ */
cpu_set_reserved_ttbr0(); cpu_set_reserved_ttbr0();
if (!((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS) asid = atomic64_read(&mm->context.id);
&& atomic64_xchg(&per_cpu(active_asids, cpu), mm->context.id)) if (!((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS)
&& atomic64_xchg(&per_cpu(active_asids, cpu), asid))
goto switch_mm_fastpath; goto switch_mm_fastpath;
raw_spin_lock_irqsave(&cpu_asid_lock, flags); raw_spin_lock_irqsave(&cpu_asid_lock, flags);
/* Check that our ASID belongs to the current generation. */ /* Check that our ASID belongs to the current generation. */
if ((mm->context.id ^ atomic64_read(&asid_generation)) >> ASID_BITS) asid = atomic64_read(&mm->context.id);
new_context(mm, cpu); if ((asid ^ atomic64_read(&asid_generation)) >> ASID_BITS) {
asid = new_context(mm, cpu);
atomic64_set(&per_cpu(active_asids, cpu), mm->context.id); atomic64_set(&mm->context.id, asid);
cpumask_set_cpu(cpu, mm_cpumask(mm)); }
if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) {
local_flush_bp_all();
local_flush_tlb_all(); local_flush_tlb_all();
}
atomic64_set(&per_cpu(active_asids, cpu), asid);
cpumask_set_cpu(cpu, mm_cpumask(mm));
raw_spin_unlock_irqrestore(&cpu_asid_lock, flags); raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
switch_mm_fastpath: switch_mm_fastpath:
......
...@@ -141,6 +141,7 @@ void setup_mm_for_reboot(void) ...@@ -141,6 +141,7 @@ void setup_mm_for_reboot(void)
{ {
/* Switch to the identity mapping. */ /* Switch to the identity mapping. */
cpu_switch_mm(idmap_pgd, &init_mm); cpu_switch_mm(idmap_pgd, &init_mm);
local_flush_bp_all();
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
/* /*
......
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
ENTRY(cpu_v7_switch_mm) ENTRY(cpu_v7_switch_mm)
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
mmid r1, r1 @ get mm->context.id mmid r1, r1 @ get mm->context.id
and r3, r1, #0xff asid r3, r1
mov r3, r3, lsl #(48 - 32) @ ASID mov r3, r3, lsl #(48 - 32) @ ASID
mcrr p15, 0, r0, r3, c2 @ set TTB 0 mcrr p15, 0, r0, r3, c2 @ set TTB 0
isb isb
......
...@@ -619,6 +619,7 @@ static struct file_system_type pfm_fs_type = { ...@@ -619,6 +619,7 @@ static struct file_system_type pfm_fs_type = {
.mount = pfmfs_mount, .mount = pfmfs_mount,
.kill_sb = kill_anon_super, .kill_sb = kill_anon_super,
}; };
MODULE_ALIAS_FS("pfmfs");
DEFINE_PER_CPU(unsigned long, pfm_syst_info); DEFINE_PER_CPU(unsigned long, pfm_syst_info);
DEFINE_PER_CPU(struct task_struct *, pmu_owner); DEFINE_PER_CPU(struct task_struct *, pmu_owner);
......
...@@ -100,9 +100,6 @@ typedef unsigned long elf_fpregset_t; ...@@ -100,9 +100,6 @@ typedef unsigned long elf_fpregset_t;
#define ELF_PLATFORM (NULL) #define ELF_PLATFORM (NULL)
#define SET_PERSONALITY(ex) \
set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
#define STACK_RND_MASK (0) #define STACK_RND_MASK (0)
#ifdef CONFIG_METAG_USER_TCM #ifdef CONFIG_METAG_USER_TCM
......
...@@ -40,6 +40,7 @@ endchoice ...@@ -40,6 +40,7 @@ endchoice
config NUMA config NUMA
bool "Non Uniform Memory Access (NUMA) Support" bool "Non Uniform Memory Access (NUMA) Support"
select ARCH_WANT_NUMA_VARIABLE_LOCALITY
help help
Some Meta systems have MMU-mappable on-chip memories with Some Meta systems have MMU-mappable on-chip memories with
lower latencies than main memory. This enables support for lower latencies than main memory. This enables support for
......
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
STEPUP4((t)+16, fn) STEPUP4((t)+16, fn)
_GLOBAL(powerpc_sha_transform) _GLOBAL(powerpc_sha_transform)
PPC_STLU r1,-STACKFRAMESIZE(r1) PPC_STLU r1,-INT_FRAME_SIZE(r1)
SAVE_8GPRS(14, r1) SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1) SAVE_10GPRS(22, r1)
...@@ -175,5 +175,5 @@ _GLOBAL(powerpc_sha_transform) ...@@ -175,5 +175,5 @@ _GLOBAL(powerpc_sha_transform)
REST_8GPRS(14, r1) REST_8GPRS(14, r1)
REST_10GPRS(22, r1) REST_10GPRS(22, r1)
addi r1,r1,STACKFRAMESIZE addi r1,r1,INT_FRAME_SIZE
blr blr
...@@ -52,8 +52,6 @@ ...@@ -52,8 +52,6 @@
#define smp_mb__before_clear_bit() smp_mb() #define smp_mb__before_clear_bit() smp_mb()
#define smp_mb__after_clear_bit() smp_mb() #define smp_mb__after_clear_bit() smp_mb()
#define BITOP_LE_SWIZZLE ((BITS_PER_LONG-1) & ~0x7)
/* Macro for generating the ***_bits() functions */ /* Macro for generating the ***_bits() functions */
#define DEFINE_BITOP(fn, op, prefix, postfix) \ #define DEFINE_BITOP(fn, op, prefix, postfix) \
static __inline__ void fn(unsigned long mask, \ static __inline__ void fn(unsigned long mask, \
......
...@@ -266,7 +266,8 @@ ...@@ -266,7 +266,8 @@
#define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */ #define SPRN_HSRR0 0x13A /* Hypervisor Save/Restore 0 */
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */ #define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
#define SPRN_FSCR 0x099 /* Facility Status & Control Register */ #define SPRN_FSCR 0x099 /* Facility Status & Control Register */
#define FSCR_TAR (1<<8) /* Enable Target Adress Register */ #define FSCR_TAR (1 << (63-55)) /* Enable Target Address Register */
#define FSCR_DSCR (1 << (63-61)) /* Enable Data Stream Control Register */
#define SPRN_TAR 0x32f /* Target Address Register */ #define SPRN_TAR 0x32f /* Target Address Register */
#define SPRN_LPCR 0x13E /* LPAR Control Register */ #define SPRN_LPCR 0x13E /* LPAR Control Register */
#define LPCR_VPM0 (1ul << (63-0)) #define LPCR_VPM0 (1ul << (63-0))
......
...@@ -358,3 +358,4 @@ SYSCALL_SPU(setns) ...@@ -358,3 +358,4 @@ SYSCALL_SPU(setns)
COMPAT_SYS(process_vm_readv) COMPAT_SYS(process_vm_readv)
COMPAT_SYS(process_vm_writev) COMPAT_SYS(process_vm_writev)
SYSCALL(finit_module) SYSCALL(finit_module)
SYSCALL(ni_syscall) /* sys_kcmp */
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <uapi/asm/unistd.h> #include <uapi/asm/unistd.h>
#define __NR_syscalls 354 #define __NR_syscalls 355
#define __NR__exit __NR_exit #define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls #define NR_syscalls __NR_syscalls
......
...@@ -376,6 +376,7 @@ ...@@ -376,6 +376,7 @@
#define __NR_process_vm_readv 351 #define __NR_process_vm_readv 351
#define __NR_process_vm_writev 352 #define __NR_process_vm_writev 352
#define __NR_finit_module 353 #define __NR_finit_module 353
#define __NR_kcmp 354
#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
...@@ -48,6 +48,7 @@ _GLOBAL(__restore_cpu_power7) ...@@ -48,6 +48,7 @@ _GLOBAL(__restore_cpu_power7)
_GLOBAL(__setup_cpu_power8) _GLOBAL(__setup_cpu_power8)
mflr r11 mflr r11
bl __init_FSCR
bl __init_hvmode_206 bl __init_hvmode_206
mtlr r11 mtlr r11
beqlr beqlr
...@@ -56,13 +57,13 @@ _GLOBAL(__setup_cpu_power8) ...@@ -56,13 +57,13 @@ _GLOBAL(__setup_cpu_power8)
mfspr r3,SPRN_LPCR mfspr r3,SPRN_LPCR
oris r3, r3, LPCR_AIL_3@h oris r3, r3, LPCR_AIL_3@h
bl __init_LPCR bl __init_LPCR
bl __init_FSCR
bl __init_TLB bl __init_TLB
mtlr r11 mtlr r11
blr blr
_GLOBAL(__restore_cpu_power8) _GLOBAL(__restore_cpu_power8)
mflr r11 mflr r11
bl __init_FSCR
mfmsr r3 mfmsr r3
rldicl. r0,r3,4,63 rldicl. r0,r3,4,63
beqlr beqlr
...@@ -115,7 +116,7 @@ __init_LPCR: ...@@ -115,7 +116,7 @@ __init_LPCR:
__init_FSCR: __init_FSCR:
mfspr r3,SPRN_FSCR mfspr r3,SPRN_FSCR
ori r3,r3,FSCR_TAR ori r3,r3,FSCR_TAR|FSCR_DSCR
mtspr SPRN_FSCR,r3 mtspr SPRN_FSCR,r3
blr blr
......
...@@ -74,13 +74,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \ ...@@ -74,13 +74,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) \
mflr r10 ; \ mflr r10 ; \
ld r12,PACAKBASE(r13) ; \ ld r12,PACAKBASE(r13) ; \
LOAD_HANDLER(r12, system_call_entry_direct) ; \ LOAD_HANDLER(r12, system_call_entry_direct) ; \
mtlr r12 ; \ mtctr r12 ; \
mfspr r12,SPRN_SRR1 ; \ mfspr r12,SPRN_SRR1 ; \
/* Re-use of r13... No spare regs to do this */ \ /* Re-use of r13... No spare regs to do this */ \
li r13,MSR_RI ; \ li r13,MSR_RI ; \
mtmsrd r13,1 ; \ mtmsrd r13,1 ; \
GET_PACA(r13) ; /* get r13 back */ \ GET_PACA(r13) ; /* get r13 back */ \
blr ; bctr ;
#else #else
/* We can branch directly */ /* We can branch directly */
#define SYSCALL_PSERIES_2_DIRECT \ #define SYSCALL_PSERIES_2_DIRECT \
......
...@@ -749,6 +749,7 @@ static struct file_system_type spufs_type = { ...@@ -749,6 +749,7 @@ static struct file_system_type spufs_type = {
.mount = spufs_mount, .mount = spufs_mount,
.kill_sb = kill_litter_super, .kill_sb = kill_litter_super,
}; };
MODULE_ALIAS_FS("spufs");
static int __init spufs_init(void) static int __init spufs_init(void)
{ {
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include <asm/hvcall.h> #include <asm/hvcall.h>
#include <asm/hvcserver.h> #include <asm/hvcserver.h>
...@@ -188,9 +189,9 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head, ...@@ -188,9 +189,9 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head,
= (unsigned int)last_p_partition_ID; = (unsigned int)last_p_partition_ID;
/* copy the Null-term char too */ /* copy the Null-term char too */
strncpy(&next_partner_info->location_code[0], strlcpy(&next_partner_info->location_code[0],
(char *)&pi_buff[2], (char *)&pi_buff[2],
strlen((char *)&pi_buff[2]) + 1); sizeof(next_partner_info->location_code));
list_add_tail(&(next_partner_info->node), head); list_add_tail(&(next_partner_info->node), head);
next_partner_info = NULL; next_partner_info = NULL;
......
...@@ -456,6 +456,7 @@ static struct file_system_type hypfs_type = { ...@@ -456,6 +456,7 @@ static struct file_system_type hypfs_type = {
.mount = hypfs_mount, .mount = hypfs_mount,
.kill_sb = hypfs_kill_super .kill_sb = hypfs_kill_super
}; };
MODULE_ALIAS_FS("s390_hypfs");
static const struct super_operations hypfs_s_ops = { static const struct super_operations hypfs_s_ops = {
.statfs = simple_statfs, .statfs = simple_statfs,
......
...@@ -288,6 +288,9 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags, ...@@ -288,6 +288,9 @@ long compat_sys_sync_file_range2(int fd, unsigned int flags,
long compat_sys_fallocate(int fd, int mode, long compat_sys_fallocate(int fd, int mode,
u32 offset_lo, u32 offset_hi, u32 offset_lo, u32 offset_hi,
u32 len_lo, u32 len_hi); u32 len_lo, u32 len_hi);
long compat_sys_llseek(unsigned int fd, unsigned int offset_high,
unsigned int offset_low, loff_t __user * result,
unsigned int origin);
/* Assembly trampoline to avoid clobbering r0. */ /* Assembly trampoline to avoid clobbering r0. */
long _compat_sys_rt_sigreturn(void); long _compat_sys_rt_sigreturn(void);
......
...@@ -32,50 +32,65 @@ ...@@ -32,50 +32,65 @@
* adapt the usual convention. * adapt the usual convention.
*/ */
long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high) COMPAT_SYSCALL_DEFINE4(truncate64, char __user *, filename, u32, dummy,
u32, low, u32, high)
{ {
return sys_truncate(filename, ((loff_t)high << 32) | low); return sys_truncate(filename, ((loff_t)high << 32) | low);
} }
long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high) COMPAT_SYSCALL_DEFINE4(ftruncate64, unsigned int, fd, u32, dummy,
u32, low, u32, high)
{ {
return sys_ftruncate(fd, ((loff_t)high << 32) | low); return sys_ftruncate(fd, ((loff_t)high << 32) | low);
} }
long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count, COMPAT_SYSCALL_DEFINE6(pread64, unsigned int, fd, char __user *, ubuf,
u32 dummy, u32 low, u32 high) size_t, count, u32, dummy, u32, low, u32, high)
{ {
return sys_pread64(fd, ubuf, count, ((loff_t)high << 32) | low); return sys_pread64(fd, ubuf, count, ((loff_t)high << 32) | low);
} }
long compat_sys_pwrite64(unsigned int fd, char __user *ubuf, size_t count, COMPAT_SYSCALL_DEFINE6(pwrite64, unsigned int, fd, char __user *, ubuf,
u32 dummy, u32 low, u32 high) size_t, count, u32, dummy, u32, low, u32, high)
{ {
return sys_pwrite64(fd, ubuf, count, ((loff_t)high << 32) | low); return sys_pwrite64(fd, ubuf, count, ((loff_t)high << 32) | low);
} }
long compat_sys_lookup_dcookie(u32 low, u32 high, char __user *buf, size_t len) COMPAT_SYSCALL_DEFINE4(lookup_dcookie, u32, low, u32, high,
char __user *, buf, size_t, len)
{ {
return sys_lookup_dcookie(((loff_t)high << 32) | low, buf, len); return sys_lookup_dcookie(((loff_t)high << 32) | low, buf, len);
} }
long compat_sys_sync_file_range2(int fd, unsigned int flags, COMPAT_SYSCALL_DEFINE6(sync_file_range2, int, fd, unsigned int, flags,
u32 offset_lo, u32 offset_hi, u32, offset_lo, u32, offset_hi,
u32 nbytes_lo, u32 nbytes_hi) u32, nbytes_lo, u32, nbytes_hi)
{ {
return sys_sync_file_range(fd, ((loff_t)offset_hi << 32) | offset_lo, return sys_sync_file_range(fd, ((loff_t)offset_hi << 32) | offset_lo,
((loff_t)nbytes_hi << 32) | nbytes_lo, ((loff_t)nbytes_hi << 32) | nbytes_lo,
flags); flags);
} }
long compat_sys_fallocate(int fd, int mode, COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode,
u32 offset_lo, u32 offset_hi, u32, offset_lo, u32, offset_hi,
u32 len_lo, u32 len_hi) u32, len_lo, u32, len_hi)
{ {
return sys_fallocate(fd, mode, ((loff_t)offset_hi << 32) | offset_lo, return sys_fallocate(fd, mode, ((loff_t)offset_hi << 32) | offset_lo,
((loff_t)len_hi << 32) | len_lo); ((loff_t)len_hi << 32) | len_lo);
} }
/*
* Avoid bug in generic sys_llseek() that specifies offset_high and
* offset_low as "unsigned long", thus making it possible to pass
* a sign-extended high 32 bits in offset_low.
*/
COMPAT_SYSCALL_DEFINE5(llseek, unsigned int, fd, unsigned int, offset_high,
unsigned int, offset_low, loff_t __user *, result,
unsigned int, origin)
{
return sys_llseek(fd, offset_high, offset_low, result, origin);
}
/* Provide the compat syscall number to call mapping. */ /* Provide the compat syscall number to call mapping. */
#undef __SYSCALL #undef __SYSCALL
#define __SYSCALL(nr, call) [nr] = (call), #define __SYSCALL(nr, call) [nr] = (call),
...@@ -83,6 +98,7 @@ long compat_sys_fallocate(int fd, int mode, ...@@ -83,6 +98,7 @@ long compat_sys_fallocate(int fd, int mode,
/* See comments in sys.c */ /* See comments in sys.c */
#define compat_sys_fadvise64_64 sys32_fadvise64_64 #define compat_sys_fadvise64_64 sys32_fadvise64_64
#define compat_sys_readahead sys32_readahead #define compat_sys_readahead sys32_readahead
#define sys_llseek compat_sys_llseek
/* Call the assembly trampolines where necessary. */ /* Call the assembly trampolines where necessary. */
#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn #define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
......
...@@ -14,13 +14,29 @@ ...@@ -14,13 +14,29 @@
* analysis of kexec-tools; if other broken bootloaders initialize a * analysis of kexec-tools; if other broken bootloaders initialize a
* different set of fields we will need to figure out how to disambiguate. * different set of fields we will need to figure out how to disambiguate.
* *
* Note: efi_info is commonly left uninitialized, but that field has a
* private magic, so it is better to leave it unchanged.
*/ */
static void sanitize_boot_params(struct boot_params *boot_params) static void sanitize_boot_params(struct boot_params *boot_params)
{ {
/*
* IMPORTANT NOTE TO BOOTLOADER AUTHORS: do not simply clear
* this field. The purpose of this field is to guarantee
* compliance with the x86 boot spec located in
* Documentation/x86/boot.txt . That spec says that the
* *whole* structure should be cleared, after which only the
* portion defined by struct setup_header (boot_params->hdr)
* should be copied in.
*
* If you're having an issue because the sentinel is set, you
* need to change the whole structure to be cleared, not this
* (or any other) individual field, or you will soon have
* problems again.
*/
if (boot_params->sentinel) { if (boot_params->sentinel) {
/*fields in boot_params are not valid, clear them */ /* fields in boot_params are left uninitialized, clear them */
memset(&boot_params->olpc_ofw_header, 0, memset(&boot_params->olpc_ofw_header, 0,
(char *)&boot_params->alt_mem_k - (char *)&boot_params->efi_info -
(char *)&boot_params->olpc_ofw_header); (char *)&boot_params->olpc_ofw_header);
memset(&boot_params->kbd_status, 0, memset(&boot_params->kbd_status, 0,
(char *)&boot_params->hdr - (char *)&boot_params->hdr -
......
...@@ -171,9 +171,15 @@ static struct resource bss_resource = { ...@@ -171,9 +171,15 @@ static struct resource bss_resource = {
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
/* cpu data as detected by the assembly code in head.S */ /* cpu data as detected by the assembly code in head.S */
struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1}; struct cpuinfo_x86 new_cpu_data __cpuinitdata = {
.wp_works_ok = -1,
.fdiv_bug = -1,
};
/* common cpu data for all cpus */ /* common cpu data for all cpus */
struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1}; struct cpuinfo_x86 boot_cpu_data __read_mostly = {
.wp_works_ok = -1,
.fdiv_bug = -1,
};
EXPORT_SYMBOL(boot_cpu_data); EXPORT_SYMBOL(boot_cpu_data);
unsigned int def_to_bigsmp; unsigned int def_to_bigsmp;
......
...@@ -1365,9 +1365,8 @@ static inline void mwait_play_dead(void) ...@@ -1365,9 +1365,8 @@ static inline void mwait_play_dead(void)
unsigned int eax, ebx, ecx, edx; unsigned int eax, ebx, ecx, edx;
unsigned int highest_cstate = 0; unsigned int highest_cstate = 0;
unsigned int highest_subcstate = 0; unsigned int highest_subcstate = 0;
int i;
void *mwait_ptr; void *mwait_ptr;
struct cpuinfo_x86 *c = __this_cpu_ptr(&cpu_info); int i;
if (!this_cpu_has(X86_FEATURE_MWAIT)) if (!this_cpu_has(X86_FEATURE_MWAIT))
return; return;
......
...@@ -410,9 +410,8 @@ void __init init_mem_mapping(void) ...@@ -410,9 +410,8 @@ void __init init_mem_mapping(void)
/* the ISA range is always mapped regardless of memory holes */ /* the ISA range is always mapped regardless of memory holes */
init_memory_mapping(0, ISA_END_ADDRESS); init_memory_mapping(0, ISA_END_ADDRESS);
/* xen has big range in reserved near end of ram, skip it at first */ /* xen has big range in reserved near end of ram, skip it at first.*/
addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, PMD_SIZE);
PAGE_SIZE);
real_end = addr + PMD_SIZE; real_end = addr + PMD_SIZE;
/* step_size need to be small so pgt_buf from BRK could cover it */ /* step_size need to be small so pgt_buf from BRK could cover it */
......
...@@ -563,6 +563,13 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags) ...@@ -563,6 +563,13 @@ int kernel_map_sync_memtype(u64 base, unsigned long size, unsigned long flags)
if (base > __pa(high_memory-1)) if (base > __pa(high_memory-1))
return 0; return 0;
/*
* some areas in the middle of the kernel identity range
* are not mapped, like the PCI space.
*/
if (!page_is_ram(base >> PAGE_SHIFT))
return 0;
id_sz = (__pa(high_memory-1) <= base + size) ? id_sz = (__pa(high_memory-1) <= base + size) ?
__pa(high_memory) - base : __pa(high_memory) - base :
size; size;
......
...@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type) ...@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
{ {
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
if (type && type->bus && type->find_device) { if (type && type->match && type->find_device) {
down_write(&bus_type_sem); down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list); list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem); up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "bus type %s registered\n", printk(KERN_INFO PREFIX "bus type %s registered\n", type->name);
type->bus->name);
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
...@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type) ...@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem); down_write(&bus_type_sem);
list_del_init(&type->list); list_del_init(&type->list);
up_write(&bus_type_sem); up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", printk(KERN_INFO PREFIX "bus type %s unregistered\n",
type->bus->name); type->name);
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
{ {
struct acpi_bus_type *tmp, *ret = NULL; struct acpi_bus_type *tmp, *ret = NULL;
if (!type)
return NULL;
down_read(&bus_type_sem); down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) { list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->bus == type) { if (tmp->match(dev)) {
ret = tmp; ret = tmp;
break; break;
} }
...@@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) ...@@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
return ret; return ret;
} }
static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
{
struct acpi_bus_type *tmp;
int ret = -ENODEV;
down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) {
ret = 0;
break;
}
}
up_read(&bus_type_sem);
return ret;
}
static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used,
void *addr_p, void **ret_p) void *addr_p, void **ret_p)
{ {
...@@ -261,29 +241,12 @@ static int acpi_unbind_one(struct device *dev) ...@@ -261,29 +241,12 @@ static int acpi_unbind_one(struct device *dev)
static int acpi_platform_notify(struct device *dev) static int acpi_platform_notify(struct device *dev)
{ {
struct acpi_bus_type *type; struct acpi_bus_type *type = acpi_get_bus_type(dev);
acpi_handle handle; acpi_handle handle;
int ret; int ret;
ret = acpi_bind_one(dev, NULL); ret = acpi_bind_one(dev, NULL);
if (ret && (!dev->bus || !dev->parent)) { if (ret && type) {
/* bridge devices genernally haven't bus or parent */
ret = acpi_find_bridge_device(dev, &handle);
if (!ret) {
ret = acpi_bind_one(dev, handle);
if (ret)
goto out;
}
}
type = acpi_get_bus_type(dev->bus);
if (ret) {
if (!type || !type->find_device) {
DBG("No ACPI bus support for %s\n", dev_name(dev));
ret = -EINVAL;
goto out;
}
ret = type->find_device(dev, &handle); ret = type->find_device(dev, &handle);
if (ret) { if (ret) {
DBG("Unable to get handle for %s\n", dev_name(dev)); DBG("Unable to get handle for %s\n", dev_name(dev));
...@@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev) ...@@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev)
{ {
struct acpi_bus_type *type; struct acpi_bus_type *type;
type = acpi_get_bus_type(dev->bus); type = acpi_get_bus_type(dev);
if (type && type->cleanup) if (type && type->cleanup)
type->cleanup(dev); type->cleanup(dev);
......
...@@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) ...@@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id)
} }
exit: exit:
if (buffer.pointer) kfree(buffer.pointer);
kfree(buffer.pointer);
return apic_id; return apic_id;
} }
......
...@@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) ...@@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
return 0; return 0;
#endif #endif
BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); BUG_ON(pr->id >= nr_cpu_ids);
/* /*
* Buggy BIOS check * Buggy BIOS check
......
...@@ -599,7 +599,6 @@ static void acpi_sleep_suspend_setup(void) ...@@ -599,7 +599,6 @@ static void acpi_sleep_suspend_setup(void)
status = acpi_get_sleep_type_data(i, &type_a, &type_b); status = acpi_get_sleep_type_data(i, &type_a, &type_b);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
sleep_states[i] = 1; sleep_states[i] = 1;
pr_cont(" S%d", i);
} }
} }
...@@ -742,7 +741,6 @@ static void acpi_sleep_hibernate_setup(void) ...@@ -742,7 +741,6 @@ static void acpi_sleep_hibernate_setup(void)
hibernation_set_ops(old_suspend_ordering ? hibernation_set_ops(old_suspend_ordering ?
&acpi_hibernation_ops_old : &acpi_hibernation_ops); &acpi_hibernation_ops_old : &acpi_hibernation_ops);
sleep_states[ACPI_STATE_S4] = 1; sleep_states[ACPI_STATE_S4] = 1;
pr_cont(KERN_CONT " S4");
if (nosigcheck) if (nosigcheck)
return; return;
...@@ -788,6 +786,9 @@ int __init acpi_sleep_init(void) ...@@ -788,6 +786,9 @@ int __init acpi_sleep_init(void)
{ {
acpi_status status; acpi_status status;
u8 type_a, type_b; u8 type_a, type_b;
char supported[ACPI_S_STATE_COUNT * 3 + 1];
char *pos = supported;
int i;
if (acpi_disabled) if (acpi_disabled)
return 0; return 0;
...@@ -795,7 +796,6 @@ int __init acpi_sleep_init(void) ...@@ -795,7 +796,6 @@ int __init acpi_sleep_init(void)
acpi_sleep_dmi_check(); acpi_sleep_dmi_check();
sleep_states[ACPI_STATE_S0] = 1; sleep_states[ACPI_STATE_S0] = 1;
pr_info(PREFIX "(supports S0");
acpi_sleep_suspend_setup(); acpi_sleep_suspend_setup();
acpi_sleep_hibernate_setup(); acpi_sleep_hibernate_setup();
...@@ -803,11 +803,17 @@ int __init acpi_sleep_init(void) ...@@ -803,11 +803,17 @@ int __init acpi_sleep_init(void)
status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
sleep_states[ACPI_STATE_S5] = 1; sleep_states[ACPI_STATE_S5] = 1;
pr_cont(" S5");
pm_power_off_prepare = acpi_power_off_prepare; pm_power_off_prepare = acpi_power_off_prepare;
pm_power_off = acpi_power_off; pm_power_off = acpi_power_off;
} }
pr_cont(")\n");
supported[0] = 0;
for (i = 0; i < ACPI_S_STATE_COUNT; i++) {
if (sleep_states[i])
pos += sprintf(pos, " S%d", i);
}
pr_info(PREFIX "(supports%s)\n", supported);
/* /*
* Register the tts_notifier to reboot notifier list so that the _TTS * Register the tts_notifier to reboot notifier list so that the _TTS
* object can also be evaluated when the system enters S5. * object can also be evaluated when the system enters S5.
......
...@@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle) ...@@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
return -ENODEV; return -ENODEV;
} }
static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
{
return -ENODEV;
}
static struct acpi_bus_type ata_acpi_bus = { static struct acpi_bus_type ata_acpi_bus = {
.find_bridge = ata_acpi_find_dummy, .name = "ATA",
.find_device = ata_acpi_find_device, .find_device = ata_acpi_find_device,
}; };
......
...@@ -99,7 +99,6 @@ void device_pm_add(struct device *dev) ...@@ -99,7 +99,6 @@ void device_pm_add(struct device *dev)
dev_warn(dev, "parent %s should not be sleeping\n", dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent)); dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list); list_add_tail(&dev->power.entry, &dpm_list);
dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx); mutex_unlock(&dpm_list_mtx);
} }
...@@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev) ...@@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev)
dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
complete_all(&dev->power.completion); complete_all(&dev->power.completion);
mutex_lock(&dpm_list_mtx); mutex_lock(&dpm_list_mtx);
dev_pm_qos_constraints_destroy(dev);
list_del_init(&dev->power.entry); list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx); mutex_unlock(&dpm_list_mtx);
device_wakeup_disable(dev); device_wakeup_disable(dev);
......
...@@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev) ...@@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev)
{ {
if (!dev->power.early_init) { if (!dev->power.early_init) {
spin_lock_init(&dev->power.lock); spin_lock_init(&dev->power.lock);
dev->power.power_state = PMSG_INVALID; dev->power.qos = NULL;
dev->power.early_init = true; dev->power.early_init = true;
} }
} }
...@@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *); ...@@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *);
static inline void device_pm_sleep_init(struct device *dev) {} static inline void device_pm_sleep_init(struct device *dev) {}
static inline void device_pm_add(struct device *dev) static inline void device_pm_add(struct device *dev) {}
{
dev_pm_qos_constraints_init(dev);
}
static inline void device_pm_remove(struct device *dev) static inline void device_pm_remove(struct device *dev)
{ {
dev_pm_qos_constraints_destroy(dev);
pm_runtime_remove(dev); pm_runtime_remove(dev);
} }
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/err.h>
#include "power.h" #include "power.h"
...@@ -61,7 +62,7 @@ enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask) ...@@ -61,7 +62,7 @@ enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask)
struct pm_qos_flags *pqf; struct pm_qos_flags *pqf;
s32 val; s32 val;
if (!qos) if (IS_ERR_OR_NULL(qos))
return PM_QOS_FLAGS_UNDEFINED; return PM_QOS_FLAGS_UNDEFINED;
pqf = &qos->flags; pqf = &qos->flags;
...@@ -101,7 +102,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags); ...@@ -101,7 +102,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
*/ */
s32 __dev_pm_qos_read_value(struct device *dev) s32 __dev_pm_qos_read_value(struct device *dev)
{ {
return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0; return IS_ERR_OR_NULL(dev->power.qos) ?
0 : pm_qos_read_value(&dev->power.qos->latency);
} }
/** /**
...@@ -198,20 +200,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) ...@@ -198,20 +200,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
return 0; return 0;
} }
/** static void __dev_pm_qos_hide_latency_limit(struct device *dev);
* dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. static void __dev_pm_qos_hide_flags(struct device *dev);
* @dev: target device
*
* Called from the device PM subsystem during device insertion under
* device_pm_lock().
*/
void dev_pm_qos_constraints_init(struct device *dev)
{
mutex_lock(&dev_pm_qos_mtx);
dev->power.qos = NULL;
dev->power.power_state = PMSG_ON;
mutex_unlock(&dev_pm_qos_mtx);
}
/** /**
* dev_pm_qos_constraints_destroy * dev_pm_qos_constraints_destroy
...@@ -226,16 +216,15 @@ void dev_pm_qos_constraints_destroy(struct device *dev) ...@@ -226,16 +216,15 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
struct pm_qos_constraints *c; struct pm_qos_constraints *c;
struct pm_qos_flags *f; struct pm_qos_flags *f;
mutex_lock(&dev_pm_qos_mtx);
/* /*
* If the device's PM QoS resume latency limit or PM QoS flags have been * If the device's PM QoS resume latency limit or PM QoS flags have been
* exposed to user space, they have to be hidden at this point. * exposed to user space, they have to be hidden at this point.
*/ */
dev_pm_qos_hide_latency_limit(dev); __dev_pm_qos_hide_latency_limit(dev);
dev_pm_qos_hide_flags(dev); __dev_pm_qos_hide_flags(dev);
mutex_lock(&dev_pm_qos_mtx);
dev->power.power_state = PMSG_INVALID;
qos = dev->power.qos; qos = dev->power.qos;
if (!qos) if (!qos)
goto out; goto out;
...@@ -257,7 +246,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) ...@@ -257,7 +246,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
} }
spin_lock_irq(&dev->power.lock); spin_lock_irq(&dev->power.lock);
dev->power.qos = NULL; dev->power.qos = ERR_PTR(-ENODEV);
spin_unlock_irq(&dev->power.lock); spin_unlock_irq(&dev->power.lock);
kfree(c->notifiers); kfree(c->notifiers);
...@@ -301,32 +290,19 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, ...@@ -301,32 +290,19 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
"%s() called for already added request\n", __func__)) "%s() called for already added request\n", __func__))
return -EINVAL; return -EINVAL;
req->dev = dev;
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
if (!dev->power.qos) { if (IS_ERR(dev->power.qos))
if (dev->power.power_state.event == PM_EVENT_INVALID) { ret = -ENODEV;
/* The device has been removed from the system. */ else if (!dev->power.qos)
req->dev = NULL; ret = dev_pm_qos_constraints_allocate(dev);
ret = -ENODEV;
goto out;
} else {
/*
* Allocate the constraints data on the first call to
* add_request, i.e. only if the data is not already
* allocated and if the device has not been removed.
*/
ret = dev_pm_qos_constraints_allocate(dev);
}
}
if (!ret) { if (!ret) {
req->dev = dev;
req->type = type; req->type = type;
ret = apply_constraint(req, PM_QOS_ADD_REQ, value); ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
} }
out:
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
return ret; return ret;
...@@ -344,7 +320,14 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, ...@@ -344,7 +320,14 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
s32 curr_value; s32 curr_value;
int ret = 0; int ret = 0;
if (!req->dev->power.qos) if (!req) /*guard against callers passing in null */
return -EINVAL;
if (WARN(!dev_pm_qos_request_active(req),
"%s() called for unknown object\n", __func__))
return -EINVAL;
if (IS_ERR_OR_NULL(req->dev->power.qos))
return -ENODEV; return -ENODEV;
switch(req->type) { switch(req->type) {
...@@ -386,6 +369,17 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) ...@@ -386,6 +369,17 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
{ {
int ret; int ret;
mutex_lock(&dev_pm_qos_mtx);
ret = __dev_pm_qos_update_request(req, new_value);
mutex_unlock(&dev_pm_qos_mtx);
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
{
int ret;
if (!req) /*guard against callers passing in null */ if (!req) /*guard against callers passing in null */
return -EINVAL; return -EINVAL;
...@@ -393,13 +387,13 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) ...@@ -393,13 +387,13 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value)
"%s() called for unknown object\n", __func__)) "%s() called for unknown object\n", __func__))
return -EINVAL; return -EINVAL;
mutex_lock(&dev_pm_qos_mtx); if (IS_ERR_OR_NULL(req->dev->power.qos))
ret = __dev_pm_qos_update_request(req, new_value); return -ENODEV;
mutex_unlock(&dev_pm_qos_mtx);
ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
/** /**
* dev_pm_qos_remove_request - modifies an existing qos request * dev_pm_qos_remove_request - modifies an existing qos request
...@@ -418,26 +412,10 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); ...@@ -418,26 +412,10 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request);
*/ */
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
{ {
int ret = 0; int ret;
if (!req) /*guard against callers passing in null */
return -EINVAL;
if (WARN(!dev_pm_qos_request_active(req),
"%s() called for unknown object\n", __func__))
return -EINVAL;
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
ret = __dev_pm_qos_remove_request(req);
if (req->dev->power.qos) {
ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
} else {
/* Return if the device has been removed */
ret = -ENODEV;
}
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
return ret; return ret;
} }
...@@ -462,9 +440,10 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) ...@@ -462,9 +440,10 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
if (!dev->power.qos) if (IS_ERR(dev->power.qos))
ret = dev->power.power_state.event != PM_EVENT_INVALID ? ret = -ENODEV;
dev_pm_qos_constraints_allocate(dev) : -ENODEV; else if (!dev->power.qos)
ret = dev_pm_qos_constraints_allocate(dev);
if (!ret) if (!ret)
ret = blocking_notifier_chain_register( ret = blocking_notifier_chain_register(
...@@ -493,7 +472,7 @@ int dev_pm_qos_remove_notifier(struct device *dev, ...@@ -493,7 +472,7 @@ int dev_pm_qos_remove_notifier(struct device *dev,
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
/* Silently return if the constraints object is not present. */ /* Silently return if the constraints object is not present. */
if (dev->power.qos) if (!IS_ERR_OR_NULL(dev->power.qos))
retval = blocking_notifier_chain_unregister( retval = blocking_notifier_chain_unregister(
dev->power.qos->latency.notifiers, dev->power.qos->latency.notifiers,
notifier); notifier);
...@@ -563,16 +542,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); ...@@ -563,16 +542,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
static void __dev_pm_qos_drop_user_request(struct device *dev, static void __dev_pm_qos_drop_user_request(struct device *dev,
enum dev_pm_qos_req_type type) enum dev_pm_qos_req_type type)
{ {
struct dev_pm_qos_request *req = NULL;
switch(type) { switch(type) {
case DEV_PM_QOS_LATENCY: case DEV_PM_QOS_LATENCY:
dev_pm_qos_remove_request(dev->power.qos->latency_req); req = dev->power.qos->latency_req;
dev->power.qos->latency_req = NULL; dev->power.qos->latency_req = NULL;
break; break;
case DEV_PM_QOS_FLAGS: case DEV_PM_QOS_FLAGS:
dev_pm_qos_remove_request(dev->power.qos->flags_req); req = dev->power.qos->flags_req;
dev->power.qos->flags_req = NULL; dev->power.qos->flags_req = NULL;
break; break;
} }
__dev_pm_qos_remove_request(req);
kfree(req);
} }
/** /**
...@@ -588,36 +571,57 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) ...@@ -588,36 +571,57 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
if (!device_is_registered(dev) || value < 0) if (!device_is_registered(dev) || value < 0)
return -EINVAL; return -EINVAL;
if (dev->power.qos && dev->power.qos->latency_req)
return -EEXIST;
req = kzalloc(sizeof(*req), GFP_KERNEL); req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req) if (!req)
return -ENOMEM; return -ENOMEM;
ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value);
if (ret < 0) if (ret < 0) {
kfree(req);
return ret; return ret;
}
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos))
ret = -ENODEV;
else if (dev->power.qos->latency_req)
ret = -EEXIST;
if (ret < 0) {
__dev_pm_qos_remove_request(req);
kfree(req);
goto out;
}
dev->power.qos->latency_req = req; dev->power.qos->latency_req = req;
ret = pm_qos_sysfs_add_latency(dev); ret = pm_qos_sysfs_add_latency(dev);
if (ret) if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
out:
mutex_unlock(&dev_pm_qos_mtx);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
static void __dev_pm_qos_hide_latency_limit(struct device *dev)
{
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
pm_qos_sysfs_remove_latency(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
}
}
/** /**
* dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space.
* @dev: Device whose PM QoS latency limit is to be hidden from user space. * @dev: Device whose PM QoS latency limit is to be hidden from user space.
*/ */
void dev_pm_qos_hide_latency_limit(struct device *dev) void dev_pm_qos_hide_latency_limit(struct device *dev)
{ {
if (dev->power.qos && dev->power.qos->latency_req) { mutex_lock(&dev_pm_qos_mtx);
pm_qos_sysfs_remove_latency(dev); __dev_pm_qos_hide_latency_limit(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); mutex_unlock(&dev_pm_qos_mtx);
}
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
...@@ -634,41 +638,61 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) ...@@ -634,41 +638,61 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
if (!device_is_registered(dev)) if (!device_is_registered(dev))
return -EINVAL; return -EINVAL;
if (dev->power.qos && dev->power.qos->flags_req)
return -EEXIST;
req = kzalloc(sizeof(*req), GFP_KERNEL); req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req) if (!req)
return -ENOMEM; return -ENOMEM;
pm_runtime_get_sync(dev);
ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val);
if (ret < 0) if (ret < 0) {
goto fail; kfree(req);
return ret;
}
pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos))
ret = -ENODEV;
else if (dev->power.qos->flags_req)
ret = -EEXIST;
if (ret < 0) {
__dev_pm_qos_remove_request(req);
kfree(req);
goto out;
}
dev->power.qos->flags_req = req; dev->power.qos->flags_req = req;
ret = pm_qos_sysfs_add_flags(dev); ret = pm_qos_sysfs_add_flags(dev);
if (ret) if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
fail: out:
mutex_unlock(&dev_pm_qos_mtx);
pm_runtime_put(dev); pm_runtime_put(dev);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
static void __dev_pm_qos_hide_flags(struct device *dev)
{
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
pm_qos_sysfs_remove_flags(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
}
}
/** /**
* dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space.
* @dev: Device whose PM QoS flags are to be hidden from user space. * @dev: Device whose PM QoS flags are to be hidden from user space.
*/ */
void dev_pm_qos_hide_flags(struct device *dev) void dev_pm_qos_hide_flags(struct device *dev)
{ {
if (dev->power.qos && dev->power.qos->flags_req) { pm_runtime_get_sync(dev);
pm_qos_sysfs_remove_flags(dev); mutex_lock(&dev_pm_qos_mtx);
pm_runtime_get_sync(dev); __dev_pm_qos_hide_flags(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); mutex_unlock(&dev_pm_qos_mtx);
pm_runtime_put(dev); pm_runtime_put(dev);
}
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
...@@ -683,12 +707,14 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) ...@@ -683,12 +707,14 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
s32 value; s32 value;
int ret; int ret;
if (!dev->power.qos || !dev->power.qos->flags_req)
return -EINVAL;
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) {
ret = -EINVAL;
goto out;
}
value = dev_pm_qos_requested_flags(dev); value = dev_pm_qos_requested_flags(dev);
if (set) if (set)
value |= mask; value |= mask;
...@@ -697,9 +723,12 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) ...@@ -697,9 +723,12 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set)
ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value);
out:
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
pm_runtime_put(dev); pm_runtime_put(dev);
return ret; return ret;
} }
#else /* !CONFIG_PM_RUNTIME */
static void __dev_pm_qos_hide_latency_limit(struct device *dev) {}
static void __dev_pm_qos_hide_flags(struct device *dev) {}
#endif /* CONFIG_PM_RUNTIME */ #endif /* CONFIG_PM_RUNTIME */
...@@ -708,6 +708,7 @@ void rpm_sysfs_remove(struct device *dev) ...@@ -708,6 +708,7 @@ void rpm_sysfs_remove(struct device *dev)
void dpm_sysfs_remove(struct device *dev) void dpm_sysfs_remove(struct device *dev)
{ {
dev_pm_qos_constraints_destroy(dev);
rpm_sysfs_remove(dev); rpm_sysfs_remove(dev);
sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
sysfs_remove_group(&dev->kobj, &pm_attr_group); sysfs_remove_group(&dev->kobj, &pm_attr_group);
......
...@@ -184,6 +184,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) ...@@ -184,6 +184,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d)
if (ret < 0) { if (ret < 0) {
dev_err(map->dev, "IRQ thread failed to resume: %d\n", dev_err(map->dev, "IRQ thread failed to resume: %d\n",
ret); ret);
pm_runtime_put(map->dev);
return IRQ_NONE; return IRQ_NONE;
} }
} }
......
...@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) ...@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
return; return;
} }
spin_lock_init(&pc_host->cfgspace_lock);
pc->host_controller = pc_host; pc->host_controller = pc_host;
pc_host->pci_controller.io_resource = &pc_host->io_resource; pc_host->pci_controller.io_resource = &pc_host->io_resource;
pc_host->pci_controller.mem_resource = &pc_host->mem_resource; pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -52,8 +53,12 @@ static struct hwrng *current_rng; ...@@ -52,8 +53,12 @@ static struct hwrng *current_rng;
static LIST_HEAD(rng_list); static LIST_HEAD(rng_list);
static DEFINE_MUTEX(rng_mutex); static DEFINE_MUTEX(rng_mutex);
static int data_avail; static int data_avail;
static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] static u8 *rng_buffer;
__cacheline_aligned;
static size_t rng_buffer_size(void)
{
return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
}
static inline int hwrng_init(struct hwrng *rng) static inline int hwrng_init(struct hwrng *rng)
{ {
...@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, ...@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
if (!data_avail) { if (!data_avail) {
bytes_read = rng_get_data(current_rng, rng_buffer, bytes_read = rng_get_data(current_rng, rng_buffer,
sizeof(rng_buffer), rng_buffer_size(),
!(filp->f_flags & O_NONBLOCK)); !(filp->f_flags & O_NONBLOCK));
if (bytes_read < 0) { if (bytes_read < 0) {
err = bytes_read; err = bytes_read;
...@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) ...@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng)
mutex_lock(&rng_mutex); mutex_lock(&rng_mutex);
/* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
err = -ENOMEM;
if (!rng_buffer) {
rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
if (!rng_buffer)
goto out_unlock;
}
/* Must not register two RNGs with the same name. */ /* Must not register two RNGs with the same name. */
err = -EEXIST; err = -EEXIST;
list_for_each_entry(tmp, &rng_list, list) { list_for_each_entry(tmp, &rng_list, list) {
......
...@@ -852,6 +852,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, ...@@ -852,6 +852,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
int reserved) int reserved)
{ {
unsigned long flags; unsigned long flags;
int wakeup_write = 0;
/* Hold lock while accounting */ /* Hold lock while accounting */
spin_lock_irqsave(&r->lock, flags); spin_lock_irqsave(&r->lock, flags);
...@@ -873,10 +874,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, ...@@ -873,10 +874,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
else else
r->entropy_count = reserved; r->entropy_count = reserved;
if (r->entropy_count < random_write_wakeup_thresh) { if (r->entropy_count < random_write_wakeup_thresh)
wake_up_interruptible(&random_write_wait); wakeup_write = 1;
kill_fasync(&fasync, SIGIO, POLL_OUT);
}
} }
DEBUG_ENT("debiting %zu entropy credits from %s%s\n", DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
...@@ -884,6 +883,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, ...@@ -884,6 +883,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
spin_unlock_irqrestore(&r->lock, flags); spin_unlock_irqrestore(&r->lock, flags);
if (wakeup_write) {
wake_up_interruptible(&random_write_wait);
kill_fasync(&fasync, SIGIO, POLL_OUT);
}
return nbytes; return nbytes;
} }
......
...@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, ...@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
(task_active_pid_ns(current) != &init_pid_ns)) (task_active_pid_ns(current) != &init_pid_ns))
return; return;
/* Can only change if privileged. */
if (!capable(CAP_NET_ADMIN)) {
err = EPERM;
goto out;
}
mc_op = (enum proc_cn_mcast_op *)msg->data; mc_op = (enum proc_cn_mcast_op *)msg->data;
switch (*mc_op) { switch (*mc_op) {
case PROC_CN_MCAST_LISTEN: case PROC_CN_MCAST_LISTEN:
...@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, ...@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg,
err = EINVAL; err = EINVAL;
break; break;
} }
out:
cn_proc_ack(err, msg->seq, msg->ack); cn_proc_ack(err, msg->seq, msg->ack);
} }
......
...@@ -64,7 +64,7 @@ static void *get_cpu_dbs_info_s(int cpu) \ ...@@ -64,7 +64,7 @@ static void *get_cpu_dbs_info_s(int cpu) \
* dbs: used as a shortform for demand based switching It helps to keep variable * dbs: used as a shortform for demand based switching It helps to keep variable
* names smaller, simpler * names smaller, simpler
* cdbs: common dbs * cdbs: common dbs
* on_*: On-demand governor * od_*: On-demand governor
* cs_*: Conservative governor * cs_*: Conservative governor
*/ */
......
...@@ -28,13 +28,7 @@ ...@@ -28,13 +28,7 @@
static int hb_voltage_change(unsigned int freq) static int hb_voltage_change(unsigned int freq)
{ {
int i; u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 1000000};
u32 msg[HB_CPUFREQ_IPC_LEN];
msg[0] = HB_CPUFREQ_CHANGE_NOTE;
msg[1] = freq / 1000000;
for (i = 2; i < HB_CPUFREQ_IPC_LEN; i++)
msg[i] = 0;
return pl320_ipc_transmit(msg); return pl320_ipc_transmit(msg);
} }
......
...@@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) ...@@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
cpu = all_cpu_data[policy->cpu]; cpu = all_cpu_data[policy->cpu];
if (!policy->cpuinfo.max_freq)
return -ENODEV;
intel_pstate_get_min_max(cpu, &min, &max); intel_pstate_get_min_max(cpu, &min, &max);
limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq;
...@@ -747,37 +750,11 @@ static struct cpufreq_driver intel_pstate_driver = { ...@@ -747,37 +750,11 @@ static struct cpufreq_driver intel_pstate_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static void intel_pstate_exit(void)
{
int cpu;
sysfs_remove_group(intel_pstate_kobject,
&intel_pstate_attr_group);
debugfs_remove_recursive(debugfs_parent);
cpufreq_unregister_driver(&intel_pstate_driver);
if (!all_cpu_data)
return;
get_online_cpus();
for_each_online_cpu(cpu) {
if (all_cpu_data[cpu]) {
del_timer_sync(&all_cpu_data[cpu]->timer);
kfree(all_cpu_data[cpu]);
}
}
put_online_cpus();
vfree(all_cpu_data);
}
module_exit(intel_pstate_exit);
static int __initdata no_load; static int __initdata no_load;
static int __init intel_pstate_init(void) static int __init intel_pstate_init(void)
{ {
int rc = 0; int cpu, rc = 0;
const struct x86_cpu_id *id; const struct x86_cpu_id *id;
if (no_load) if (no_load)
...@@ -802,7 +779,16 @@ static int __init intel_pstate_init(void) ...@@ -802,7 +779,16 @@ static int __init intel_pstate_init(void)
intel_pstate_sysfs_expose_params(); intel_pstate_sysfs_expose_params();
return rc; return rc;
out: out:
intel_pstate_exit(); get_online_cpus();
for_each_online_cpu(cpu) {
if (all_cpu_data[cpu]) {
del_timer_sync(&all_cpu_data[cpu]->timer);
kfree(all_cpu_data[cpu]);
}
}
put_online_cpus();
vfree(all_cpu_data);
return -ENODEV; return -ENODEV;
} }
device_initcall(intel_pstate_init); device_initcall(intel_pstate_init);
......
...@@ -442,7 +442,6 @@ static int __init dmi_present(const char __iomem *p) ...@@ -442,7 +442,6 @@ static int __init dmi_present(const char __iomem *p)
static int __init smbios_present(const char __iomem *p) static int __init smbios_present(const char __iomem *p)
{ {
u8 buf[32]; u8 buf[32];
int offset = 0;
memcpy_fromio(buf, p, 32); memcpy_fromio(buf, p, 32);
if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) {
...@@ -461,9 +460,9 @@ static int __init smbios_present(const char __iomem *p) ...@@ -461,9 +460,9 @@ static int __init smbios_present(const char __iomem *p)
dmi_ver = 0x0206; dmi_ver = 0x0206;
break; break;
} }
offset = 16; return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16);
} }
return dmi_present(buf + offset); return 1;
} }
void __init dmi_scan_machine(void) void __init dmi_scan_machine(void)
......
...@@ -426,6 +426,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var) ...@@ -426,6 +426,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var)
return status; return status;
} }
static efi_status_t
check_var_size_locked(struct efivars *efivars, u32 attributes,
unsigned long size)
{
u64 storage_size, remaining_size, max_size;
efi_status_t status;
const struct efivar_operations *fops = efivars->ops;
if (!efivars->ops->query_variable_info)
return EFI_UNSUPPORTED;
status = fops->query_variable_info(attributes, &storage_size,
&remaining_size, &max_size);
if (status != EFI_SUCCESS)
return status;
if (!storage_size || size > remaining_size || size > max_size ||
(remaining_size - size) < (storage_size / 2))
return EFI_OUT_OF_RESOURCES;
return status;
}
static efi_status_t
check_var_size(struct efivars *efivars, u32 attributes, unsigned long size)
{
efi_status_t status;
unsigned long flags;
spin_lock_irqsave(&efivars->lock, flags);
status = check_var_size_locked(efivars, attributes, size);
spin_unlock_irqrestore(&efivars->lock, flags);
return status;
}
static ssize_t static ssize_t
efivar_guid_read(struct efivar_entry *entry, char *buf) efivar_guid_read(struct efivar_entry *entry, char *buf)
{ {
...@@ -547,11 +585,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) ...@@ -547,11 +585,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
} }
spin_lock_irq(&efivars->lock); spin_lock_irq(&efivars->lock);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid, status = check_var_size_locked(efivars, new_var->Attributes,
new_var->Attributes, new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
new_var->DataSize,
new_var->Data); if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
new_var->Attributes,
new_var->DataSize,
new_var->Data);
spin_unlock_irq(&efivars->lock); spin_unlock_irq(&efivars->lock);
...@@ -702,8 +745,7 @@ static ssize_t efivarfs_file_write(struct file *file, ...@@ -702,8 +745,7 @@ static ssize_t efivarfs_file_write(struct file *file,
u32 attributes; u32 attributes;
struct inode *inode = file->f_mapping->host; struct inode *inode = file->f_mapping->host;
unsigned long datasize = count - sizeof(attributes); unsigned long datasize = count - sizeof(attributes);
unsigned long newdatasize; unsigned long newdatasize, varsize;
u64 storage_size, remaining_size, max_size;
ssize_t bytes = 0; ssize_t bytes = 0;
if (count < sizeof(attributes)) if (count < sizeof(attributes))
...@@ -722,28 +764,18 @@ static ssize_t efivarfs_file_write(struct file *file, ...@@ -722,28 +764,18 @@ static ssize_t efivarfs_file_write(struct file *file,
* amounts of memory. Pick a default size of 64K if * amounts of memory. Pick a default size of 64K if
* QueryVariableInfo() isn't supported by the firmware. * QueryVariableInfo() isn't supported by the firmware.
*/ */
spin_lock_irq(&efivars->lock);
if (!efivars->ops->query_variable_info)
status = EFI_UNSUPPORTED;
else {
const struct efivar_operations *fops = efivars->ops;
status = fops->query_variable_info(attributes, &storage_size,
&remaining_size, &max_size);
}
spin_unlock_irq(&efivars->lock); varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
status = check_var_size(efivars, attributes, varsize);
if (status != EFI_SUCCESS) { if (status != EFI_SUCCESS) {
if (status != EFI_UNSUPPORTED) if (status != EFI_UNSUPPORTED)
return efi_status_to_err(status); return efi_status_to_err(status);
remaining_size = 65536; if (datasize > 65536)
return -ENOSPC;
} }
if (datasize > remaining_size)
return -ENOSPC;
data = kmalloc(datasize, GFP_KERNEL); data = kmalloc(datasize, GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
...@@ -765,6 +797,19 @@ static ssize_t efivarfs_file_write(struct file *file, ...@@ -765,6 +797,19 @@ static ssize_t efivarfs_file_write(struct file *file,
*/ */
spin_lock_irq(&efivars->lock); spin_lock_irq(&efivars->lock);
/*
* Ensure that the available space hasn't shrunk below the safe level
*/
status = check_var_size_locked(efivars, attributes, varsize);
if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) {
spin_unlock_irq(&efivars->lock);
kfree(data);
return efi_status_to_err(status);
}
status = efivars->ops->set_variable(var->var.VariableName, status = efivars->ops->set_variable(var->var.VariableName,
&var->var.VendorGuid, &var->var.VendorGuid,
attributes, datasize, attributes, datasize,
...@@ -929,8 +974,8 @@ static bool efivarfs_valid_name(const char *str, int len) ...@@ -929,8 +974,8 @@ static bool efivarfs_valid_name(const char *str, int len)
if (len < GUID_LEN + 2) if (len < GUID_LEN + 2)
return false; return false;
/* GUID should be right after the first '-' */ /* GUID must be preceded by a '-' */
if (s - 1 != strchr(str, '-')) if (*(s - 1) != '-')
return false; return false;
/* /*
...@@ -1118,15 +1163,22 @@ static struct dentry_operations efivarfs_d_ops = { ...@@ -1118,15 +1163,22 @@ static struct dentry_operations efivarfs_d_ops = {
static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
{ {
struct dentry *d;
struct qstr q; struct qstr q;
int err;
q.name = name; q.name = name;
q.len = strlen(name); q.len = strlen(name);
if (efivarfs_d_hash(NULL, NULL, &q)) err = efivarfs_d_hash(NULL, NULL, &q);
return NULL; if (err)
return ERR_PTR(err);
d = d_alloc(parent, &q);
if (d)
return d;
return d_alloc(parent, &q); return ERR_PTR(-ENOMEM);
} }
static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
...@@ -1136,6 +1188,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1136,6 +1188,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
struct efivar_entry *entry, *n; struct efivar_entry *entry, *n;
struct efivars *efivars = &__efivars; struct efivars *efivars = &__efivars;
char *name; char *name;
int err = -ENOMEM;
efivarfs_sb = sb; efivarfs_sb = sb;
...@@ -1186,8 +1239,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1186,8 +1239,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
goto fail_name; goto fail_name;
dentry = efivarfs_alloc_dentry(root, name); dentry = efivarfs_alloc_dentry(root, name);
if (!dentry) if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
goto fail_inode; goto fail_inode;
}
/* copied by the above to local storage in the dentry. */ /* copied by the above to local storage in the dentry. */
kfree(name); kfree(name);
...@@ -1214,7 +1269,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1214,7 +1269,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
fail_name: fail_name:
kfree(name); kfree(name);
fail: fail:
return -ENOMEM; return err;
} }
static struct dentry *efivarfs_mount(struct file_system_type *fs_type, static struct dentry *efivarfs_mount(struct file_system_type *fs_type,
...@@ -1234,6 +1289,7 @@ static struct file_system_type efivarfs_type = { ...@@ -1234,6 +1289,7 @@ static struct file_system_type efivarfs_type = {
.mount = efivarfs_mount, .mount = efivarfs_mount,
.kill_sb = efivarfs_kill_sb, .kill_sb = efivarfs_kill_sb,
}; };
MODULE_ALIAS_FS("efivarfs");
/* /*
* Handle negative dentry. * Handle negative dentry.
...@@ -1345,7 +1401,6 @@ static int efi_pstore_write(enum pstore_type_id type, ...@@ -1345,7 +1401,6 @@ static int efi_pstore_write(enum pstore_type_id type,
efi_guid_t vendor = LINUX_EFI_CRASH_GUID; efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
struct efivars *efivars = psi->data; struct efivars *efivars = psi->data;
int i, ret = 0; int i, ret = 0;
u64 storage_space, remaining_space, max_variable_size;
efi_status_t status = EFI_NOT_FOUND; efi_status_t status = EFI_NOT_FOUND;
unsigned long flags; unsigned long flags;
...@@ -1365,11 +1420,11 @@ static int efi_pstore_write(enum pstore_type_id type, ...@@ -1365,11 +1420,11 @@ static int efi_pstore_write(enum pstore_type_id type,
* size: a size of logging data * size: a size of logging data
* DUMP_NAME_LEN * 2: a maximum size of variable name * DUMP_NAME_LEN * 2: a maximum size of variable name
*/ */
status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES,
&storage_space, status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES,
&remaining_space, size + DUMP_NAME_LEN * 2);
&max_variable_size);
if (status || remaining_space < size + DUMP_NAME_LEN * 2) { if (status) {
spin_unlock_irqrestore(&efivars->lock, flags); spin_unlock_irqrestore(&efivars->lock, flags);
*id = part; *id = part;
return -ENOSPC; return -ENOSPC;
...@@ -1544,6 +1599,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, ...@@ -1544,6 +1599,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
return -EINVAL; return -EINVAL;
} }
status = check_var_size_locked(efivars, new_var->Attributes,
new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
if (status && status != EFI_UNSUPPORTED) {
spin_unlock_irq(&efivars->lock);
return efi_status_to_err(status);
}
/* now *really* create the variable via EFI */ /* now *really* create the variable via EFI */
status = efivars->ops->set_variable(new_var->VariableName, status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid, &new_var->VendorGuid,
......
...@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr) ...@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr)
return data & (1 << bit) ? 1 : 0; return data & (1 << bit) ? 1 : 0;
} }
static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
{ {
return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; return ichx_priv.use_gpio & (1 << (nr / 32));
} }
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
......
...@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); ...@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label);
static void gpiod_free(struct gpio_desc *desc); static void gpiod_free(struct gpio_desc *desc);
static int gpiod_direction_input(struct gpio_desc *desc); static int gpiod_direction_input(struct gpio_desc *desc);
static int gpiod_direction_output(struct gpio_desc *desc, int value); static int gpiod_direction_output(struct gpio_desc *desc, int value);
static int gpiod_get_direction(const struct gpio_desc *desc);
static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
static int gpiod_get_value_cansleep(struct gpio_desc *desc); static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value);
static int gpiod_get_value(struct gpio_desc *desc); static int gpiod_get_value(const struct gpio_desc *desc);
static void gpiod_set_value(struct gpio_desc *desc, int value); static void gpiod_set_value(struct gpio_desc *desc, int value);
static int gpiod_cansleep(struct gpio_desc *desc); static int gpiod_cansleep(const struct gpio_desc *desc);
static int gpiod_to_irq(struct gpio_desc *desc); static int gpiod_to_irq(const struct gpio_desc *desc);
static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); static int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
static int gpiod_export_link(struct device *dev, const char *name, static int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc); struct gpio_desc *desc);
...@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc) ...@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc)
return 0; return 0;
} }
/* caller holds gpio_lock *OR* gpio is marked as requested */ static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc)
static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc)
{ {
return desc->chip; return desc ? desc->chip : NULL;
} }
/* caller holds gpio_lock *OR* gpio is marked as requested */
struct gpio_chip *gpio_to_chip(unsigned gpio) struct gpio_chip *gpio_to_chip(unsigned gpio)
{ {
return gpiod_to_chip(gpio_to_desc(gpio)); return gpiod_to_chip(gpio_to_desc(gpio));
...@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio) ...@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio)
} }
/* caller ensures gpio is valid and requested, chip->get_direction may sleep */ /* caller ensures gpio is valid and requested, chip->get_direction may sleep */
static int gpiod_get_direction(struct gpio_desc *desc) static int gpiod_get_direction(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
unsigned offset; unsigned offset;
...@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc) ...@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc)
if (status > 0) { if (status > 0) {
/* GPIOF_DIR_IN, or other positive */ /* GPIOF_DIR_IN, or other positive */
status = 1; status = 1;
clear_bit(FLAG_IS_OUT, &desc->flags); /* FLAG_IS_OUT is just a cache of the result of get_direction(),
* so it does not affect constness per se */
clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
} }
if (status == 0) { if (status == 0) {
/* GPIOF_DIR_OUT */ /* GPIOF_DIR_OUT */
set_bit(FLAG_IS_OUT, &desc->flags); set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags);
} }
return status; return status;
} }
...@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock); ...@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock);
static ssize_t gpio_direction_show(struct device *dev, static ssize_t gpio_direction_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct gpio_desc *desc = dev_get_drvdata(dev); const struct gpio_desc *desc = dev_get_drvdata(dev);
ssize_t status; ssize_t status;
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class, ...@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class,
goto done; goto done;
desc = gpio_to_desc(gpio); desc = gpio_to_desc(gpio);
/* reject invalid GPIOs */
if (!desc) {
pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
/* No extra locking here; FLAG_SYSFS just signifies that the /* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so * request and export were done by on behalf of userspace, so
...@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class, ...@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class,
if (status < 0) if (status < 0)
goto done; goto done;
status = -EINVAL;
desc = gpio_to_desc(gpio); desc = gpio_to_desc(gpio);
/* reject bogus commands (gpio_unexport ignores them) */ /* reject bogus commands (gpio_unexport ignores them) */
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
return -EINVAL;
}
status = -EINVAL;
/* No extra locking here; FLAG_SYSFS just signifies that the /* No extra locking here; FLAG_SYSFS just signifies that the
* request and export were done by on behalf of userspace, so * request and export were done by on behalf of userspace, so
...@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name, ...@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name,
{ {
int status = -EINVAL; int status = -EINVAL;
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name, ...@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name,
mutex_unlock(&sysfs_lock); mutex_unlock(&sysfs_lock);
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) ...@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
struct device *dev = NULL; struct device *dev = NULL;
int status = -EINVAL; int status = -EINVAL;
if (!desc) if (!desc) {
goto done; pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) ...@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value)
unlock: unlock:
mutex_unlock(&sysfs_lock); mutex_unlock(&sysfs_lock);
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc) ...@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc)
struct device *dev = NULL; struct device *dev = NULL;
if (!desc) { if (!desc) {
status = -EINVAL; pr_warn("%s: invalid GPIO\n", __func__);
goto done; return;
} }
mutex_lock(&sysfs_lock); mutex_lock(&sysfs_lock);
...@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc) ...@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc)
device_unregister(dev); device_unregister(dev);
put_device(dev); put_device(dev);
} }
done:
if (status) if (status)
pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc),
status); status);
...@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) ...@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
int status = -EPROBE_DEFER; int status = -EPROBE_DEFER;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
if (!desc) { if (!desc) {
status = -EINVAL; pr_warn("%s: invalid GPIO\n", __func__);
goto done; return -EINVAL;
} }
spin_lock_irqsave(&gpio_lock, flags);
chip = desc->chip; chip = desc->chip;
if (chip == NULL) if (chip == NULL)
goto done; goto done;
...@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) ...@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label)
done: done:
if (status) if (status)
pr_debug("_gpio_request: gpio-%d (%s) status %d\n", pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
desc ? desc_to_gpio(desc) : -1, desc_to_gpio(desc), label ? : "?", status);
label ? : "?", status);
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
return status; return status;
} }
...@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc) ...@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->get || !chip->direction_input) if (!chip || !chip->get || !chip->direction_input)
goto fail; goto fail;
...@@ -1655,13 +1670,9 @@ static int gpiod_direction_input(struct gpio_desc *desc) ...@@ -1655,13 +1670,9 @@ static int gpiod_direction_input(struct gpio_desc *desc)
return status; return status;
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
/* Open drain pin should not be driven to 1 */ /* Open drain pin should not be driven to 1 */
if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags))
return gpiod_direction_input(desc); return gpiod_direction_input(desc);
...@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->set || !chip->direction_output) if (!chip || !chip->set || !chip->direction_output)
goto fail; goto fail;
...@@ -1725,13 +1739,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) ...@@ -1725,13 +1739,9 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value)
return status; return status;
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) ...@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
int status = -EINVAL; int status = -EINVAL;
int offset; int offset;
if (!desc) {
pr_warn("%s: invalid GPIO\n", __func__);
return -EINVAL;
}
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
if (!desc)
goto fail;
chip = desc->chip; chip = desc->chip;
if (!chip || !chip->set || !chip->set_debounce) if (!chip || !chip->set || !chip->set_debounce)
goto fail; goto fail;
...@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) ...@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
fail: fail:
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
if (status) { if (status)
int gpio = -1; pr_debug("%s: gpio-%d status %d\n", __func__,
if (desc) desc_to_gpio(desc), status);
gpio = desc_to_gpio(desc);
pr_debug("%s: gpio-%d status %d\n",
__func__, gpio, status);
}
return status; return status;
} }
...@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); ...@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce);
* It returns the zero or nonzero value provided by the associated * It returns the zero or nonzero value provided by the associated
* gpio_chip.get() method; or zero if no such method is provided. * gpio_chip.get() method; or zero if no such method is provided.
*/ */
static int gpiod_get_value(struct gpio_desc *desc) static int gpiod_get_value(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value; int value;
int offset; int offset;
if (!desc)
return 0;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
/* Should be using gpio_get_value_cansleep() */ /* Should be using gpio_get_value_cansleep() */
...@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value) ...@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
if (!desc)
return;
chip = desc->chip; chip = desc->chip;
/* Should be using gpio_set_value_cansleep() */ /* Should be using gpio_set_value_cansleep() */
WARN_ON(chip->can_sleep); WARN_ON(chip->can_sleep);
...@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value); ...@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value);
* This is used directly or indirectly to implement gpio_cansleep(). It * This is used directly or indirectly to implement gpio_cansleep(). It
* returns nonzero if access reading or writing the GPIO value can sleep. * returns nonzero if access reading or writing the GPIO value can sleep.
*/ */
static int gpiod_cansleep(struct gpio_desc *desc) static int gpiod_cansleep(const struct gpio_desc *desc)
{ {
if (!desc)
return 0;
/* only call this on GPIOs that are valid! */ /* only call this on GPIOs that are valid! */
return desc->chip->can_sleep; return desc->chip->can_sleep;
} }
...@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep); ...@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep);
* It returns the number of the IRQ signaled by this (input) GPIO, * It returns the number of the IRQ signaled by this (input) GPIO,
* or a negative errno. * or a negative errno.
*/ */
static int gpiod_to_irq(struct gpio_desc *desc) static int gpiod_to_irq(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int offset; int offset;
if (!desc)
return -EINVAL;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO;
...@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); ...@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq);
* Common examples include ones connected to I2C or SPI chips. * Common examples include ones connected to I2C or SPI chips.
*/ */
static int gpiod_get_value_cansleep(struct gpio_desc *desc) static int gpiod_get_value_cansleep(const struct gpio_desc *desc)
{ {
struct gpio_chip *chip; struct gpio_chip *chip;
int value; int value;
int offset; int offset;
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
if (!desc)
return 0;
chip = desc->chip; chip = desc->chip;
offset = gpio_chip_hwgpio(desc); offset = gpio_chip_hwgpio(desc);
value = chip->get ? chip->get(chip, offset) : 0; value = chip->get ? chip->get(chip, offset) : 0;
...@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) ...@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value)
struct gpio_chip *chip; struct gpio_chip *chip;
might_sleep_if(extra_checks); might_sleep_if(extra_checks);
if (!desc)
return;
chip = desc->chip; chip = desc->chip;
trace_gpio_value(desc_to_gpio(desc), 0, value); trace_gpio_value(desc_to_gpio(desc), 0, value);
if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) if (test_bit(FLAG_OPEN_DRAIN, &desc->flags))
......
...@@ -379,15 +379,15 @@ static const struct pci_device_id pciidlist[] = { /* aka */ ...@@ -379,15 +379,15 @@ static const struct pci_device_id pciidlist[] = { /* aka */
INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */
INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */
INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */
INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */
INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */
INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */
INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */
INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */
INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */
INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */
INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */
INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */
INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */
INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info),
INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),
INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),
...@@ -495,6 +495,7 @@ static int i915_drm_freeze(struct drm_device *dev) ...@@ -495,6 +495,7 @@ static int i915_drm_freeze(struct drm_device *dev)
intel_modeset_disable(dev); intel_modeset_disable(dev);
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
dev_priv->enable_hotplug_processing = false;
} }
i915_save_state(dev); i915_save_state(dev);
...@@ -568,10 +569,20 @@ static int __i915_drm_thaw(struct drm_device *dev) ...@@ -568,10 +569,20 @@ static int __i915_drm_thaw(struct drm_device *dev)
error = i915_gem_init_hw(dev); error = i915_gem_init_hw(dev);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
/* We need working interrupts for modeset enabling ... */
drm_irq_install(dev);
intel_modeset_init_hw(dev); intel_modeset_init_hw(dev);
intel_modeset_setup_hw_state(dev, false); intel_modeset_setup_hw_state(dev, false);
drm_irq_install(dev);
/*
* ... but also need to make sure that hotplug processing
* doesn't cause havoc. Like in the driver load code we don't
* bother with the tiny race here where we might loose hotplug
* notifications.
* */
intel_hpd_init(dev); intel_hpd_init(dev);
dev_priv->enable_hotplug_processing = true;
} }
intel_opregion_init(dev); intel_opregion_init(dev);
......
...@@ -701,7 +701,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) ...@@ -701,7 +701,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 de_iir, gt_iir, de_ier, pm_iir; u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
int i; int i;
...@@ -711,6 +711,15 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) ...@@ -711,6 +711,15 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
de_ier = I915_READ(DEIER); de_ier = I915_READ(DEIER);
I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
/* Disable south interrupts. We'll only write to SDEIIR once, so further
* interrupts will will be stored on its back queue, and then we'll be
* able to process them after we restore SDEIER (as soon as we restore
* it, we'll get an interrupt if SDEIIR still has something to process
* due to its back queue). */
sde_ier = I915_READ(SDEIER);
I915_WRITE(SDEIER, 0);
POSTING_READ(SDEIER);
gt_iir = I915_READ(GTIIR); gt_iir = I915_READ(GTIIR);
if (gt_iir) { if (gt_iir) {
snb_gt_irq_handler(dev, dev_priv, gt_iir); snb_gt_irq_handler(dev, dev_priv, gt_iir);
...@@ -759,6 +768,8 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) ...@@ -759,6 +768,8 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)
I915_WRITE(DEIER, de_ier); I915_WRITE(DEIER, de_ier);
POSTING_READ(DEIER); POSTING_READ(DEIER);
I915_WRITE(SDEIER, sde_ier);
POSTING_READ(SDEIER);
return ret; return ret;
} }
...@@ -778,7 +789,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) ...@@ -778,7 +789,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE; int ret = IRQ_NONE;
u32 de_iir, gt_iir, de_ier, pm_iir; u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier;
atomic_inc(&dev_priv->irq_received); atomic_inc(&dev_priv->irq_received);
...@@ -787,6 +798,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) ...@@ -787,6 +798,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL);
POSTING_READ(DEIER); POSTING_READ(DEIER);
/* Disable south interrupts. We'll only write to SDEIIR once, so further
* interrupts will will be stored on its back queue, and then we'll be
* able to process them after we restore SDEIER (as soon as we restore
* it, we'll get an interrupt if SDEIIR still has something to process
* due to its back queue). */
sde_ier = I915_READ(SDEIER);
I915_WRITE(SDEIER, 0);
POSTING_READ(SDEIER);
de_iir = I915_READ(DEIIR); de_iir = I915_READ(DEIIR);
gt_iir = I915_READ(GTIIR); gt_iir = I915_READ(GTIIR);
pm_iir = I915_READ(GEN6_PMIIR); pm_iir = I915_READ(GEN6_PMIIR);
...@@ -849,6 +869,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) ...@@ -849,6 +869,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)
done: done:
I915_WRITE(DEIER, de_ier); I915_WRITE(DEIER, de_ier);
POSTING_READ(DEIER); POSTING_READ(DEIER);
I915_WRITE(SDEIER, sde_ier);
POSTING_READ(SDEIER);
return ret; return ret;
} }
......
...@@ -1613,9 +1613,9 @@ ...@@ -1613,9 +1613,9 @@
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
#define ADPA_USE_VGA_HVPOLARITY (1<<15) #define ADPA_USE_VGA_HVPOLARITY (1<<15)
#define ADPA_SETS_HVPOLARITY 0 #define ADPA_SETS_HVPOLARITY 0
#define ADPA_VSYNC_CNTL_DISABLE (1<<11) #define ADPA_VSYNC_CNTL_DISABLE (1<<10)
#define ADPA_VSYNC_CNTL_ENABLE 0 #define ADPA_VSYNC_CNTL_ENABLE 0
#define ADPA_HSYNC_CNTL_DISABLE (1<<10) #define ADPA_HSYNC_CNTL_DISABLE (1<<11)
#define ADPA_HSYNC_CNTL_ENABLE 0 #define ADPA_HSYNC_CNTL_ENABLE 0
#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) #define ADPA_VSYNC_ACTIVE_HIGH (1<<4)
#define ADPA_VSYNC_ACTIVE_LOW 0 #define ADPA_VSYNC_ACTIVE_LOW 0
......
...@@ -88,7 +88,7 @@ static void intel_disable_crt(struct intel_encoder *encoder) ...@@ -88,7 +88,7 @@ static void intel_disable_crt(struct intel_encoder *encoder)
u32 temp; u32 temp;
temp = I915_READ(crt->adpa_reg); temp = I915_READ(crt->adpa_reg);
temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
temp &= ~ADPA_DAC_ENABLE; temp &= ~ADPA_DAC_ENABLE;
I915_WRITE(crt->adpa_reg, temp); I915_WRITE(crt->adpa_reg, temp);
} }
......
...@@ -1391,8 +1391,8 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) ...@@ -1391,8 +1391,8 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder)
struct intel_dp *intel_dp = &intel_dig_port->dp; struct intel_dp *intel_dp = &intel_dig_port->dp;
struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct drm_i915_private *dev_priv = encoder->dev->dev_private;
enum port port = intel_dig_port->port; enum port port = intel_dig_port->port;
bool wait;
uint32_t val; uint32_t val;
bool wait = false;
if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) {
val = I915_READ(DDI_BUF_CTL(port)); val = I915_READ(DDI_BUF_CTL(port));
......
...@@ -3604,6 +3604,30 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) ...@@ -3604,6 +3604,30 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable)
*/ */
} }
/**
* i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware
* cursor plane briefly if not already running after enabling the display
* plane.
* This workaround avoids occasional blank screens when self refresh is
* enabled.
*/
static void
g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe)
{
u32 cntl = I915_READ(CURCNTR(pipe));
if ((cntl & CURSOR_MODE) == 0) {
u32 fw_bcl_self = I915_READ(FW_BLC_SELF);
I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN);
I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX);
intel_wait_for_vblank(dev_priv->dev, pipe);
I915_WRITE(CURCNTR(pipe), cntl);
I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe)));
I915_WRITE(FW_BLC_SELF, fw_bcl_self);
}
}
static void i9xx_crtc_enable(struct drm_crtc *crtc) static void i9xx_crtc_enable(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
...@@ -3629,6 +3653,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) ...@@ -3629,6 +3653,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc)
intel_enable_pipe(dev_priv, pipe, false); intel_enable_pipe(dev_priv, pipe, false);
intel_enable_plane(dev_priv, plane, pipe); intel_enable_plane(dev_priv, plane, pipe);
if (IS_G4X(dev))
g4x_fixup_plane(dev_priv, pipe);
intel_crtc_load_lut(crtc); intel_crtc_load_lut(crtc);
intel_update_fbc(dev); intel_update_fbc(dev);
...@@ -7256,8 +7282,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -7256,8 +7282,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_framebuffer *intel_fb; struct drm_framebuffer *old_fb = crtc->fb;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_unpin_work *work; struct intel_unpin_work *work;
unsigned long flags; unsigned long flags;
...@@ -7282,8 +7308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -7282,8 +7308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
work->event = event; work->event = event;
work->crtc = crtc; work->crtc = crtc;
intel_fb = to_intel_framebuffer(crtc->fb); work->old_fb_obj = to_intel_framebuffer(old_fb)->obj;
work->old_fb_obj = intel_fb->obj;
INIT_WORK(&work->work, intel_unpin_work_fn); INIT_WORK(&work->work, intel_unpin_work_fn);
ret = drm_vblank_get(dev, intel_crtc->pipe); ret = drm_vblank_get(dev, intel_crtc->pipe);
...@@ -7303,9 +7328,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -7303,9 +7328,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
intel_crtc->unpin_work = work; intel_crtc->unpin_work = work;
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
intel_fb = to_intel_framebuffer(fb);
obj = intel_fb->obj;
if (atomic_read(&intel_crtc->unpin_work_count) >= 2) if (atomic_read(&intel_crtc->unpin_work_count) >= 2)
flush_workqueue(dev_priv->wq); flush_workqueue(dev_priv->wq);
...@@ -7340,6 +7362,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, ...@@ -7340,6 +7362,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
cleanup_pending: cleanup_pending:
atomic_dec(&intel_crtc->unpin_work_count); atomic_dec(&intel_crtc->unpin_work_count);
crtc->fb = old_fb;
drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&work->old_fb_obj->base);
drm_gem_object_unreference(&obj->base); drm_gem_object_unreference(&obj->base);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
......
...@@ -353,7 +353,8 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) ...@@ -353,7 +353,8 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq)
#define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
if (has_aux_irq) if (has_aux_irq)
done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
msecs_to_jiffies(10));
else else
done = wait_for_atomic(C, 10) == 0; done = wait_for_atomic(C, 10) == 0;
if (!done) if (!done)
......
...@@ -2574,7 +2574,7 @@ static void gen6_enable_rps(struct drm_device *dev) ...@@ -2574,7 +2574,7 @@ static void gen6_enable_rps(struct drm_device *dev)
I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC_SLEEP, 0);
I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); I915_WRITE(GEN6_RC1e_THRESHOLD, 1000);
I915_WRITE(GEN6_RC6_THRESHOLD, 50000); I915_WRITE(GEN6_RC6_THRESHOLD, 50000);
I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); I915_WRITE(GEN6_RC6p_THRESHOLD, 150000);
I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
/* Check if we are enabling RC6 */ /* Check if we are enabling RC6 */
......
...@@ -112,7 +112,6 @@ struct mga_framebuffer { ...@@ -112,7 +112,6 @@ struct mga_framebuffer {
struct mga_fbdev { struct mga_fbdev {
struct drm_fb_helper helper; struct drm_fb_helper helper;
struct mga_framebuffer mfb; struct mga_framebuffer mfb;
struct list_head fbdev_list;
void *sysram; void *sysram;
int size; int size;
struct ttm_bo_kmap_obj mapping; struct ttm_bo_kmap_obj mapping;
......
...@@ -92,6 +92,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev) ...@@ -92,6 +92,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
int ret; int ret;
int data, clock; int data, clock;
WREG_DAC(MGA1064_GEN_IO_CTL2, 1);
WREG_DAC(MGA1064_GEN_IO_DATA, 0xff); WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
WREG_DAC(MGA1064_GEN_IO_CTL, 0); WREG_DAC(MGA1064_GEN_IO_CTL, 0);
......
...@@ -1406,6 +1406,14 @@ static int mga_vga_get_modes(struct drm_connector *connector) ...@@ -1406,6 +1406,14 @@ static int mga_vga_get_modes(struct drm_connector *connector)
static int mga_vga_mode_valid(struct drm_connector *connector, static int mga_vga_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_device *dev = connector->dev;
struct mga_device *mdev = (struct mga_device*)dev->dev_private;
struct mga_fbdev *mfbdev = mdev->mfbdev;
struct drm_fb_helper *fb_helper = &mfbdev->helper;
struct drm_fb_helper_connector *fb_helper_conn = NULL;
int bpp = 32;
int i = 0;
/* FIXME: Add bandwidth and g200se limitations */ /* FIXME: Add bandwidth and g200se limitations */
if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
...@@ -1415,6 +1423,25 @@ static int mga_vga_mode_valid(struct drm_connector *connector, ...@@ -1415,6 +1423,25 @@ static int mga_vga_mode_valid(struct drm_connector *connector,
return MODE_BAD; return MODE_BAD;
} }
/* Validate the mode input by the user */
for (i = 0; i < fb_helper->connector_count; i++) {
if (fb_helper->connector_info[i]->connector == connector) {
/* Found the helper for this connector */
fb_helper_conn = fb_helper->connector_info[i];
if (fb_helper_conn->cmdline_mode.specified) {
if (fb_helper_conn->cmdline_mode.bpp_specified) {
bpp = fb_helper_conn->cmdline_mode.bpp;
}
}
}
}
if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) {
if (fb_helper_conn)
fb_helper_conn->cmdline_mode.specified = false;
return MODE_BAD;
}
return MODE_OK; return MODE_OK;
} }
......
...@@ -350,7 +350,7 @@ nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) ...@@ -350,7 +350,7 @@ nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv)
nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
} }
nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
} }
......
...@@ -869,7 +869,7 @@ init_idx_addr_latched(struct nvbios_init *init) ...@@ -869,7 +869,7 @@ init_idx_addr_latched(struct nvbios_init *init)
init->offset += 2; init->offset += 2;
init_wr32(init, dreg, idata); init_wr32(init, dreg, idata);
init_mask(init, creg, ~mask, data | idata); init_mask(init, creg, ~mask, data | iaddr);
} }
} }
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册