Merge branch 'kvm-updates/3.3' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Fixing a regression with the PMU MSRs when PMU virtualization is
disabled, a guest-internal DoS with the SYSCALL instruction, and a dirty
memory logging race that may cause live migration to fail.
* 'kvm-updates/3.3' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: do not #GP on perf MSR writes when vPMU is disabled
KVM: x86: fix missing checks in syscall emulation
KVM: x86: extend "struct x86_emulate_ops" with "get_cpuid"
KVM: Fix __set_bit() race in mark_page_dirty() during dirty logging
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 2f7fd43..9c27e51 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -102,9 +102,12 @@
!Iinclude/linux/device.h
</sect1>
<sect1><title>Device Drivers Base</title>
+!Idrivers/base/init.c
!Edrivers/base/driver.c
!Edrivers/base/core.c
+!Edrivers/base/syscore.c
!Edrivers/base/class.c
+!Idrivers/base/node.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
<!-- Cannot be included, because
@@ -113,7 +116,7 @@
exceed allowed 44 characters maximum
X!Edrivers/base/attribute_container.c
-->
-!Edrivers/base/sys.c
+!Edrivers/base/dd.c
<!--
X!Edrivers/base/interface.c
-->
@@ -121,6 +124,11 @@
!Edrivers/base/platform.c
!Edrivers/base/bus.c
</sect1>
+ <sect1><title>Device Drivers DMA Management</title>
+!Edrivers/base/dma-buf.c
+!Edrivers/base/dma-coherent.c
+!Edrivers/base/dma-mapping.c
+ </sect1>
<sect1><title>Device Drivers Power Management</title>
!Edrivers/base/power/main.c
</sect1>
@@ -219,7 +227,7 @@
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250.c
+!Edrivers/tty/serial/8250/8250.c
</chapter>
<chapter id="fbdev">
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 10c64c8..41c0c5d 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -233,6 +233,10 @@
6. List of managed interfaces
-----------------------------
+MEM
+ devm_kzalloc()
+ devm_kfree()
+
IO region
devm_request_region()
devm_request_mem_region()
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 1bea46a..a0ffac0 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -510,3 +510,17 @@
convert to using pci_scan_root_bus() so they can supply a list of
bus resources when the bus is created.
Who: Bjorn Helgaas <bhelgaas@google.com>
+
+----------------------------
+
+What: The CAP9 SoC family will be removed
+When: 3.4
+Files: arch/arm/mach-at91/at91cap9.c
+ arch/arm/mach-at91/at91cap9_devices.c
+ arch/arm/mach-at91/include/mach/at91cap9.h
+ arch/arm/mach-at91/include/mach/at91cap9_matrix.h
+ arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
+ arch/arm/mach-at91/board-cap9adk.c
+Why: The code is not actively maintained and platforms are now hard to find.
+Who: Nicolas Ferre <nicolas.ferre@atmel.com>
+ Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
index 23fcb05..53305bd 100644
--- a/Documentation/input/event-codes.txt
+++ b/Documentation/input/event-codes.txt
@@ -17,11 +17,11 @@
class/input/event*/device/capabilities/, and the properties of a device are
provided in class/input/event*/device/properties.
-Types:
-==========
-Types are groupings of codes under a logical input construct. Each type has a
-set of applicable codes to be used in generating events. See the Codes section
-for details on valid codes for each type.
+Event types:
+===========
+Event types are groupings of codes under a logical input construct. Each
+type has a set of applicable codes to be used in generating events. See the
+Codes section for details on valid codes for each type.
* EV_SYN:
- Used as markers to separate events. Events may be separated in time or in
@@ -63,9 +63,9 @@
* EV_FF_STATUS:
- Used to receive force feedback device status.
-Codes:
-==========
-Codes define the precise type of event.
+Event codes:
+===========
+Event codes define the precise type of event.
EV_SYN:
----------
@@ -220,6 +220,56 @@
EV_PWR events are a special type of event used specifically for power
mangement. Its usage is not well defined. To be addressed later.
+Device properties:
+=================
+Normally, userspace sets up an input device based on the data it emits,
+i.e., the event types. In the case of two devices emitting the same event
+types, additional information can be provided in the form of device
+properties.
+
+INPUT_PROP_DIRECT + INPUT_PROP_POINTER:
+--------------------------------------
+The INPUT_PROP_DIRECT property indicates that device coordinates should be
+directly mapped to screen coordinates (not taking into account trivial
+transformations, such as scaling, flipping and rotating). Non-direct input
+devices require non-trivial transformation, such as absolute to relative
+transformation for touchpads. Typical direct input devices: touchscreens,
+drawing tablets; non-direct devices: touchpads, mice.
+
+The INPUT_PROP_POINTER property indicates that the device is not transposed
+on the screen and thus requires use of an on-screen pointer to trace user's
+movements. Typical pointer devices: touchpads, tablets, mice; non-pointer
+device: touchscreen.
+
+If neither INPUT_PROP_DIRECT or INPUT_PROP_POINTER are set, the property is
+considered undefined and the device type should be deduced in the
+traditional way, using emitted event types.
+
+INPUT_PROP_BUTTONPAD:
+--------------------
+For touchpads where the button is placed beneath the surface, such that
+pressing down on the pad causes a button click, this property should be
+set. Common in clickpad notebooks and macbooks from 2009 and onwards.
+
+Originally, the buttonpad property was coded into the bcm5974 driver
+version field under the name integrated button. For backwards
+compatibility, both methods need to be checked in userspace.
+
+INPUT_PROP_SEMI_MT:
+------------------
+Some touchpads, most common between 2008 and 2011, can detect the presence
+of multiple contacts without resolving the individual positions; only the
+number of contacts and a rectangular shape is known. For such
+touchpads, the semi-mt property should be set.
+
+Depending on the device, the rectangle may enclose all touches, like a
+bounding box, or just some of them, for instance the two most recent
+touches. The diversity makes the rectangle of limited use, but some
+gestures can normally be extracted from it.
+
+If INPUT_PROP_SEMI_MT is not set, the device is assumed to be a true MT
+device.
+
Guidelines:
==========
The guidelines below ensure proper single-touch and multi-finger functionality.
@@ -240,6 +290,8 @@
BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
contact. BTN_TOOL_<name> events should be reported where possible.
+For new hardware, INPUT_PROP_DIRECT should be set.
+
Trackpads:
----------
Legacy trackpads that only provide relative position information must report
@@ -250,6 +302,8 @@
on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
be used to report the number of touches active on the trackpad.
+For new hardware, INPUT_PROP_POINTER should be set.
+
Tablets:
----------
BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
@@ -260,3 +314,5 @@
BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
purpose on the device.
+
+For new hardware, both INPUT_PROP_DIRECT and INPUT_PROP_POINTER should be set.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index 6727b92..150fd38 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -857,42 +857,41 @@
...
{
- .name "2bit"
+ .name = "2bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "4bit"
+ .name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "4bit"
+ .name = "4bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
- .function = "mmc0",
.group = "mmc0_1_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_2_grp",
.dev_name = "foo-mmc.0",
},
{
- .name "8bit"
+ .name = "8bit"
.ctrl_dev_name = "pinctrl-foo",
.function = "mmc0",
.group = "mmc0_3_grp",
@@ -995,7 +994,7 @@
like this:
{
- .name "POWERMAP"
+ .name = "POWERMAP"
.ctrl_dev_name = "pinctrl-foo",
.function = "power_func",
.hog_on_boot = true,
@@ -1025,7 +1024,7 @@
foo_switch()
{
- struct pinmux pmx;
+ struct pinmux *pmx;
/* Enable on position A */
pmx = pinmux_get(&device, "spi0-pos-A");
diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt
index 21fd05c..f0ab5cf 100644
--- a/Documentation/stable_kernel_rules.txt
+++ b/Documentation/stable_kernel_rules.txt
@@ -25,7 +25,8 @@
- Send the patch, after verifying that it follows the above rules, to
stable@vger.kernel.org. You must note the upstream commit ID in the
- changelog of your submission.
+ changelog of your submission, as well as the kernel version you wish
+ it to be applied to.
- To have the patch automatically included in the stable tree, add the tag
Cc: stable@vger.kernel.org
in the sign-off area. Once the patch is merged it will be applied to
diff --git a/Documentation/virtual/00-INDEX b/Documentation/virtual/00-INDEX
index 8e60199..924bd46 100644
--- a/Documentation/virtual/00-INDEX
+++ b/Documentation/virtual/00-INDEX
@@ -4,8 +4,6 @@
- this file.
kvm/
- Kernel Virtual Machine. See also http://linux-kvm.org
-lguest/
- - Extremely simple hypervisor for experimental/educational use.
uml/
- User Mode Linux, builds/runs Linux kernel as a userspace program.
virtio.txt
diff --git a/MAINTAINERS b/MAINTAINERS
index 93c68d5..8591c03 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -159,7 +159,7 @@
F: drivers/net/ethernet/realtek/r8169.c
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-serial@vger.kernel.org
W: http://serial.sourceforge.net
S: Maintained
@@ -789,12 +789,6 @@
F: arch/arm/mach-imx/
F: arch/arm/plat-mxc/
-ARM/FREESCALE IMX51
-M: Amit Kucheria <amit.kucheria@canonical.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-F: arch/arm/mach-mx5/
-
ARM/FREESCALE IMX6
M: Shawn Guo <shawn.guo@linaro.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1783,9 +1777,9 @@
CHAR and MISC DRIVERS
M: Arnd Bergmann <arnd@arndb.de>
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
-S: Maintained
+S: Supported
F: drivers/char/*
F: drivers/misc/*
@@ -2320,7 +2314,7 @@
F: Documentation/blockdev/drbd/
DRIVER CORE, KOBJECTS, DEBUGFS AND SYSFS
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6.git
S: Supported
F: Documentation/kobject.txt
@@ -2350,6 +2344,9 @@
DRM DRIVERS FOR EXYNOS
M: Inki Dae <inki.dae@samsung.com>
+M: Joonyoung Shim <jy0922.shim@samsung.com>
+M: Seung-Woo Kim <sw0312.kim@samsung.com>
+M: Kyungmin Park <kyungmin.park@samsung.com>
L: dri-devel@lists.freedesktop.org
S: Supported
F: drivers/gpu/drm/exynos
@@ -2402,7 +2399,7 @@
ECRYPT FILE SYSTEM
M: Tyler Hicks <tyhicks@canonical.com>
-M: Dustin Kirkland <kirkland@canonical.com>
+M: Dustin Kirkland <dustin.kirkland@gazzang.com>
L: ecryptfs@vger.kernel.org
W: https://launchpad.net/ecryptfs
S: Supported
@@ -3989,11 +3986,11 @@
L: lguest@lists.ozlabs.org
W: http://lguest.ozlabs.org/
S: Odd Fixes
-F: Documentation/virtual/lguest/
+F: arch/x86/include/asm/lguest*.h
F: arch/x86/lguest/
F: drivers/lguest/
F: include/linux/lguest*.h
-F: arch/x86/include/asm/lguest*.h
+F: tools/lguest/
LINUX FOR IBM pSERIES (RS/6000)
M: Paul Mackerras <paulus@au.ibm.com>
@@ -4133,10 +4130,11 @@
W: http://www.linux-ntfs.org/content/view/19/37/
S: Maintained
F: Documentation/ldm.txt
-F: fs/partitions/ldm.*
+F: block/partitions/ldm.*
LogFS
M: Joern Engel <joern@logfs.org>
+M: Prasad Joshi <prasadjoshi.linux@gmail.com>
L: logfs@logfs.org
W: logfs.org
S: Maintained
@@ -4278,13 +4276,6 @@
F: drivers/video/matrox/matroxfb_*
F: include/linux/matroxfb.h
-MAX1668 TEMPERATURE SENSOR DRIVER
-M: "David George" <david.george@ska.ac.za>
-L: lm-sensors@lm-sensors.org
-S: Maintained
-F: Documentation/hwmon/max1668
-F: drivers/hwmon/max1668.c
-
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
M: "Hans J. Koch" <hjk@hansjkoch.de>
L: lm-sensors@lm-sensors.org
@@ -5636,7 +5627,7 @@
S: Supported
F: arch/s390/
F: drivers/s390/
-F: fs/partitions/ibm.c
+F: block/partitions/ibm.c
F: Documentation/s390/
F: Documentation/DocBook/s390*
@@ -6279,15 +6270,15 @@
F: arch/alpha/kernel/srm_env.c
STABLE BRANCH
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: stable@vger.kernel.org
-S: Maintained
+S: Supported
STAGING SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
L: devel@driverdev.osuosl.org
-S: Maintained
+S: Supported
F: drivers/staging/
STAGING - AGERE HERMES II and II.5 WIRELESS DRIVERS
@@ -6399,11 +6390,6 @@
S: Odd Fixes
F: drivers/staging/tidspbridge/
-STAGING - TRIDENT TVMASTER TMxxxx USB VIDEO CAPTURE DRIVERS
-L: linux-media@vger.kernel.org
-S: Odd Fixes
-F: drivers/staging/tm6000/
-
STAGING - USB ENE SM/MS CARD READER DRIVER
M: Al Cho <acho@novell.com>
S: Odd Fixes
@@ -6672,10 +6658,10 @@
K: ^Subject:.*(?i)trivial
TTY LAYER
-M: Greg Kroah-Hartman <gregkh@suse.de>
-S: Maintained
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6.git
-F: drivers/tty/*
+F: drivers/tty/
F: drivers/tty/serial/serial_core.c
F: include/linux/serial_core.h
F: include/linux/serial.h
@@ -6961,7 +6947,7 @@
F: drivers/usb/serial/digi_acceleport.c
USB SERIAL DRIVER
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
S: Supported
F: Documentation/usb/usb-serial.txt
@@ -6976,9 +6962,8 @@
F: drivers/usb/serial/empeg.c
USB SERIAL KEYSPAN DRIVER
-M: Greg Kroah-Hartman <greg@kroah.com>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
-W: http://www.kroah.com/linux/
S: Maintained
F: drivers/usb/serial/*keyspan*
@@ -7006,7 +6991,7 @@
F: drivers/media/video/sn9c102/
USB SUBSYSTEM
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
W: http://www.linux-usb.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6.git
@@ -7093,7 +7078,7 @@
USERSPACE I/O (UIO)
M: "Hans J. Koch" <hjk@hansjkoch.de>
-M: Greg Kroah-Hartman <gregkh@suse.de>
+M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
S: Maintained
F: Documentation/DocBook/uio-howto.tmpl
F: drivers/uio/
@@ -7368,6 +7353,7 @@
F: Documentation/hwmon/wm83??
F: arch/arm/mach-s3c64xx/mach-crag6410*
F: drivers/leds/leds-wm83*.c
+F: drivers/hwmon/wm83??-hwmon.c
F: drivers/input/misc/wm831x-on.c
F: drivers/input/touchscreen/wm831x-ts.c
F: drivers/input/touchscreen/wm97*.c
diff --git a/Makefile b/Makefile
index 71e6ed2..e3b23e8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 3
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 24626b0..a48aecc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -754,7 +754,7 @@
select ARCH_HAS_CPUFREQ
select CPU_FREQ
select GENERIC_CLOCKEVENTS
- select CLKDEV_LOOKUP
+ select HAVE_CLK
select HAVE_SCHED_CLOCK
select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB
@@ -825,7 +825,6 @@
select HAVE_CLK
select CLKDEV_LOOKUP
select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
select ARCH_USES_GETTIMEOFFSET
select HAVE_S3C2410_I2C if I2C
select HAVE_S3C_RTC if RTC_CLASS
@@ -842,7 +841,6 @@
select HAVE_CLK
select CLKDEV_LOOKUP
select CLKSRC_MMIO
- select ARM_L1_CACHE_SHIFT_6
select ARCH_HAS_CPUFREQ
select GENERIC_CLOCKEVENTS
select HAVE_SCHED_CLOCK
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index b2dc2dd..c47d619 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -41,6 +41,7 @@
#include <asm/irq.h>
#include <asm/exception.h>
+#include <asm/smp_plat.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
@@ -352,11 +353,7 @@
unsigned int gic_irqs = gic->gic_irqs;
struct irq_domain *domain = &gic->domain;
void __iomem *base = gic_data_dist_base(gic);
- u32 cpu = 0;
-
-#ifdef CONFIG_SMP
- cpu = cpu_logical_map(smp_processor_id());
-#endif
+ u32 cpu = cpu_logical_map(smp_processor_id());
cpumask = 1 << cpu;
cpumask |= cpumask << 8;
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index b6e65de..62f8095 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -237,7 +237,7 @@
*/
#ifdef CONFIG_THUMB2_KERNEL
- .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
+ .macro usraccoff, instr, reg, ptr, inc, off, cond, abort, t=TUSER()
9999:
.if \inc == 1
\instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
@@ -277,7 +277,7 @@
#else /* !CONFIG_THUMB2_KERNEL */
- .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
+ .macro usracc, instr, reg, ptr, inc, cond, rept, abort, t=TUSER()
.rept \rept
9999:
.if \inc == 1
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index af18cea..b5dc173 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -83,9 +83,9 @@
* instructions (inline assembly)
*/
#ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr) #instr "t"
+#define TUSER(instr) #instr "t"
#else
-#define T(instr) #instr
+#define TUSER(instr) #instr
#endif
#else /* __ASSEMBLY__ */
@@ -95,9 +95,9 @@
* instructions
*/
#ifdef CONFIG_CPU_USE_DOMAINS
-#define T(instr) instr ## t
+#define TUSER(instr) instr ## t
#else
-#define T(instr) instr
+#define TUSER(instr) instr
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
index 253cc86..7be5469 100644
--- a/arch/arm/include/asm/futex.h
+++ b/arch/arm/include/asm/futex.h
@@ -75,9 +75,9 @@
#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
__asm__ __volatile__( \
- "1: " T(ldr) " %1, [%3]\n" \
+ "1: " TUSER(ldr) " %1, [%3]\n" \
" " insn "\n" \
- "2: " T(str) " %0, [%3]\n" \
+ "2: " TUSER(str) " %0, [%3]\n" \
" mov %0, #0\n" \
__futex_atomic_ex_table("%5") \
: "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
@@ -95,10 +95,10 @@
return -EFAULT;
__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
- "1: " T(ldr) " %1, [%4]\n"
+ "1: " TUSER(ldr) " %1, [%4]\n"
" teq %1, %2\n"
" it eq @ explicit IT needed for the 2b label\n"
- "2: " T(streq) " %3, [%4]\n"
+ "2: " TUSER(streq) " %3, [%4]\n"
__futex_atomic_ex_table("%5")
: "+r" (ret), "=&r" (val)
: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 1e5717a..ae29293 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -71,12 +71,6 @@
extern void platform_smp_prepare_cpus(unsigned int);
/*
- * Logical CPU mapping.
- */
-extern int __cpu_logical_map[NR_CPUS];
-#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
-
-/*
* Initial data for bringing up a secondary CPU.
*/
struct secondary_data {
diff --git a/arch/arm/include/asm/smp_plat.h b/arch/arm/include/asm/smp_plat.h
index f24c1b9..558d6c8 100644
--- a/arch/arm/include/asm/smp_plat.h
+++ b/arch/arm/include/asm/smp_plat.h
@@ -43,4 +43,10 @@
}
#endif
+/*
+ * Logical CPU mapping.
+ */
+extern int __cpu_logical_map[];
+#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
+
#endif
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h
index 5d3ed7e3..314d466 100644
--- a/arch/arm/include/asm/tlb.h
+++ b/arch/arm/include/asm/tlb.h
@@ -198,7 +198,15 @@
unsigned long addr)
{
pgtable_page_dtor(pte);
- tlb_add_flush(tlb, addr);
+
+ /*
+ * With the classic ARM MMU, a pte page has two corresponding pmd
+ * entries, each covering 1MB.
+ */
+ addr &= PMD_MASK;
+ tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
+ tlb_add_flush(tlb, addr + SZ_1M);
+
tlb_remove_page(tlb, pte);
}
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
index b293616..2958976 100644
--- a/arch/arm/include/asm/uaccess.h
+++ b/arch/arm/include/asm/uaccess.h
@@ -227,7 +227,7 @@
#define __get_user_asm_byte(x,addr,err) \
__asm__ __volatile__( \
- "1: " T(ldrb) " %1,[%2],#0\n" \
+ "1: " TUSER(ldrb) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
@@ -263,7 +263,7 @@
#define __get_user_asm_word(x,addr,err) \
__asm__ __volatile__( \
- "1: " T(ldr) " %1,[%2],#0\n" \
+ "1: " TUSER(ldr) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
@@ -308,7 +308,7 @@
#define __put_user_asm_byte(x,__pu_addr,err) \
__asm__ __volatile__( \
- "1: " T(strb) " %1,[%2],#0\n" \
+ "1: " TUSER(strb) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
@@ -341,7 +341,7 @@
#define __put_user_asm_word(x,__pu_addr,err) \
__asm__ __volatile__( \
- "1: " T(str) " %1,[%2],#0\n" \
+ "1: " TUSER(str) " %1,[%2],#0\n" \
"2:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
@@ -366,10 +366,10 @@
#define __put_user_asm_dword(x,__pu_addr,err) \
__asm__ __volatile__( \
- ARM( "1: " T(str) " " __reg_oper1 ", [%1], #4\n" ) \
- ARM( "2: " T(str) " " __reg_oper0 ", [%1]\n" ) \
- THUMB( "1: " T(str) " " __reg_oper1 ", [%1]\n" ) \
- THUMB( "2: " T(str) " " __reg_oper0 ", [%1, #4]\n" ) \
+ ARM( "1: " TUSER(str) " " __reg_oper1 ", [%1], #4\n" ) \
+ ARM( "2: " TUSER(str) " " __reg_oper0 ", [%1]\n" ) \
+ THUMB( "1: " TUSER(str) " " __reg_oper1 ", [%1]\n" ) \
+ THUMB( "2: " TUSER(str) " " __reg_oper0 ", [%1, #4]\n" ) \
"3:\n" \
" .pushsection .fixup,\"ax\"\n" \
" .align 2\n" \
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 3a456c6..be16a48 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -790,7 +790,7 @@
smp_dmb arm
rsbs r0, r3, #0 @ set returned val and C flag
ldmfd sp!, {r4, r5, r6, r7}
- bx lr
+ usr_ret lr
#elif !defined(CONFIG_SMP)
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 520889c..9fd0ba9 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -149,6 +149,11 @@
#endif
#endif
+.macro mcount_adjust_addr rd, rn
+ bic \rd, \rn, #1 @ clear the Thumb bit if present
+ sub \rd, \rd, #MCOUNT_INSN_SIZE
+.endm
+
.macro __mcount suffix
mcount_enter
ldr r0, =ftrace_trace_function
@@ -173,8 +178,7 @@
mcount_exit
1: mcount_get_lr r1 @ lr of instrumented func
- mov r0, lr @ instrumented function
- sub r0, r0, #MCOUNT_INSN_SIZE
+ mcount_adjust_addr r0, lr @ instrumented function
adr lr, BSYM(2f)
mov pc, r2
2: mcount_exit
@@ -184,8 +188,7 @@
mcount_enter
mcount_get_lr r1 @ lr of instrumented func
- mov r0, lr @ instrumented function
- sub r0, r0, #MCOUNT_INSN_SIZE
+ mcount_adjust_addr r0, lr @ instrumented function
.globl ftrace_call\suffix
ftrace_call\suffix:
@@ -205,11 +208,11 @@
#ifdef CONFIG_DYNAMIC_FTRACE
@ called from __ftrace_caller, saved in mcount_enter
ldr r1, [sp, #16] @ instrumented routine (func)
+ mcount_adjust_addr r1, r1
#else
@ called from __mcount, untouched in lr
- mov r1, lr @ instrumented routine (func)
+ mcount_adjust_addr r1, lr @ instrumented routine (func)
#endif
- sub r1, r1, #MCOUNT_INSN_SIZE
mov r2, fp @ frame pointer
bl prepare_ftrace_return
mcount_exit
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 460bbbb..6933244 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -469,6 +469,20 @@
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
@@ -579,6 +593,20 @@
[C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
},
},
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
};
/*
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index e1d5e19..e33870f 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -699,10 +699,13 @@
{
int ret;
struct thread_info *thread = task_thread_info(target);
- struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
+ struct vfp_hard_struct new_vfp;
const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
+ vfp_sync_hwstate(thread);
+ new_vfp = thread->vfpstate.hard;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&new_vfp.fpregs,
user_fpregs_offset,
@@ -723,9 +726,8 @@
if (ret)
return ret;
- vfp_sync_hwstate(thread);
- thread->vfpstate.hard = new_vfp;
vfp_flush_hwstate(thread);
+ thread->vfpstate.hard = new_vfp;
return 0;
}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 129fbd5..a255c39 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -21,7 +21,6 @@
#include <linux/init.h>
#include <linux/kexec.h>
#include <linux/of_fdt.h>
-#include <linux/crash_dump.h>
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
@@ -160,7 +159,7 @@
.flags = IORESOURCE_MEM
},
{
- .name = "Kernel text",
+ .name = "Kernel code",
.start = 0,
.end = 0,
.flags = IORESOURCE_MEM
@@ -427,6 +426,20 @@
: "r14");
}
+int __cpu_logical_map[NR_CPUS];
+
+void __init smp_setup_processor_id(void)
+{
+ int i;
+ u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
+
+ cpu_logical_map(0) = cpu;
+ for (i = 1; i < NR_CPUS; ++i)
+ cpu_logical_map(i) = i == cpu ? 0 : i;
+
+ printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
+}
+
static void __init setup_processor(void)
{
struct proc_info_list *list;
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 0340224..9e617bd 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -227,6 +227,8 @@
if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
return -EINVAL;
+ vfp_flush_hwstate(thread);
+
/*
* Copy the floating point registers. There can be unused
* registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@
__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
- if (!err)
- vfp_flush_hwstate(thread);
-
return err ? -EFAULT : 0;
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 57db122..cdeb727 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -233,20 +233,6 @@
}
#endif /* CONFIG_HOTPLUG_CPU */
-int __cpu_logical_map[NR_CPUS];
-
-void __init smp_setup_processor_id(void)
-{
- int i;
- u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0;
-
- cpu_logical_map(0) = cpu;
- for (i = 1; i < NR_CPUS; ++i)
- cpu_logical_map(i) = i == cpu ? 0 : i;
-
- printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu);
-}
-
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
@@ -443,9 +429,7 @@
static void ipi_timer(void)
{
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
- irq_enter();
evt->event_handler(evt);
- irq_exit();
}
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -548,7 +532,9 @@
switch (ipinr) {
case IPI_TIMER:
+ irq_enter();
ipi_timer();
+ irq_exit();
break;
case IPI_RESCHEDULE:
@@ -556,15 +542,21 @@
break;
case IPI_CALL_FUNC:
+ irq_enter();
generic_smp_call_function_interrupt();
+ irq_exit();
break;
case IPI_CALL_FUNC_SINGLE:
+ irq_enter();
generic_smp_call_function_single_interrupt();
+ irq_exit();
break;
case IPI_CPU_STOP:
+ irq_enter();
ipi_cpu_stop(cpu);
+ irq_exit();
break;
default:
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index c8e9385..4285daa 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -252,6 +252,8 @@
else
twd_calibrate_rate();
+ __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
+
clk->name = "local_timer";
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_C3STOP;
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f76e755..1e19691 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -4,6 +4,7 @@
*/
#include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
@@ -181,7 +182,7 @@
}
#endif
- PERCPU_SECTION(32)
+ PERCPU_SECTION(L1_CACHE_BYTES)
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
@@ -212,13 +213,13 @@
#endif
NOSAVE_DATA
- CACHELINE_ALIGNED_DATA(32)
- READ_MOSTLY_DATA(32)
+ CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES)
+ READ_MOSTLY_DATA(L1_CACHE_BYTES)
/*
* The exception fixup table (might need resorting at runtime)
*/
- . = ALIGN(32);
+ . = ALIGN(4);
__start___ex_table = .;
#ifdef CONFIG_MMU
*(__ex_table)
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index 1b049cd..11093a7 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -31,18 +31,18 @@
#include <asm/domain.h>
ENTRY(__get_user_1)
-1: T(ldrb) r2, [r0]
+1: TUSER(ldrb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__get_user_1)
ENTRY(__get_user_2)
#ifdef CONFIG_THUMB2_KERNEL
-2: T(ldrb) r2, [r0]
-3: T(ldrb) r3, [r0, #1]
+2: TUSER(ldrb) r2, [r0]
+3: TUSER(ldrb) r3, [r0, #1]
#else
-2: T(ldrb) r2, [r0], #1
-3: T(ldrb) r3, [r0]
+2: TUSER(ldrb) r2, [r0], #1
+3: TUSER(ldrb) r3, [r0]
#endif
#ifndef __ARMEB__
orr r2, r2, r3, lsl #8
@@ -54,7 +54,7 @@
ENDPROC(__get_user_2)
ENTRY(__get_user_4)
-4: T(ldr) r2, [r0]
+4: TUSER(ldr) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__get_user_4)
diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S
index c023fc1..7db2599 100644
--- a/arch/arm/lib/putuser.S
+++ b/arch/arm/lib/putuser.S
@@ -31,7 +31,7 @@
#include <asm/domain.h>
ENTRY(__put_user_1)
-1: T(strb) r2, [r0]
+1: TUSER(strb) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_1)
@@ -40,19 +40,19 @@
mov ip, r2, lsr #8
#ifdef CONFIG_THUMB2_KERNEL
#ifndef __ARMEB__
-2: T(strb) r2, [r0]
-3: T(strb) ip, [r0, #1]
+2: TUSER(strb) r2, [r0]
+3: TUSER(strb) ip, [r0, #1]
#else
-2: T(strb) ip, [r0]
-3: T(strb) r2, [r0, #1]
+2: TUSER(strb) ip, [r0]
+3: TUSER(strb) r2, [r0, #1]
#endif
#else /* !CONFIG_THUMB2_KERNEL */
#ifndef __ARMEB__
-2: T(strb) r2, [r0], #1
-3: T(strb) ip, [r0]
+2: TUSER(strb) r2, [r0], #1
+3: TUSER(strb) ip, [r0]
#else
-2: T(strb) ip, [r0], #1
-3: T(strb) r2, [r0]
+2: TUSER(strb) ip, [r0], #1
+3: TUSER(strb) r2, [r0]
#endif
#endif /* CONFIG_THUMB2_KERNEL */
mov r0, #0
@@ -60,18 +60,18 @@
ENDPROC(__put_user_2)
ENTRY(__put_user_4)
-4: T(str) r2, [r0]
+4: TUSER(str) r2, [r0]
mov r0, #0
mov pc, lr
ENDPROC(__put_user_4)
ENTRY(__put_user_8)
#ifdef CONFIG_THUMB2_KERNEL
-5: T(str) r2, [r0]
-6: T(str) r3, [r0, #4]
+5: TUSER(str) r2, [r0]
+6: TUSER(str) r3, [r0, #4]
#else
-5: T(str) r2, [r0], #4
-6: T(str) r3, [r0]
+5: TUSER(str) r2, [r0], #4
+6: TUSER(str) r3, [r0]
#endif
mov r0, #0
mov pc, lr
diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S
index d0ece2a..5c908b1 100644
--- a/arch/arm/lib/uaccess.S
+++ b/arch/arm/lib/uaccess.S
@@ -32,11 +32,11 @@
rsb ip, ip, #4
cmp ip, #2
ldrb r3, [r1], #1
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
sub r2, r2, ip
b .Lc2u_dest_aligned
@@ -59,7 +59,7 @@
addmi ip, r2, #4
bmi .Lc2u_0nowords
ldr r3, [r1], #4
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
@@ -88,18 +88,18 @@
stmneia r0!, {r3 - r4} @ Shouldnt fault
tst ip, #4
ldrne r3, [r1], #4
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_0fupi
.Lc2u_0nowords: teq ip, #0
beq .Lc2u_finished
.Lc2u_nowords: cmp ip, #2
ldrb r3, [r1], #1
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #1
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_not_enough:
@@ -120,7 +120,7 @@
mov r3, r7, pull #8
ldr r7, [r1], #4
orr r3, r3, r7, push #24
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
@@ -155,18 +155,18 @@
movne r3, r7, pull #8
ldrne r7, [r1], #4
orrne r3, r3, r7, push #24
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_1fupi
.Lc2u_1nowords: mov r3, r7, get_byte_1
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_2
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
movgt r3, r7, get_byte_3
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_2fupi: subs r2, r2, #4
@@ -175,7 +175,7 @@
mov r3, r7, pull #16
ldr r7, [r1], #4
orr r3, r3, r7, push #16
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
@@ -210,18 +210,18 @@
movne r3, r7, pull #16
ldrne r7, [r1], #4
orrne r3, r3, r7, push #16
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_2fupi
.Lc2u_2nowords: mov r3, r7, get_byte_2
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
movge r3, r7, get_byte_3
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
.Lc2u_3fupi: subs r2, r2, #4
@@ -230,7 +230,7 @@
mov r3, r7, pull #24
ldr r7, [r1], #4
orr r3, r3, r7, push #8
-USER( T(str) r3, [r0], #4) @ May fault
+USER( TUSER( str) r3, [r0], #4) @ May fault
mov ip, r0, lsl #32 - PAGE_SHIFT
rsb ip, ip, #0
movs ip, ip, lsr #32 - PAGE_SHIFT
@@ -265,18 +265,18 @@
movne r3, r7, pull #24
ldrne r7, [r1], #4
orrne r3, r3, r7, push #8
- T(strne) r3, [r0], #4 @ Shouldnt fault
+ TUSER( strne) r3, [r0], #4 @ Shouldnt fault
ands ip, ip, #3
beq .Lc2u_3fupi
.Lc2u_3nowords: mov r3, r7, get_byte_3
teq ip, #0
beq .Lc2u_finished
cmp ip, #2
-USER( T(strb) r3, [r0], #1) @ May fault
+USER( TUSER( strb) r3, [r0], #1) @ May fault
ldrgeb r3, [r1], #1
-USER( T(strgeb) r3, [r0], #1) @ May fault
+USER( TUSER( strgeb) r3, [r0], #1) @ May fault
ldrgtb r3, [r1], #0
-USER( T(strgtb) r3, [r0], #1) @ May fault
+USER( TUSER( strgtb) r3, [r0], #1) @ May fault
b .Lc2u_finished
ENDPROC(__copy_to_user)
@@ -295,11 +295,11 @@
.Lcfu_dest_not_aligned:
rsb ip, ip, #4
cmp ip, #2
-USER( T(ldrb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
sub r2, r2, ip
b .Lcfu_dest_aligned
@@ -322,7 +322,7 @@
.Lcfu_0fupi: subs r2, r2, #4
addmi ip, r2, #4
bmi .Lcfu_0nowords
-USER( T(ldr) r3, [r1], #4)
+USER( TUSER( ldr) r3, [r1], #4)
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT @ On each page, use a ld/st??t instruction
rsb ip, ip, #0
@@ -351,18 +351,18 @@
ldmneia r1!, {r3 - r4} @ Shouldnt fault
stmneia r0!, {r3 - r4}
tst ip, #4
- T(ldrne) r3, [r1], #4 @ Shouldnt fault
+ TUSER( ldrne) r3, [r1], #4 @ Shouldnt fault
strne r3, [r0], #4
ands ip, ip, #3
beq .Lcfu_0fupi
.Lcfu_0nowords: teq ip, #0
beq .Lcfu_finished
.Lcfu_nowords: cmp ip, #2
-USER( T(ldrb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrb) r3, [r1], #1) @ May fault
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
@@ -375,7 +375,7 @@
.Lcfu_src_not_aligned:
bic r1, r1, #3
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
cmp ip, #2
bgt .Lcfu_3fupi
beq .Lcfu_2fupi
@@ -383,7 +383,7 @@
addmi ip, r2, #4
bmi .Lcfu_1nowords
mov r3, r7, pull #8
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #24
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
@@ -418,7 +418,7 @@
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #8
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #24
strne r3, [r0], #4
ands ip, ip, #3
@@ -438,7 +438,7 @@
addmi ip, r2, #4
bmi .Lcfu_2nowords
mov r3, r7, pull #16
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #16
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
@@ -474,7 +474,7 @@
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #16
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #16
strne r3, [r0], #4
ands ip, ip, #3
@@ -486,7 +486,7 @@
strb r3, [r0], #1
movge r3, r7, get_byte_3
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #0) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #0) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
@@ -494,7 +494,7 @@
addmi ip, r2, #4
bmi .Lcfu_3nowords
mov r3, r7, pull #24
-USER( T(ldr) r7, [r1], #4) @ May fault
+USER( TUSER( ldr) r7, [r1], #4) @ May fault
orr r3, r3, r7, push #8
str r3, [r0], #4
mov ip, r1, lsl #32 - PAGE_SHIFT
@@ -529,7 +529,7 @@
stmneia r0!, {r3 - r4}
tst ip, #4
movne r3, r7, pull #24
-USER( T(ldrne) r7, [r1], #4) @ May fault
+USER( TUSER( ldrne) r7, [r1], #4) @ May fault
orrne r3, r3, r7, push #8
strne r3, [r0], #4
ands ip, ip, #3
@@ -539,9 +539,9 @@
beq .Lcfu_finished
cmp ip, #2
strb r3, [r0], #1
-USER( T(ldrgeb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgeb) r3, [r1], #1) @ May fault
strgeb r3, [r0], #1
-USER( T(ldrgtb) r3, [r1], #1) @ May fault
+USER( TUSER( ldrgtb) r3, [r1], #1) @ May fault
strgtb r3, [r0], #1
b .Lcfu_finished
ENDPROC(__copy_from_user)
diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 4f991f2..71feb00 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -18,6 +18,12 @@
config HAVE_AT91_USART5
bool
+config AT91_SAM9_ALT_RESET
+ bool
+
+config AT91_SAM9G45_RESET
+ bool
+
menu "Atmel AT91 System-on-Chip"
choice
@@ -39,6 +45,7 @@
select HAVE_AT91_USART4
select HAVE_AT91_USART5
select HAVE_NET_MACB
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9261
bool "AT91SAM9261"
@@ -46,6 +53,7 @@
select GENERIC_CLOCKEVENTS
select HAVE_FB_ATMEL
select HAVE_AT91_DBGU0
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G10
bool "AT91SAM9G10"
@@ -53,6 +61,7 @@
select GENERIC_CLOCKEVENTS
select HAVE_AT91_DBGU0
select HAVE_FB_ATMEL
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9263
bool "AT91SAM9263"
@@ -61,6 +70,7 @@
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9RL
bool "AT91SAM9RL"
@@ -69,6 +79,7 @@
select HAVE_AT91_USART3
select HAVE_FB_ATMEL
select HAVE_AT91_DBGU0
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G20
bool "AT91SAM9G20"
@@ -79,6 +90,7 @@
select HAVE_AT91_USART4
select HAVE_AT91_USART5
select HAVE_NET_MACB
+ select AT91_SAM9_ALT_RESET
config ARCH_AT91SAM9G45
bool "AT91SAM9G45"
@@ -88,6 +100,7 @@
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9G45_RESET
config ARCH_AT91CAP9
bool "AT91CAP9"
@@ -96,6 +109,7 @@
select HAVE_FB_ATMEL
select HAVE_NET_MACB
select HAVE_AT91_DBGU1
+ select AT91_SAM9G45_RESET
config ARCH_AT91X40
bool "AT91x40"
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 242174f..705e1fb 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -8,15 +8,17 @@
obj- :=
obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
+obj-$(CONFIG_AT91_SAM9_ALT_RESET) += at91sam9_alt_reset.o
+obj-$(CONFIG_AT91_SAM9G45_RESET) += at91sam9g45_reset.o
# CPU-specific support
obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o
-obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o
diff --git a/arch/arm/mach-at91/at91cap9.c b/arch/arm/mach-at91/at91cap9.c
index edb879a..a42edc2 100644
--- a/arch/arm/mach-at91/at91cap9.c
+++ b/arch/arm/mach-at91/at91cap9.c
@@ -21,7 +21,6 @@
#include <mach/cpu.h>
#include <mach/at91cap9.h>
#include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
#include "soc.h"
#include "generic.h"
@@ -314,11 +313,6 @@
}
};
-static void at91cap9_restart(char mode, const char *cmd)
-{
- at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
/* --------------------------------------------------------------------
* AT91CAP9 processor initialization
* -------------------------------------------------------------------- */
@@ -331,13 +325,14 @@
static void __init at91cap9_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91CAP9_BASE_SHDWC);
+ at91_ioremap_rstc(AT91CAP9_BASE_RSTC);
at91sam926x_ioremap_pit(AT91CAP9_BASE_PIT);
at91sam9_ioremap_smc(0, AT91CAP9_BASE_SMC);
}
static void __init at91cap9_initialize(void)
{
- arm_pm_restart = at91cap9_restart;
+ arm_pm_restart = at91sam9g45_restart;
at91_extern_irq = (1 << AT91CAP9_ID_IRQ0) | (1 << AT91CAP9_ID_IRQ1);
/* Register GPIO subsystem */
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 5e46e4a..d4036ba 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -323,6 +323,7 @@
static void __init at91sam9260_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9260_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9260_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
}
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index b85b9ea..023c2ff 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -281,6 +281,7 @@
static void __init at91sam9261_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9261_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9261_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
}
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c
index 79e3669..75e876c 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -301,6 +301,7 @@
static void __init at91sam9263_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9263_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9263_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9263_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
index d3f931c..518e423 100644
--- a/arch/arm/mach-at91/at91sam9_alt_reset.S
+++ b/arch/arm/mach-at91/at91sam9_alt_reset.S
@@ -23,7 +23,8 @@
.globl at91sam9_alt_restart
at91sam9_alt_restart: ldr r0, .at91_va_base_sdramc @ preload constants
- ldr r1, .at91_va_base_rstc_cr
+ ldr r1, =at91_rstc_base
+ ldr r1, [r1]
mov r2, #1
mov r3, #AT91_SDRAMC_LPCB_POWER_DOWN
@@ -33,11 +34,9 @@
str r2, [r0, #AT91_SDRAMC_TR] @ disable SDRAM access
str r3, [r0, #AT91_SDRAMC_LPR] @ power down SDRAM
- str r4, [r1] @ reset processor
+ str r4, [r1, #AT91_RSTC_CR] @ reset processor
b .
.at91_va_base_sdramc:
.word AT91_VA_BASE_SYS + AT91_SDRAMC0
-.at91_va_base_rstc_cr:
- .word AT91_VA_BASE_SYS + AT91_RSTC_CR
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 7032dd3..1cb6a96 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -18,7 +18,6 @@
#include <asm/mach/map.h>
#include <mach/at91sam9g45.h>
#include <mach/at91_pmc.h>
-#include <mach/at91_rstc.h>
#include <mach/cpu.h>
#include "soc.h"
@@ -318,11 +317,6 @@
}
};
-static void at91sam9g45_restart(char mode, const char *cmd)
-{
- at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
/* --------------------------------------------------------------------
* AT91SAM9G45 processor initialization
* -------------------------------------------------------------------- */
@@ -336,6 +330,7 @@
static void __init at91sam9g45_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9G45_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9G45_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
}
diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S
new file mode 100644
index 0000000..0468be1
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam9g45_reset.S
@@ -0,0 +1,40 @@
+/*
+ * reset AT91SAM9G45 as per errata
+ *
+ * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcosoft.com>
+ *
+ * unless the SDRAM is cleanly shutdown before we hit the
+ * reset register it can be left driving the data bus and
+ * killing the chance of a subsequent boot from NAND
+ *
+ * GPLv2 Only
+ */
+
+#include <linux/linkage.h>
+#include <mach/hardware.h>
+#include <mach/at91sam9_ddrsdr.h>
+#include <mach/at91_rstc.h>
+
+ .arm
+
+ .globl at91sam9g45_restart
+
+at91sam9g45_restart:
+ ldr r0, .at91_va_base_sdramc0 @ preload constants
+ ldr r1, =at91_rstc_base
+ ldr r1, [r1]
+
+ mov r2, #1
+ mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN
+ ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
+
+ .balign 32 @ align to cache line
+
+ str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access
+ str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0
+ str r4, [r1, #AT91_RSTC_CR] @ reset processor
+
+ b .
+
+.at91_va_base_sdramc0:
+ .word AT91_VA_BASE_SYS + AT91_DDRSDRC0
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index d6bcb1d..d2c91a8 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -286,6 +286,7 @@
static void __init at91sam9rl_ioremap_registers(void)
{
at91_ioremap_shdwc(AT91SAM9RL_BASE_SHDWC);
+ at91_ioremap_rstc(AT91SAM9RL_BASE_RSTC);
at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
}
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 4866b81..5941334 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -58,7 +58,9 @@
extern void at91_irq_resume(void);
/* reset */
+extern void at91_ioremap_rstc(u32 base_addr);
extern void at91sam9_alt_restart(char, const char *);
+extern void at91sam9g45_restart(char, const char *);
/* shutdown */
extern void at91_ioremap_shdwc(u32 base_addr);
diff --git a/arch/arm/mach-at91/include/mach/at91_rstc.h b/arch/arm/mach-at91/include/mach/at91_rstc.h
index cbd2bf0..875fa33 100644
--- a/arch/arm/mach-at91/include/mach/at91_rstc.h
+++ b/arch/arm/mach-at91/include/mach/at91_rstc.h
@@ -16,13 +16,25 @@
#ifndef AT91_RSTC_H
#define AT91_RSTC_H
-#define AT91_RSTC_CR (AT91_RSTC + 0x00) /* Reset Controller Control Register */
+#ifndef __ASSEMBLY__
+extern void __iomem *at91_rstc_base;
+
+#define at91_rstc_read(field) \
+ __raw_readl(at91_rstc_base + field)
+
+#define at91_rstc_write(field, value) \
+ __raw_writel(value, at91_rstc_base + field);
+#else
+.extern at91_rstc_base
+#endif
+
+#define AT91_RSTC_CR 0x00 /* Reset Controller Control Register */
#define AT91_RSTC_PROCRST (1 << 0) /* Processor Reset */
#define AT91_RSTC_PERRST (1 << 2) /* Peripheral Reset */
#define AT91_RSTC_EXTRST (1 << 3) /* External Reset */
#define AT91_RSTC_KEY (0xa5 << 24) /* KEY Password */
-#define AT91_RSTC_SR (AT91_RSTC + 0x04) /* Reset Controller Status Register */
+#define AT91_RSTC_SR 0x04 /* Reset Controller Status Register */
#define AT91_RSTC_URSTS (1 << 0) /* User Reset Status */
#define AT91_RSTC_RSTTYP (7 << 8) /* Reset Type */
#define AT91_RSTC_RSTTYP_GENERAL (0 << 8)
@@ -33,7 +45,7 @@
#define AT91_RSTC_NRSTL (1 << 16) /* NRST Pin Level */
#define AT91_RSTC_SRCMP (1 << 17) /* Software Reset Command in Progress */
-#define AT91_RSTC_MR (AT91_RSTC + 0x08) /* Reset Controller Mode Register */
+#define AT91_RSTC_MR 0x08 /* Reset Controller Mode Register */
#define AT91_RSTC_URSTEN (1 << 0) /* User Reset Enable */
#define AT91_RSTC_URSTIEN (1 << 4) /* User Reset Interrupt Enable */
#define AT91_RSTC_ERSTL (0xf << 8) /* External Reset Length */
diff --git a/arch/arm/mach-at91/include/mach/at91cap9.h b/arch/arm/mach-at91/include/mach/at91cap9.h
index 4c0e2f6..61d9529 100644
--- a/arch/arm/mach-at91/include/mach/at91cap9.h
+++ b/arch/arm/mach-at91/include/mach/at91cap9.h
@@ -83,7 +83,6 @@
#define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (cpu_is_at91cap9_revB() ? \
(0xfffffd50 - AT91_BASE_SYS) : \
(0xfffffd60 - AT91_BASE_SYS))
@@ -96,6 +95,7 @@
#define AT91CAP9_BASE_PIOB 0xfffff400
#define AT91CAP9_BASE_PIOC 0xfffff600
#define AT91CAP9_BASE_PIOD 0xfffff800
+#define AT91CAP9_BASE_RSTC 0xfffffd00
#define AT91CAP9_BASE_SHDWC 0xfffffd10
#define AT91CAP9_BASE_RTT 0xfffffd20
#define AT91CAP9_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
deleted file mode 100644
index 976f4a6..0000000
--- a/arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91cap9_ddrsdr.h
- *
- * (C) 2008 Andrew Victor
- *
- * DDR/SDR Controller (DDRSDRC) - System peripherals registers.
- * Based on AT91CAP9 datasheet revision B.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91CAP9_DDRSDR_H
-#define AT91CAP9_DDRSDR_H
-
-#define AT91_DDRSDRC_MR 0x00 /* Mode Register */
-#define AT91_DDRSDRC_MODE (0xf << 0) /* Command Mode */
-#define AT91_DDRSDRC_MODE_NORMAL 0
-#define AT91_DDRSDRC_MODE_NOP 1
-#define AT91_DDRSDRC_MODE_PRECHARGE 2
-#define AT91_DDRSDRC_MODE_LMR 3
-#define AT91_DDRSDRC_MODE_REFRESH 4
-#define AT91_DDRSDRC_MODE_EXT_LMR 5
-#define AT91_DDRSDRC_MODE_DEEP 6
-
-#define AT91_DDRSDRC_RTR 0x04 /* Refresh Timer Register */
-#define AT91_DDRSDRC_COUNT (0xfff << 0) /* Refresh Timer Counter */
-
-#define AT91_DDRSDRC_CR 0x08 /* Configuration Register */
-#define AT91_DDRSDRC_NC (3 << 0) /* Number of Column Bits */
-#define AT91_DDRSDRC_NC_SDR8 (0 << 0)
-#define AT91_DDRSDRC_NC_SDR9 (1 << 0)
-#define AT91_DDRSDRC_NC_SDR10 (2 << 0)
-#define AT91_DDRSDRC_NC_SDR11 (3 << 0)
-#define AT91_DDRSDRC_NC_DDR9 (0 << 0)
-#define AT91_DDRSDRC_NC_DDR10 (1 << 0)
-#define AT91_DDRSDRC_NC_DDR11 (2 << 0)
-#define AT91_DDRSDRC_NC_DDR12 (3 << 0)
-#define AT91_DDRSDRC_NR (3 << 2) /* Number of Row Bits */
-#define AT91_DDRSDRC_NR_11 (0 << 2)
-#define AT91_DDRSDRC_NR_12 (1 << 2)
-#define AT91_DDRSDRC_NR_13 (2 << 2)
-#define AT91_DDRSDRC_CAS (7 << 4) /* CAS Latency */
-#define AT91_DDRSDRC_CAS_2 (2 << 4)
-#define AT91_DDRSDRC_CAS_3 (3 << 4)
-#define AT91_DDRSDRC_CAS_25 (6 << 4)
-#define AT91_DDRSDRC_DLL (1 << 7) /* Reset DLL */
-#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */
-
-#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */
-#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */
-#define AT91_DDRSDRC_TRCD (0xf << 4) /* Row to Column delay */
-#define AT91_DDRSDRC_TWR (0xf << 8) /* Write recovery delay */
-#define AT91_DDRSDRC_TRC (0xf << 12) /* Row cycle delay */
-#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */
-#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */
-#define AT91_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */
-#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */
-
-#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */
-#define AT91_DDRSDRC_TRFC (0x1f << 0) /* Row Cycle Delay */
-#define AT91_DDRSDRC_TXSNR (0xff << 8) /* Exit self-refresh to non-read */
-#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */
-#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */
-
-#define AT91_DDRSDRC_LPR 0x18 /* Low Power Register */
-#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */
-#define AT91_DDRSDRC_LPCB_DISABLE 0
-#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1
-#define AT91_DDRSDRC_LPCB_POWER_DOWN 2
-#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3
-#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */
-#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */
-#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */
-#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */
-#define AT91_DDRSDRC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */
-#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES (0 << 12)
-#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES (1 << 12)
-#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES (2 << 12)
-
-#define AT91_DDRSDRC_MDR 0x1C /* Memory Device Register */
-#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
-#define AT91_DDRSDRC_MD_SDR 0
-#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
-#define AT91_DDRSDRC_MD_DDR 2
-#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
-
-#define AT91_DDRSDRC_DLLR 0x20 /* DLL Information Register */
-#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */
-#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */
-#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */
-#define AT91_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */
-#define AT91_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */
-#define AT91_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */
-#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */
-#define AT91_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */
-#define AT91_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */
-
-/* Register access macros */
-#define at91_ramc_read(num, reg) \
- at91_sys_read(AT91_DDRSDRC##num + reg)
-#define at91_ramc_write(num, reg, value) \
- at91_sys_write(AT91_DDRSDRC##num + reg, value)
-
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
index f937c47..fa5ca27 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9260.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
@@ -83,7 +83,6 @@
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
#define AT91SAM9260_BASE_ECC 0xffffe800
@@ -92,6 +91,7 @@
#define AT91SAM9260_BASE_PIOA 0xfffff400
#define AT91SAM9260_BASE_PIOB 0xfffff600
#define AT91SAM9260_BASE_PIOC 0xfffff800
+#define AT91SAM9260_BASE_RSTC 0xfffffd00
#define AT91SAM9260_BASE_SHDWC 0xfffffd10
#define AT91SAM9260_BASE_RTT 0xfffffd20
#define AT91SAM9260_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
index 175604e..7cde2d3 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9261.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
@@ -68,7 +68,6 @@
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
#define AT91SAM9261_BASE_SMC 0xffffec00
@@ -76,6 +75,7 @@
#define AT91SAM9261_BASE_PIOA 0xfffff400
#define AT91SAM9261_BASE_PIOB 0xfffff600
#define AT91SAM9261_BASE_PIOC 0xfffff800
+#define AT91SAM9261_BASE_RSTC 0xfffffd00
#define AT91SAM9261_BASE_SHDWC 0xfffffd10
#define AT91SAM9261_BASE_RTT 0xfffffd20
#define AT91SAM9261_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
index 80c9150..5949abd 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9263.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
@@ -78,7 +78,6 @@
#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91SAM9263_BASE_ECC0 0xffffe000
@@ -91,6 +90,7 @@
#define AT91SAM9263_BASE_PIOC 0xfffff600
#define AT91SAM9263_BASE_PIOD 0xfffff800
#define AT91SAM9263_BASE_PIOE 0xfffffa00
+#define AT91SAM9263_BASE_RSTC 0xfffffd00
#define AT91SAM9263_BASE_SHDWC 0xfffffd10
#define AT91SAM9263_BASE_RTT0 0xfffffd20
#define AT91SAM9263_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h
index d27b15b..e2f8da8 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h
@@ -46,10 +46,10 @@
#define AT91_DDRSDRC_CAS_25 (6 << 4)
#define AT91_DDRSDRC_RST_DLL (1 << 7) /* Reset DLL */
#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */
-#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL */
-#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver */
-#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared */
-#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y */
+#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL [SAM9 Only] */
+#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver [SAM9 Only] */
+#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared [SAM9 Only] */
+#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */
#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */
#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */
@@ -59,7 +59,8 @@
#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */
#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */
#define AT91_DDRSDRC_TWTR (0x7 << 24) /* Internal Write to Read delay */
-#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay */
+#define AT91CAP9_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */
+#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay [SAM9 Only] */
#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */
#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */
@@ -68,13 +69,14 @@
#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */
#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */
-#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register */
+#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register [SAM9 Only] */
#define AT91_DDRSDRC_TXARD (0xf << 0) /* Exit active power down delay to read command in mode "Fast Exit" */
#define AT91_DDRSDRC_TXARDS (0xf << 4) /* Exit active power down delay to read command in mode "Slow Exit" */
#define AT91_DDRSDRC_TRPA (0xf << 8) /* Row Precharge All delay */
#define AT91_DDRSDRC_TRTP (0x7 << 12) /* Read to Precharge delay */
#define AT91_DDRSDRC_LPR 0x1C /* Low Power Register */
+#define AT91CAP9_DDRSDRC_LPR 0x18 /* Low Power Register */
#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */
#define AT91_DDRSDRC_LPCB_DISABLE 0
#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1
@@ -92,32 +94,40 @@
#define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */
#define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */
+#define AT91CAP9_DDRSDRC_MDR 0x1C /* Memory Device Register */
#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */
#define AT91_DDRSDRC_MD_SDR 0
#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1
+#define AT91CAP9_DDRSDRC_MD_DDR 2
#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3
-#define AT91_DDRSDRC_MD_DDR2 6
+#define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */
#define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */
#define AT91_DDRSDRC_DBW_32BITS (0 << 4)
#define AT91_DDRSDRC_DBW_16BITS (1 << 4)
#define AT91_DDRSDRC_DLL 0x24 /* DLL Information Register */
+#define AT91CAP9_DDRSDRC_DLL 0x20 /* DLL Information Register */
#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */
#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */
#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */
+#define AT91CAP9_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */
+#define AT91CAP9_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */
+#define AT91CAP9_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */
#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */
+#define AT91CAP9_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */
+#define AT91CAP9_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */
-#define AT91_DDRSDRC_HS 0x2C /* High Speed Register */
+#define AT91_DDRSDRC_HS 0x2C /* High Speed Register [SAM9 Only] */
#define AT91_DDRSDRC_DIS_ATCP_RD (1 << 2) /* Anticip read access is disabled */
#define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) /* Delay I/O Register n */
-#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register */
+#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register [SAM9 Only] */
#define AT91_DDRSDRC_WP (1 << 0) /* Write protect enable */
#define AT91_DDRSDRC_WPKEY (0xffffff << 8) /* Write protect key */
#define AT91_DDRSDRC_KEY (0x444452 << 8) /* Write protect key = "DDR" */
-#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register */
+#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register [SAM9 Only] */
#define AT91_DDRSDRC_WPVS (1 << 0) /* Write protect violation status */
#define AT91_DDRSDRC_WPVSRC (0xffff << 8) /* Write protect violation source */
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index f0c23c9..dd9c95e 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -90,7 +90,6 @@
#define AT91_DDRSDRC0 (0xffffe600 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffea00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91SAM9G45_BASE_ECC 0xffffe200
@@ -102,6 +101,7 @@
#define AT91SAM9G45_BASE_PIOC 0xfffff600
#define AT91SAM9G45_BASE_PIOD 0xfffff800
#define AT91SAM9G45_BASE_PIOE 0xfffffa00
+#define AT91SAM9G45_BASE_RSTC 0xfffffd00
#define AT91SAM9G45_BASE_SHDWC 0xfffffd10
#define AT91SAM9G45_BASE_RTT 0xfffffd20
#define AT91SAM9G45_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/at91sam9rl.h b/arch/arm/mach-at91/include/mach/at91sam9rl.h
index 2bb359e..d7bead7 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9rl.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9rl.h
@@ -72,7 +72,6 @@
#define AT91_SDRAMC0 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
-#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SCKCR (0xfffffd50 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
@@ -84,6 +83,7 @@
#define AT91SAM9RL_BASE_PIOB 0xfffff600
#define AT91SAM9RL_BASE_PIOC 0xfffff800
#define AT91SAM9RL_BASE_PIOD 0xfffffa00
+#define AT91SAM9RL_BASE_RSTC 0xfffffd00
#define AT91SAM9RL_BASE_SHDWC 0xfffffd10
#define AT91SAM9RL_BASE_RTT 0xfffffd20
#define AT91SAM9RL_BASE_PIT 0xfffffd30
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index d0b377b..3b33f07 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -88,7 +88,7 @@
struct at91_usbh_data {
u8 ports; /* number of ports on root hub */
int vbus_pin[2]; /* port power-control pin */
- u8 vbus_pin_inverted;
+ u8 vbus_pin_active_low[2];
u8 overcurrent_supported;
int overcurrent_pin[2];
u8 overcurrent_status[2];
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 62ad955..1606379 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -34,7 +34,6 @@
/*
* Show the reason for the previous system reset.
*/
-#if defined(AT91_RSTC)
#include <mach/at91_rstc.h>
#include <mach/at91_shdwc.h>
@@ -58,10 +57,10 @@
char *reason, *r2 = reset;
u32 reset_type, wake_type;
- if (!at91_shdwc_base)
+ if (!at91_shdwc_base || !at91_rstc_base)
return;
- reset_type = at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
+ reset_type = at91_rstc_read(AT91_RSTC_SR) & AT91_RSTC_RSTTYP;
wake_type = at91_shdwc_read(AT91_SHDW_SR);
switch (reset_type) {
@@ -102,10 +101,6 @@
}
pr_info("AT91: Starting after %s %s\n", reason, r2);
}
-#else
-static void __init show_reset_status(void) {}
-#endif
-
static int at91_pm_valid_state(suspend_state_t state)
{
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index ce9a206..7eb40d2 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -25,21 +25,21 @@
: : "r" (0))
#elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
+#include <mach/at91sam9_ddrsdr.h>
static inline u32 sdram_selfrefresh_enable(void)
{
u32 saved_lpr, lpr;
- saved_lpr = at91_ramc_read(0, AT91_DDRSDRC_LPR);
+ saved_lpr = at91_ramc_read(0, AT91CAP9_DDRSDRC_LPR);
lpr = saved_lpr & ~AT91_DDRSDRC_LPCB;
- at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
+ at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, lpr | AT91_DDRSDRC_LPCB_SELF_REFRESH);
return saved_lpr;
}
-#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr)
+#define sdram_selfrefresh_disable(saved_lpr) at91_ramc_write(0, AT91CAP9_DDRSDRC_LPR, saved_lpr)
#define wait_for_interrupt_enable() cpu_do_idle()
#elif defined(CONFIG_ARCH_AT91SAM9G45)
diff --git a/arch/arm/mach-at91/pm_slowclock.S b/arch/arm/mach-at91/pm_slowclock.S
index f7922a4..92dfb84 100644
--- a/arch/arm/mach-at91/pm_slowclock.S
+++ b/arch/arm/mach-at91/pm_slowclock.S
@@ -18,9 +18,8 @@
#if defined(CONFIG_ARCH_AT91RM9200)
#include <mach/at91rm9200_mc.h>
-#elif defined(CONFIG_ARCH_AT91CAP9)
-#include <mach/at91cap9_ddrsdr.h>
-#elif defined(CONFIG_ARCH_AT91SAM9G45)
+#elif defined(CONFIG_ARCH_AT91CAP9) \
+ || defined(CONFIG_ARCH_AT91SAM9G45)
#include <mach/at91sam9_ddrsdr.h>
#else
#include <mach/at91sam9_sdramc.h>
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 8bdcc3c..69d3fc4 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -29,9 +29,12 @@
void __init at91rm9200_set_type(int type)
{
if (type == ARCH_REVISON_9200_PQFP)
- at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
- else
at91_soc_initdata.subtype = AT91_SOC_RM9200_PQFP;
+ else
+ at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
+
+ pr_info("AT91: filled in soc subtype: %s\n",
+ at91_get_soc_subtype(&at91_soc_initdata));
}
void __init at91_init_irq_default(void)
@@ -281,6 +284,15 @@
pm_power_off = at91sam9_poweroff;
}
+void __iomem *at91_rstc_base;
+
+void __init at91_ioremap_rstc(u32 base_addr)
+{
+ at91_rstc_base = ioremap(base_addr, 16);
+ if (!at91_rstc_base)
+ panic("Impossible to ioremap at91_rstc_base\n");
+}
+
void __init at91_initialize(unsigned long main_clock)
{
at91_boot_soc.ioremap_registers();
diff --git a/arch/arm/mach-bcmring/arch.c b/arch/arm/mach-bcmring/arch.c
index 9e5e755..45c97b1 100644
--- a/arch/arm/mach-bcmring/arch.c
+++ b/arch/arm/mach-bcmring/arch.c
@@ -194,6 +194,6 @@
.init_early = bcmring_init_early,
.init_irq = bcmring_init_irq,
.timer = &bcmring_timer,
- .init_machine = bcmring_init_machine
+ .init_machine = bcmring_init_machine,
.restart = bcmring_restart,
MACHINE_END
diff --git a/arch/arm/mach-bcmring/dma.c b/arch/arm/mach-bcmring/dma.c
index 1a1a27d..1024396 100644
--- a/arch/arm/mach-bcmring/dma.c
+++ b/arch/arm/mach-bcmring/dma.c
@@ -33,17 +33,11 @@
#include <mach/timer.h>
-#include <linux/mm.h>
#include <linux/pfn.h>
#include <linux/atomic.h>
#include <linux/sched.h>
#include <mach/dma.h>
-/* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
-/* especially since dc4 doesn't use kmalloc'd memory. */
-
-#define ALLOW_MAP_OF_KMALLOC_MEMORY 0
-
/* ---- Public Variables ------------------------------------------------- */
/* ---- Private Constants and Types -------------------------------------- */
@@ -53,24 +47,12 @@
#define CONTROLLER_FROM_HANDLE(handle) (((handle) >> 4) & 0x0f)
#define CHANNEL_FROM_HANDLE(handle) ((handle) & 0x0f)
-#define DMA_MAP_DEBUG 0
-
-#if DMA_MAP_DEBUG
-# define DMA_MAP_PRINT(fmt, args...) printk("%s: " fmt, __func__, ## args)
-#else
-# define DMA_MAP_PRINT(fmt, args...)
-#endif
/* ---- Private Variables ------------------------------------------------ */
static DMA_Global_t gDMA;
static struct proc_dir_entry *gDmaDir;
-static atomic_t gDmaStatMemTypeKmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeVmalloc = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeUser = ATOMIC_INIT(0);
-static atomic_t gDmaStatMemTypeCoherent = ATOMIC_INIT(0);
-
#include "dma_device.c"
/* ---- Private Function Prototypes -------------------------------------- */
@@ -79,34 +61,6 @@
/****************************************************************************/
/**
-* Displays information for /proc/dma/mem-type
-*/
-/****************************************************************************/
-
-static int dma_proc_read_mem_type(char *buf, char **start, off_t offset,
- int count, int *eof, void *data)
-{
- int len = 0;
-
- len += sprintf(buf + len, "dma_map_mem statistics\n");
- len +=
- sprintf(buf + len, "coherent: %d\n",
- atomic_read(&gDmaStatMemTypeCoherent));
- len +=
- sprintf(buf + len, "kmalloc: %d\n",
- atomic_read(&gDmaStatMemTypeKmalloc));
- len +=
- sprintf(buf + len, "vmalloc: %d\n",
- atomic_read(&gDmaStatMemTypeVmalloc));
- len +=
- sprintf(buf + len, "user: %d\n",
- atomic_read(&gDmaStatMemTypeUser));
-
- return len;
-}
-
-/****************************************************************************/
-/**
* Displays information for /proc/dma/channels
*/
/****************************************************************************/
@@ -846,8 +800,6 @@
dma_proc_read_channels, NULL);
create_proc_read_entry("devices", 0, gDmaDir,
dma_proc_read_devices, NULL);
- create_proc_read_entry("mem-type", 0, gDmaDir,
- dma_proc_read_mem_type, NULL);
}
out:
@@ -1565,767 +1517,3 @@
}
EXPORT_SYMBOL(dma_set_device_handler);
-
-/****************************************************************************/
-/**
-* Initializes a memory mapping structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap)
-{
- memset(memMap, 0, sizeof(*memMap));
-
- sema_init(&memMap->lock, 1);
-
- return 0;
-}
-
-EXPORT_SYMBOL(dma_init_mem_map);
-
-/****************************************************************************/
-/**
-* Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap)
-{
- down(&memMap->lock); /* Just being paranoid */
-
- /* Free up any allocated memory */
-
- up(&memMap->lock);
- memset(memMap, 0, sizeof(*memMap));
-
- return 0;
-}
-
-EXPORT_SYMBOL(dma_term_mem_map);
-
-/****************************************************************************/
-/**
-* Looks at a memory address and categorizes it.
-*
-* @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr)
-{
- unsigned long addrVal = (unsigned long)addr;
-
- if (addrVal >= CONSISTENT_BASE) {
- /* NOTE: DMA virtual memory space starts at 0xFFxxxxxx */
-
- /* dma_alloc_xxx pages are physically and virtually contiguous */
-
- return DMA_MEM_TYPE_DMA;
- }
-
- /* Technically, we could add one more classification. Addresses between VMALLOC_END */
- /* and the beginning of the DMA virtual address could be considered to be I/O space. */
- /* Right now, nobody cares about this particular classification, so we ignore it. */
-
- if (is_vmalloc_addr(addr)) {
- /* Address comes from the vmalloc'd region. Pages are virtually */
- /* contiguous but NOT physically contiguous */
-
- return DMA_MEM_TYPE_VMALLOC;
- }
-
- if (addrVal >= PAGE_OFFSET) {
- /* PAGE_OFFSET is typically 0xC0000000 */
-
- /* kmalloc'd pages are physically contiguous */
-
- return DMA_MEM_TYPE_KMALLOC;
- }
-
- return DMA_MEM_TYPE_USER;
-}
-
-EXPORT_SYMBOL(dma_mem_type);
-
-/****************************************************************************/
-/**
-* Looks at a memory address and determines if we support DMA'ing to/from
-* that type of memory.
-*
-* @return boolean -
-* return value != 0 means dma supported
-* return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr)
-{
- DMA_MemType_t memType = dma_mem_type(addr);
-
- return (memType == DMA_MEM_TYPE_DMA)
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- || (memType == DMA_MEM_TYPE_KMALLOC)
-#endif
- || (memType == DMA_MEM_TYPE_USER);
-}
-
-EXPORT_SYMBOL(dma_mem_supports_dma);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- ) {
- int rc;
-
- down(&memMap->lock);
-
- DMA_MAP_PRINT("memMap: %p\n", memMap);
-
- if (memMap->inUse) {
- printk(KERN_ERR "%s: memory map %p is already being used\n",
- __func__, memMap);
- rc = -EBUSY;
- goto out;
- }
-
- memMap->inUse = 1;
- memMap->dir = dir;
- memMap->numRegionsUsed = 0;
-
- rc = 0;
-
-out:
-
- DMA_MAP_PRINT("returning %d", rc);
-
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_start);
-
-/****************************************************************************/
-/**
-* Adds a segment of memory to a memory map. Each segment is both
-* physically and virtually contiguous.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-static int dma_map_add_segment(DMA_MemMap_t *memMap, /* Stores state information about the map */
- DMA_Region_t *region, /* Region that the segment belongs to */
- void *virtAddr, /* Virtual address of the segment being added */
- dma_addr_t physAddr, /* Physical address of the segment being added */
- size_t numBytes /* Number of bytes of the segment being added */
- ) {
- DMA_Segment_t *segment;
-
- DMA_MAP_PRINT("memMap:%p va:%p pa:0x%x #:%d\n", memMap, virtAddr,
- physAddr, numBytes);
-
- /* Sanity check */
-
- if (((unsigned long)virtAddr < (unsigned long)region->virtAddr)
- || (((unsigned long)virtAddr + numBytes)) >
- ((unsigned long)region->virtAddr + region->numBytes)) {
- printk(KERN_ERR
- "%s: virtAddr %p is outside region @ %p len: %d\n",
- __func__, virtAddr, region->virtAddr, region->numBytes);
- return -EINVAL;
- }
-
- if (region->numSegmentsUsed > 0) {
- /* Check to see if this segment is physically contiguous with the previous one */
-
- segment = ®ion->segment[region->numSegmentsUsed - 1];
-
- if ((segment->physAddr + segment->numBytes) == physAddr) {
- /* It is - just add on to the end */
-
- DMA_MAP_PRINT("appending %d bytes to last segment\n",
- numBytes);
-
- segment->numBytes += numBytes;
-
- return 0;
- }
- }
-
- /* Reallocate to hold more segments, if required. */
-
- if (region->numSegmentsUsed >= region->numSegmentsAllocated) {
- DMA_Segment_t *newSegment;
- size_t oldSize =
- region->numSegmentsAllocated * sizeof(*newSegment);
- int newAlloc = region->numSegmentsAllocated + 4;
- size_t newSize = newAlloc * sizeof(*newSegment);
-
- newSegment = kmalloc(newSize, GFP_KERNEL);
- if (newSegment == NULL) {
- return -ENOMEM;
- }
- memcpy(newSegment, region->segment, oldSize);
- memset(&((uint8_t *) newSegment)[oldSize], 0,
- newSize - oldSize);
- kfree(region->segment);
-
- region->numSegmentsAllocated = newAlloc;
- region->segment = newSegment;
- }
-
- segment = ®ion->segment[region->numSegmentsUsed];
- region->numSegmentsUsed++;
-
- segment->virtAddr = virtAddr;
- segment->physAddr = physAddr;
- segment->numBytes = numBytes;
-
- DMA_MAP_PRINT("returning success\n");
-
- return 0;
-}
-
-/****************************************************************************/
-/**
-* Adds a region of memory to a memory map. Each region is virtually
-* contiguous, but not necessarily physically contiguous.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes /* Number of bytes being mapped */
- ) {
- unsigned long addr = (unsigned long)mem;
- unsigned int offset;
- int rc = 0;
- DMA_Region_t *region;
- dma_addr_t physAddr;
-
- down(&memMap->lock);
-
- DMA_MAP_PRINT("memMap:%p va:%p #:%d\n", memMap, mem, numBytes);
-
- if (!memMap->inUse) {
- printk(KERN_ERR "%s: Make sure you call dma_map_start first\n",
- __func__);
- rc = -EINVAL;
- goto out;
- }
-
- /* Reallocate to hold more regions. */
-
- if (memMap->numRegionsUsed >= memMap->numRegionsAllocated) {
- DMA_Region_t *newRegion;
- size_t oldSize =
- memMap->numRegionsAllocated * sizeof(*newRegion);
- int newAlloc = memMap->numRegionsAllocated + 4;
- size_t newSize = newAlloc * sizeof(*newRegion);
-
- newRegion = kmalloc(newSize, GFP_KERNEL);
- if (newRegion == NULL) {
- rc = -ENOMEM;
- goto out;
- }
- memcpy(newRegion, memMap->region, oldSize);
- memset(&((uint8_t *) newRegion)[oldSize], 0, newSize - oldSize);
-
- kfree(memMap->region);
-
- memMap->numRegionsAllocated = newAlloc;
- memMap->region = newRegion;
- }
-
- region = &memMap->region[memMap->numRegionsUsed];
- memMap->numRegionsUsed++;
-
- offset = addr & ~PAGE_MASK;
-
- region->memType = dma_mem_type(mem);
- region->virtAddr = mem;
- region->numBytes = numBytes;
- region->numSegmentsUsed = 0;
- region->numLockedPages = 0;
- region->lockedPages = NULL;
-
- switch (region->memType) {
- case DMA_MEM_TYPE_VMALLOC:
- {
- atomic_inc(&gDmaStatMemTypeVmalloc);
-
- /* printk(KERN_ERR "%s: vmalloc'd pages are not supported\n", __func__); */
-
- /* vmalloc'd pages are not physically contiguous */
-
- rc = -EINVAL;
- break;
- }
-
- case DMA_MEM_TYPE_KMALLOC:
- {
- atomic_inc(&gDmaStatMemTypeKmalloc);
-
- /* kmalloc'd pages are physically contiguous, so they'll have exactly */
- /* one segment */
-
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- physAddr =
- dma_map_single(NULL, mem, numBytes, memMap->dir);
- rc = dma_map_add_segment(memMap, region, mem, physAddr,
- numBytes);
-#else
- rc = -EINVAL;
-#endif
- break;
- }
-
- case DMA_MEM_TYPE_DMA:
- {
- /* dma_alloc_xxx pages are physically contiguous */
-
- atomic_inc(&gDmaStatMemTypeCoherent);
-
- physAddr = (vmalloc_to_pfn(mem) << PAGE_SHIFT) + offset;
-
- dma_sync_single_for_cpu(NULL, physAddr, numBytes,
- memMap->dir);
- rc = dma_map_add_segment(memMap, region, mem, physAddr,
- numBytes);
- break;
- }
-
- case DMA_MEM_TYPE_USER:
- {
- size_t firstPageOffset;
- size_t firstPageSize;
- struct page **pages;
- struct task_struct *userTask;
-
- atomic_inc(&gDmaStatMemTypeUser);
-
-#if 1
- /* If the pages are user pages, then the dma_mem_map_set_user_task function */
- /* must have been previously called. */
-
- if (memMap->userTask == NULL) {
- printk(KERN_ERR
- "%s: must call dma_mem_map_set_user_task when using user-mode memory\n",
- __func__);
- return -EINVAL;
- }
-
- /* User pages need to be locked. */
-
- firstPageOffset =
- (unsigned long)region->virtAddr & (PAGE_SIZE - 1);
- firstPageSize = PAGE_SIZE - firstPageOffset;
-
- region->numLockedPages = (firstPageOffset
- + region->numBytes +
- PAGE_SIZE - 1) / PAGE_SIZE;
- pages =
- kmalloc(region->numLockedPages *
- sizeof(struct page *), GFP_KERNEL);
-
- if (pages == NULL) {
- region->numLockedPages = 0;
- return -ENOMEM;
- }
-
- userTask = memMap->userTask;
-
- down_read(&userTask->mm->mmap_sem);
- rc = get_user_pages(userTask, /* task */
- userTask->mm, /* mm */
- (unsigned long)region->virtAddr, /* start */
- region->numLockedPages, /* len */
- memMap->dir == DMA_FROM_DEVICE, /* write */
- 0, /* force */
- pages, /* pages (array of pointers to page) */
- NULL); /* vmas */
- up_read(&userTask->mm->mmap_sem);
-
- if (rc != region->numLockedPages) {
- kfree(pages);
- region->numLockedPages = 0;
-
- if (rc >= 0) {
- rc = -EINVAL;
- }
- } else {
- uint8_t *virtAddr = region->virtAddr;
- size_t bytesRemaining;
- int pageIdx;
-
- rc = 0; /* Since get_user_pages returns +ve number */
-
- region->lockedPages = pages;
-
- /* We've locked the user pages. Now we need to walk them and figure */
- /* out the physical addresses. */
-
- /* The first page may be partial */
-
- dma_map_add_segment(memMap,
- region,
- virtAddr,
- PFN_PHYS(page_to_pfn
- (pages[0])) +
- firstPageOffset,
- firstPageSize);
-
- virtAddr += firstPageSize;
- bytesRemaining =
- region->numBytes - firstPageSize;
-
- for (pageIdx = 1;
- pageIdx < region->numLockedPages;
- pageIdx++) {
- size_t bytesThisPage =
- (bytesRemaining >
- PAGE_SIZE ? PAGE_SIZE :
- bytesRemaining);
-
- DMA_MAP_PRINT
- ("pageIdx:%d pages[pageIdx]=%p pfn=%u phys=%u\n",
- pageIdx, pages[pageIdx],
- page_to_pfn(pages[pageIdx]),
- PFN_PHYS(page_to_pfn
- (pages[pageIdx])));
-
- dma_map_add_segment(memMap,
- region,
- virtAddr,
- PFN_PHYS(page_to_pfn
- (pages
- [pageIdx])),
- bytesThisPage);
-
- virtAddr += bytesThisPage;
- bytesRemaining -= bytesThisPage;
- }
- }
-#else
- printk(KERN_ERR
- "%s: User mode pages are not yet supported\n",
- __func__);
-
- /* user pages are not physically contiguous */
-
- rc = -EINVAL;
-#endif
- break;
- }
-
- default:
- {
- printk(KERN_ERR "%s: Unsupported memory type: %d\n",
- __func__, region->memType);
-
- rc = -EINVAL;
- break;
- }
- }
-
- if (rc != 0) {
- memMap->numRegionsUsed--;
- }
-
-out:
-
- DMA_MAP_PRINT("returning %d\n", rc);
-
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_add_segment);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes, /* Number of bytes being mapped */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- ) {
- int rc;
-
- rc = dma_map_start(memMap, dir);
- if (rc == 0) {
- rc = dma_map_add_region(memMap, mem, numBytes);
- if (rc < 0) {
- /* Since the add fails, this function will fail, and the caller won't */
- /* call unmap, so we need to do it here. */
-
- dma_unmap(memMap, 0);
- }
- }
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_mem);
-
-/****************************************************************************/
-/**
-* Setup a descriptor ring for a given memory map.
-*
-* It is assumed that the descriptor ring has already been initialized, and
-* this routine will only reallocate a new descriptor ring if the existing
-* one is too small.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */
- DMA_MemMap_t *memMap, /* Memory map that will be used */
- dma_addr_t devPhysAddr /* Physical address of device */
- ) {
- int rc;
- int numDescriptors;
- DMA_DeviceAttribute_t *devAttr;
- DMA_Region_t *region;
- DMA_Segment_t *segment;
- dma_addr_t srcPhysAddr;
- dma_addr_t dstPhysAddr;
- int regionIdx;
- int segmentIdx;
-
- devAttr = &DMA_gDeviceAttribute[dev];
-
- down(&memMap->lock);
-
- /* Figure out how many descriptors we need */
-
- numDescriptors = 0;
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = ®ion->segment[segmentIdx];
-
- if (memMap->dir == DMA_TO_DEVICE) {
- srcPhysAddr = segment->physAddr;
- dstPhysAddr = devPhysAddr;
- } else {
- srcPhysAddr = devPhysAddr;
- dstPhysAddr = segment->physAddr;
- }
-
- rc =
- dma_calculate_descriptor_count(dev, srcPhysAddr,
- dstPhysAddr,
- segment->
- numBytes);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_calculate_descriptor_count failed: %d\n",
- __func__, rc);
- goto out;
- }
- numDescriptors += rc;
- }
- }
-
- /* Adjust the size of the ring, if it isn't big enough */
-
- if (numDescriptors > devAttr->ring.descriptorsAllocated) {
- dma_free_descriptor_ring(&devAttr->ring);
- rc =
- dma_alloc_descriptor_ring(&devAttr->ring,
- numDescriptors);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_alloc_descriptor_ring failed: %d\n",
- __func__, rc);
- goto out;
- }
- } else {
- rc =
- dma_init_descriptor_ring(&devAttr->ring,
- numDescriptors);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_init_descriptor_ring failed: %d\n",
- __func__, rc);
- goto out;
- }
- }
-
- /* Populate the descriptors */
-
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = ®ion->segment[segmentIdx];
-
- if (memMap->dir == DMA_TO_DEVICE) {
- srcPhysAddr = segment->physAddr;
- dstPhysAddr = devPhysAddr;
- } else {
- srcPhysAddr = devPhysAddr;
- dstPhysAddr = segment->physAddr;
- }
-
- rc =
- dma_add_descriptors(&devAttr->ring, dev,
- srcPhysAddr, dstPhysAddr,
- segment->numBytes);
- if (rc < 0) {
- printk(KERN_ERR
- "%s: dma_add_descriptors failed: %d\n",
- __func__, rc);
- goto out;
- }
- }
- }
-
- rc = 0;
-
-out:
-
- up(&memMap->lock);
- return rc;
-}
-
-EXPORT_SYMBOL(dma_map_create_descriptor_ring);
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
- int dirtied /* non-zero if any of the pages were modified */
- ) {
-
- int rc = 0;
- int regionIdx;
- int segmentIdx;
- DMA_Region_t *region;
- DMA_Segment_t *segment;
-
- down(&memMap->lock);
-
- for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
- region = &memMap->region[regionIdx];
-
- for (segmentIdx = 0; segmentIdx < region->numSegmentsUsed;
- segmentIdx++) {
- segment = ®ion->segment[segmentIdx];
-
- switch (region->memType) {
- case DMA_MEM_TYPE_VMALLOC:
- {
- printk(KERN_ERR
- "%s: vmalloc'd pages are not yet supported\n",
- __func__);
- rc = -EINVAL;
- goto out;
- }
-
- case DMA_MEM_TYPE_KMALLOC:
- {
-#if ALLOW_MAP_OF_KMALLOC_MEMORY
- dma_unmap_single(NULL,
- segment->physAddr,
- segment->numBytes,
- memMap->dir);
-#endif
- break;
- }
-
- case DMA_MEM_TYPE_DMA:
- {
- dma_sync_single_for_cpu(NULL,
- segment->
- physAddr,
- segment->
- numBytes,
- memMap->dir);
- break;
- }
-
- case DMA_MEM_TYPE_USER:
- {
- /* Nothing to do here. */
-
- break;
- }
-
- default:
- {
- printk(KERN_ERR
- "%s: Unsupported memory type: %d\n",
- __func__, region->memType);
- rc = -EINVAL;
- goto out;
- }
- }
-
- segment->virtAddr = NULL;
- segment->physAddr = 0;
- segment->numBytes = 0;
- }
-
- if (region->numLockedPages > 0) {
- int pageIdx;
-
- /* Some user pages were locked. We need to go and unlock them now. */
-
- for (pageIdx = 0; pageIdx < region->numLockedPages;
- pageIdx++) {
- struct page *page =
- region->lockedPages[pageIdx];
-
- if (memMap->dir == DMA_FROM_DEVICE) {
- SetPageDirty(page);
- }
- page_cache_release(page);
- }
- kfree(region->lockedPages);
- region->numLockedPages = 0;
- region->lockedPages = NULL;
- }
-
- region->memType = DMA_MEM_TYPE_NONE;
- region->virtAddr = NULL;
- region->numBytes = 0;
- region->numSegmentsUsed = 0;
- }
- memMap->userTask = NULL;
- memMap->numRegionsUsed = 0;
- memMap->inUse = 0;
-
-out:
- up(&memMap->lock);
-
- return rc;
-}
-
-EXPORT_SYMBOL(dma_unmap);
diff --git a/arch/arm/mach-bcmring/include/mach/dma.h b/arch/arm/mach-bcmring/include/mach/dma.h
index 1f2c531..7254378 100644
--- a/arch/arm/mach-bcmring/include/mach/dma.h
+++ b/arch/arm/mach-bcmring/include/mach/dma.h
@@ -26,15 +26,9 @@
/* ---- Include Files ---------------------------------------------------- */
#include <linux/kernel.h>
-#include <linux/wait.h>
#include <linux/semaphore.h>
#include <csp/dmacHw.h>
#include <mach/timer.h>
-#include <linux/scatterlist.h>
-#include <linux/dma-mapping.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/pagemap.h>
/* ---- Constants and Types ---------------------------------------------- */
@@ -113,78 +107,6 @@
/****************************************************************************
*
-* The DMA_MemType_t and DMA_MemMap_t are helper structures used to setup
-* DMA chains from a variety of memory sources.
-*
-*****************************************************************************/
-
-#define DMA_MEM_MAP_MIN_SIZE 4096 /* Pages less than this size are better */
- /* off not being DMA'd. */
-
-typedef enum {
- DMA_MEM_TYPE_NONE, /* Not a valid setting */
- DMA_MEM_TYPE_VMALLOC, /* Memory came from vmalloc call */
- DMA_MEM_TYPE_KMALLOC, /* Memory came from kmalloc call */
- DMA_MEM_TYPE_DMA, /* Memory came from dma_alloc_xxx call */
- DMA_MEM_TYPE_USER, /* Memory came from user space. */
-
-} DMA_MemType_t;
-
-/* A segment represents a physically and virtually contiguous chunk of memory. */
-/* i.e. each segment can be DMA'd */
-/* A user of the DMA code will add memory regions. Each region may need to be */
-/* represented by one or more segments. */
-
-typedef struct {
- void *virtAddr; /* Virtual address used for this segment */
- dma_addr_t physAddr; /* Physical address this segment maps to */
- size_t numBytes; /* Size of the segment, in bytes */
-
-} DMA_Segment_t;
-
-/* A region represents a virtually contiguous chunk of memory, which may be */
-/* made up of multiple segments. */
-
-typedef struct {
- DMA_MemType_t memType;
- void *virtAddr;
- size_t numBytes;
-
- /* Each region (virtually contiguous) consists of one or more segments. Each */
- /* segment is virtually and physically contiguous. */
-
- int numSegmentsUsed;
- int numSegmentsAllocated;
- DMA_Segment_t *segment;
-
- /* When a region corresponds to user memory, we need to lock all of the pages */
- /* down before we can figure out the physical addresses. The lockedPage array contains */
- /* the pages that were locked, and which subsequently need to be unlocked once the */
- /* memory is unmapped. */
-
- unsigned numLockedPages;
- struct page **lockedPages;
-
-} DMA_Region_t;
-
-typedef struct {
- int inUse; /* Is this mapping currently being used? */
- struct semaphore lock; /* Acquired when using this structure */
- enum dma_data_direction dir; /* Direction this transfer is intended for */
-
- /* In the event that we're mapping user memory, we need to know which task */
- /* the memory is for, so that we can obtain the correct mm locks. */
-
- struct task_struct *userTask;
-
- int numRegionsUsed;
- int numRegionsAllocated;
- DMA_Region_t *region;
-
-} DMA_MemMap_t;
-
-/****************************************************************************
-*
* The DMA_DeviceAttribute_t contains information which describes a
* particular DMA device (or peripheral).
*
@@ -570,124 +492,6 @@
/****************************************************************************/
/**
-* Initializes a DMA_MemMap_t data structure
-*/
-/****************************************************************************/
-
-int dma_init_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
- );
-
-/****************************************************************************/
-/**
-* Releases any memory currently being held by a memory mapping structure.
-*/
-/****************************************************************************/
-
-int dma_term_mem_map(DMA_MemMap_t *memMap /* Stores state information about the map */
- );
-
-/****************************************************************************/
-/**
-* Looks at a memory address and categorizes it.
-*
-* @return One of the values from the DMA_MemType_t enumeration.
-*/
-/****************************************************************************/
-
-DMA_MemType_t dma_mem_type(void *addr);
-
-/****************************************************************************/
-/**
-* Sets the process (aka userTask) associated with a mem map. This is
-* required if user-mode segments will be added to the mapping.
-*/
-/****************************************************************************/
-
-static inline void dma_mem_map_set_user_task(DMA_MemMap_t *memMap,
- struct task_struct *task)
-{
- memMap->userTask = task;
-}
-
-/****************************************************************************/
-/**
-* Looks at a memory address and determines if we support DMA'ing to/from
-* that type of memory.
-*
-* @return boolean -
-* return value != 0 means dma supported
-* return value == 0 means dma not supported
-*/
-/****************************************************************************/
-
-int dma_mem_supports_dma(void *addr);
-
-/****************************************************************************/
-/**
-* Initializes a memory map for use. Since this function acquires a
-* sempaphore within the memory map, it is VERY important that dma_unmap
-* be called when you're finished using the map.
-*/
-/****************************************************************************/
-
-int dma_map_start(DMA_MemMap_t *memMap, /* Stores state information about the map */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- );
-
-/****************************************************************************/
-/**
-* Adds a segment of memory to a memory map.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_add_region(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *mem, /* Virtual address that we want to get a map of */
- size_t numBytes /* Number of bytes being mapped */
- );
-
-/****************************************************************************/
-/**
-* Creates a descriptor ring from a memory mapping.
-*
-* @return 0 on success, error code otherwise.
-*/
-/****************************************************************************/
-
-int dma_map_create_descriptor_ring(DMA_Device_t dev, /* DMA device (where the ring is stored) */
- DMA_MemMap_t *memMap, /* Memory map that will be used */
- dma_addr_t devPhysAddr /* Physical address of device */
- );
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_map_mem(DMA_MemMap_t *memMap, /* Stores state information about the map */
- void *addr, /* Virtual address that we want to get a map of */
- size_t count, /* Number of bytes being mapped */
- enum dma_data_direction dir /* Direction that the mapping will be going */
- );
-
-/****************************************************************************/
-/**
-* Maps in a memory region such that it can be used for performing a DMA.
-*
-* @return
-*/
-/****************************************************************************/
-
-int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
- int dirtied /* non-zero if any of the pages were modified */
- );
-
-/****************************************************************************/
-/**
* Initiates a transfer when the descriptors have already been setup.
*
* This is a special case, and normally, the dma_transfer_xxx functions should
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 6b22b54..d508890 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -44,7 +44,7 @@
#include <mach/aemif.h>
#include <mach/spi.h>
-#define DA850_EVM_PHY_ID "0:00"
+#define DA850_EVM_PHY_ID "davinci_mdio-0:00"
#define DA850_LCD_PWR_PIN GPIO_TO_PIN(2, 8)
#define DA850_LCD_BL_PIN GPIO_TO_PIN(2, 15)
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 346e1de..849311d 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -54,7 +54,7 @@
return 0;
}
-#define DM365_EVM_PHY_ID "0:01"
+#define DM365_EVM_PHY_ID "davinci_mdio-0:01"
/*
* A MAX-II CPLD is used for various board control functions.
*/
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index a64b49c..1247ecd 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -40,7 +40,7 @@
#include <mach/usb.h>
#include <mach/aemif.h>
-#define DM644X_EVM_PHY_ID "0:01"
+#define DM644X_EVM_PHY_ID "davinci_mdio-0:01"
#define LXT971_PHY_ID (0x001378e2)
#define LXT971_PHY_MASK (0xfffffff0)
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 6401755..872ac69 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -736,7 +736,7 @@
.enabled_uarts = (1 << 0),
};
-#define DM646X_EVM_PHY_ID "0:01"
+#define DM646X_EVM_PHY_ID "davinci_mdio-0:01"
/*
* The following EDMA channels/slots are not being used by drivers (for
* example: Timer, GPIO, UART events etc) on dm646x, hence they are being
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 6c4a164..8d34f51 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -39,7 +39,7 @@
#include <mach/mmc.h>
#include <mach/usb.h>
-#define NEUROS_OSD2_PHY_ID "0:01"
+#define NEUROS_OSD2_PHY_ID "davinci_mdio-0:01"
#define LXT971_PHY_ID 0x001378e2
#define LXT971_PHY_MASK 0xfffffff0
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index e7c0c7c..45e8157 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -21,7 +21,7 @@
#include <mach/da8xx.h>
#include <mach/mux.h>
-#define HAWKBOARD_PHY_ID "0:07"
+#define HAWKBOARD_PHY_ID "davinci_mdio-0:07"
#define DA850_HAWK_MMCSD_CD_PIN GPIO_TO_PIN(3, 12)
#define DA850_HAWK_MMCSD_WP_PIN GPIO_TO_PIN(3, 13)
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 0b136a8..31da3c5 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -42,7 +42,7 @@
#include <mach/mux.h>
#include <mach/usb.h>
-#define SFFSDR_PHY_ID "0:01"
+#define SFFSDR_PHY_ID "davinci_mdio-0:01"
static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
/* U-Boot Environment: Block 0
* UBL: Block 1
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 0ed7fdb..992c4c4 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -153,34 +153,6 @@
.div_reg = PLLDIV3,
};
-static struct clk pll1_sysclk4 = {
- .name = "pll1_sysclk4",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV4,
-};
-
-static struct clk pll1_sysclk5 = {
- .name = "pll1_sysclk5",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV5,
-};
-
-static struct clk pll1_sysclk6 = {
- .name = "pll0_sysclk6",
- .parent = &pll0_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV6,
-};
-
-static struct clk pll1_sysclk7 = {
- .name = "pll1_sysclk7",
- .parent = &pll1_clk,
- .flags = CLK_PLL,
- .div_reg = PLLDIV7,
-};
-
static struct clk i2c0_clk = {
.name = "i2c0",
.parent = &pll0_aux_clk,
@@ -397,10 +369,6 @@
CLK(NULL, "pll1_aux", &pll1_aux_clk),
CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
- CLK(NULL, "pll1_sysclk4", &pll1_sysclk4),
- CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
- CLK(NULL, "pll1_sysclk6", &pll1_sysclk6),
- CLK(NULL, "pll1_sysclk7", &pll1_sysclk7),
CLK("i2c_davinci.1", NULL, &i2c0_clk),
CLK(NULL, "timer0", &timerp64_0_clk),
CLK("watchdog", NULL, &timerp64_1_clk),
diff --git a/arch/arm/mach-exynos/hotplug.c b/arch/arm/mach-exynos/hotplug.c
index da70e7e..dd1ad55 100644
--- a/arch/arm/mach-exynos/hotplug.c
+++ b/arch/arm/mach-exynos/hotplug.c
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <mach/regs-pmu.h>
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 683aec7..0f2035a 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -23,6 +23,7 @@
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 7afbe1e..8394d51 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -25,6 +25,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/hardware/arm_timer.h>
#include <asm/hardware/timer-sp.h>
@@ -72,9 +73,7 @@
void highbank_set_cpu_jump(int cpu, void *jump_addr)
{
-#ifdef CONFIG_SMP
cpu = cpu_logical_map(cpu);
-#endif
writel(virt_to_phys(jump_addr), HB_JUMP_TABLE_VIRT(cpu));
__cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 09f357b..4defb97 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -87,7 +87,6 @@
config SOC_IMX5
select CPU_V7
- select ARM_L1_CACHE_SHIFT_6
select MXC_TZIC
select ARCH_MXC_IOMUX_V3
select ARCH_MXC_AUDMUX_V2
diff --git a/arch/arm/mach-imx/clock-imx6q.c b/arch/arm/mach-imx/clock-imx6q.c
index 9273c2a..2d88f8b 100644
--- a/arch/arm/mach-imx/clock-imx6q.c
+++ b/arch/arm/mach-imx/clock-imx6q.c
@@ -814,6 +814,16 @@
DEF_PFD(pll3_pfd_508m, PFD_480, PFD2, &pll3_usb_otg);
DEF_PFD(pll3_pfd_454m, PFD_480, PFD3, &pll3_usb_otg);
+static unsigned long twd_clk_get_rate(struct clk *clk)
+{
+ return clk_get_rate(clk->parent) / 2;
+}
+
+static struct clk twd_clk = {
+ .parent = &arm_clk,
+ .get_rate = twd_clk_get_rate,
+};
+
static unsigned long pll2_200m_get_rate(struct clk *clk)
{
return clk_get_rate(clk->parent) / 2;
@@ -1894,6 +1904,7 @@
_REGISTER_CLOCK("20ec000.sdma", NULL, sdma_clk),
_REGISTER_CLOCK("20bc000.wdog", NULL, dummy_clk),
_REGISTER_CLOCK("20c0000.wdog", NULL, dummy_clk),
+ _REGISTER_CLOCK("smp_twd", NULL, twd_clk),
_REGISTER_CLOCK(NULL, "ckih", ckih_clk),
_REGISTER_CLOCK(NULL, "ckil_clk", ckil_clk),
_REGISTER_CLOCK(NULL, "aips_tz1_clk", aips_tz1_clk),
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
index 08dfb76..753f4fc 100644
--- a/arch/arm/mach-imx/mach-mx53_ard.c
+++ b/arch/arm/mach-imx/mach-mx53_ard.c
@@ -188,8 +188,10 @@
return -ENOMEM;
iomuxc_base = ioremap(MX53_IOMUXC_BASE_ADDR, SZ_4K);
- if (!iomuxc_base)
+ if (!iomuxc_base) {
+ iounmap(weim_base);
return -ENOMEM;
+ }
/* CS1 timings for LAN9220 */
writel(0x20001, (weim_base + 0x18));
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 29bd124..e15f155 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/smp.h>
+#include <asm/smp_plat.h>
#define SRC_SCR 0x000
#define SRC_GPR1 0x020
@@ -24,10 +25,6 @@
static void __iomem *src_base;
-#ifndef CONFIG_SMP
-#define cpu_logical_map(cpu) 0
-#endif
-
void imx_enable_cpu(int cpu, bool enable)
{
u32 mask, val;
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 41c252d..a446fc1 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -11,6 +11,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 0b3e357..db0117e 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/mach-types.h>
+#include <asm/smp_plat.h>
#include <mach/msm_iomap.h>
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index a8ba7b9..d965da4 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -33,7 +33,6 @@
default y
select CPU_V7
select USB_ARCH_HAS_EHCI
- select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
select ARCH_HAS_OPP
select PM_OPP if PM
select ARM_CPU_SUSPEND if PM
@@ -214,13 +213,12 @@
depends on ARCH_OMAP3
default y
select OMAP_PACKAGE_CBB
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP3_TOUCHBOOK
bool "OMAP3 Touch Book"
depends on ARCH_OMAP3
default y
- select BACKLIGHT_CLASS_DEVICE
config MACH_OMAP_3430SDP
bool "OMAP 3430 SDP board"
@@ -266,7 +264,7 @@
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP_ZOOM3
bool "OMAP3630 Zoom3 board"
@@ -276,7 +274,7 @@
select SERIAL_8250
select SERIAL_CORE_CONSOLE
select SERIAL_8250_CONSOLE
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_CM_T35
bool "CompuLab CM-T35/CM-T3730 modules"
@@ -335,7 +333,7 @@
depends on ARCH_OMAP4
select OMAP_PACKAGE_CBL
select OMAP_PACKAGE_CBS
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config MACH_OMAP4_PANDA
bool "OMAP4 Panda Board"
@@ -343,7 +341,7 @@
depends on ARCH_OMAP4
select OMAP_PACKAGE_CBL
select OMAP_PACKAGE_CBS
- select REGULATOR_FIXED_VOLTAGE
+ select REGULATOR_FIXED_VOLTAGE if REGULATOR
config OMAP3_EMU
bool "OMAP3 debugging peripherals"
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 0b510ad..283d11e 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -405,6 +405,7 @@
break;
default:
pr_err("Invalid McSPI Revision value\n");
+ kfree(pdata);
return -EINVAL;
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 130034b..dfffbbf 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -528,7 +528,13 @@
case GPMC_CONFIG_DEV_SIZE:
regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+ /* clear 2 target bits */
+ regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+
+ /* set the proper value */
regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
break;
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index bd844af..ad0adb5 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -175,14 +175,15 @@
{
u32 reg;
- if (mmc->slots[0].internal_clock) {
- reg = omap_ctrl_readl(control_devconf1_offset);
+ reg = omap_ctrl_readl(control_devconf1_offset);
+ if (mmc->slots[0].internal_clock)
reg |= OMAP2_MMCSDIO2ADPCLKISEL;
- omap_ctrl_writel(reg, control_devconf1_offset);
- }
+ else
+ reg &= ~OMAP2_MMCSDIO2ADPCLKISEL;
+ omap_ctrl_writel(reg, control_devconf1_offset);
}
-static void hsmmc23_before_set_reg(struct device *dev, int slot,
+static void hsmmc2_before_set_reg(struct device *dev, int slot,
int power_on, int vdd)
{
struct omap_mmc_platform_data *mmc = dev->platform_data;
@@ -407,14 +408,13 @@
c->caps &= ~MMC_CAP_8_BIT_DATA;
c->caps |= MMC_CAP_4_BIT_DATA;
}
- /* FALLTHROUGH */
- case 3:
if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
/* off-chip level shifting, or none */
- mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+ mmc->slots[0].before_set_reg = hsmmc2_before_set_reg;
mmc->slots[0].after_set_reg = NULL;
}
break;
+ case 3:
case 4:
case 5:
mmc->slots[0].before_set_reg = NULL;
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index 3f174d5..eb50c29 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -388,7 +388,7 @@
omap_pm_if_early_init();
}
-#ifdef CONFIG_ARCH_OMAP2
+#ifdef CONFIG_SOC_OMAP2420
void __init omap2420_init_early(void)
{
omap2_set_globals_242x();
@@ -400,7 +400,9 @@
omap_hwmod_init_postsetup();
omap2420_clk_init();
}
+#endif
+#ifdef CONFIG_SOC_OMAP2430
void __init omap2430_init_early(void)
{
omap2_set_globals_243x();
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
index c11273d..f08e442 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
@@ -56,27 +56,6 @@
};
/*
- * 'dispc' class
- * display controller
- */
-
-static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
- .rev_offs = 0x0000,
- .sysc_offs = 0x0010,
- .syss_offs = 0x0014,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
- SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-struct omap_hwmod_class omap2_dispc_hwmod_class = {
- .name = "dispc",
- .sysc = &omap2_dispc_sysc,
-};
-
-/*
* 'rfbi' class
* remote frame buffer interface
*/
diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
index 177dee2..2a67297 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
@@ -28,6 +28,28 @@
{ .name = "dispc", .dma_req = 5 },
{ .dma_req = -1 }
};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+struct omap_hwmod_class omap2_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap2_dispc_sysc,
+};
+
/* OMAP2xxx Timer Common */
static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
.rev_offs = 0x0000,
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 5324e8d..3c8dd92 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1480,6 +1480,28 @@
.masters_cnt = ARRAY_SIZE(omap3xxx_dss_masters),
};
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3_dispc_sysc = {
+ .rev_offs = 0x0000,
+ .sysc_offs = 0x0010,
+ .syss_offs = 0x0014,
+ .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+ SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+ SYSC_HAS_ENAWAKEUP),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+ .sysc_fields = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3_dispc_hwmod_class = {
+ .name = "dispc",
+ .sysc = &omap3_dispc_sysc,
+};
+
/* l4_core -> dss_dispc */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
.master = &omap3xxx_l4_core_hwmod,
@@ -1503,7 +1525,7 @@
static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
.name = "dss_dispc",
- .class = &omap2_dispc_hwmod_class,
+ .class = &omap3_dispc_hwmod_class,
.mpu_irqs = omap2_dispc_irqs,
.main_clk = "dss1_alwon_fck",
.prcm = {
@@ -3523,12 +3545,6 @@
&omap3xxx_uart2_hwmod,
&omap3xxx_uart3_hwmod,
- /* dss class */
- &omap3xxx_dss_dispc_hwmod,
- &omap3xxx_dss_dsi1_hwmod,
- &omap3xxx_dss_rfbi_hwmod,
- &omap3xxx_dss_venc_hwmod,
-
/* i2c class */
&omap3xxx_i2c1_hwmod,
&omap3xxx_i2c2_hwmod,
@@ -3635,6 +3651,15 @@
NULL
};
+static __initdata struct omap_hwmod *omap3xxx_dss_hwmods[] = {
+ /* dss class */
+ &omap3xxx_dss_dispc_hwmod,
+ &omap3xxx_dss_dsi1_hwmod,
+ &omap3xxx_dss_rfbi_hwmod,
+ &omap3xxx_dss_venc_hwmod,
+ NULL
+};
+
int __init omap3xxx_hwmod_init(void)
{
int r;
@@ -3708,6 +3733,21 @@
if (h)
r = omap_hwmod_register(h);
+ if (r < 0)
+ return r;
+
+ /*
+ * DSS code presumes that dss_core hwmod is handled first,
+ * _before_ any other DSS related hwmods so register common
+ * DSS hwmods last to ensure that dss_core is already registered.
+ * Otherwise some change things may happen, for ex. if dispc
+ * is handled before dss_core and DSS is enabled in bootloader
+ * DIPSC will be reset with outputs enabled which sometimes leads
+ * to unrecoverable L3 error.
+ * XXX The long-term fix to this is to ensure modules are set up
+ * in dependency order in the hwmod core code.
+ */
+ r = omap_hwmod_register(omap3xxx_dss_hwmods);
return r;
}
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index f9f1510..ef0524c 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -1031,6 +1031,7 @@
static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
{
+ .name = "mpu",
.pa_start = 0x4012e000,
.pa_end = 0x4012e07f,
.flags = ADDR_TYPE_RT
@@ -1049,6 +1050,7 @@
static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
{
+ .name = "dma",
.pa_start = 0x4902e000,
.pa_end = 0x4902e07f,
.flags = ADDR_TYPE_RT
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index c1c4d86..9ce7654 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -19,6 +19,7 @@
#include "common.h"
#include <plat/cpu.h>
#include <plat/prcm.h>
+#include <plat/irqs.h>
#include "vp.h"
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index 9dd9345..7e755bb 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -897,7 +897,7 @@
ret = sr_late_init(sr_info);
if (ret) {
pr_warning("%s: Error in SR late init\n", __func__);
- return ret;
+ goto err_iounmap;
}
}
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 6eeff0e..5c9acea 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -270,7 +270,7 @@
static u32 notrace dmtimer_read_sched_clock(void)
{
if (clksrc.reserved)
- return __omap_dm_timer_read_counter(clksrc.io_base, 1);
+ return __omap_dm_timer_read_counter(&clksrc, 1);
return 0;
}
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 18fd177..5bc1312 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -415,29 +415,9 @@
},
};
-static struct resource sa1100_rtc_resources[] = {
- [0] = {
- .start = 0x40900000,
- .end = 0x409000ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_RTC1Hz,
- .end = IRQ_RTC1Hz,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_RTCAlrm,
- .end = IRQ_RTCAlrm,
- .flags = IORESOURCE_IRQ,
- },
-};
-
struct platform_device sa1100_device_rtc = {
.name = "sa1100-rtc",
.id = -1,
- .num_resources = ARRAY_SIZE(sa1100_rtc_resources),
- .resource = sa1100_rtc_resources,
};
struct platform_device pxa_device_rtc = {
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index adf058f..91e4f6c 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -209,8 +209,6 @@
INIT_CLKREG(&clk_pxa25x_gpio11, NULL, "GPIO11_CLK"),
INIT_CLKREG(&clk_pxa25x_gpio12, NULL, "GPIO12_CLK"),
INIT_CLKREG(&clk_pxa25x_mem, "pxa2xx-pcmcia", NULL),
- INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static struct clk_lookup pxa25x_hwuart_clkreg =
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 180bd86..aed6cbc 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -230,8 +230,6 @@
INIT_CLKREG(&clk_pxa27x_im, NULL, "IMCLK"),
INIT_CLKREG(&clk_pxa27x_memc, NULL, "MEMCLK"),
INIT_CLKREG(&clk_pxa27x_mem, "pxa2xx-pcmcia", NULL),
- INIT_CLKREG(&clk_dummy, "pxa-gpio", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
#ifdef CONFIG_PM
diff --git a/arch/arm/mach-pxa/pxa300.c b/arch/arm/mach-pxa/pxa300.c
index 0388eda..40bb165 100644
--- a/arch/arm/mach-pxa/pxa300.c
+++ b/arch/arm/mach-pxa/pxa300.c
@@ -89,7 +89,6 @@
static struct clk_lookup common_clkregs[] = {
INIT_CLKREG(&clk_common_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static DEFINE_PXA3_CKEN(pxa310_mmc3, MMC3, 19500000, 0);
diff --git a/arch/arm/mach-pxa/pxa320.c b/arch/arm/mach-pxa/pxa320.c
index d487e1f..8d614ec 100644
--- a/arch/arm/mach-pxa/pxa320.c
+++ b/arch/arm/mach-pxa/pxa320.c
@@ -83,7 +83,6 @@
static struct clk_lookup pxa320_clkregs[] = {
INIT_CLKREG(&clk_pxa320_nand, "pxa3xx-nand", NULL),
INIT_CLKREG(&clk_gcu, "pxa3xx-gcu", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
};
static int __init pxa320_init(void)
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index f107c71..4f402af 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -67,7 +67,6 @@
INIT_CLKREG(&clk_pxa3xx_pout, NULL, "CLK_POUT"),
/* Power I2C clock is always on */
INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
INIT_CLKREG(&clk_pxa3xx_lcd, "pxa2xx-fb", NULL),
INIT_CLKREG(&clk_pxa3xx_camera, NULL, "CAMCLK"),
INIT_CLKREG(&clk_pxa3xx_ac97, NULL, "AC97CLK"),
diff --git a/arch/arm/mach-pxa/pxa95x.c b/arch/arm/mach-pxa/pxa95x.c
index fccc644..d082a58 100644
--- a/arch/arm/mach-pxa/pxa95x.c
+++ b/arch/arm/mach-pxa/pxa95x.c
@@ -217,7 +217,6 @@
INIT_CLKREG(&clk_pxa95x_pout, NULL, "CLK_POUT"),
/* Power I2C clock is always on */
INIT_CLKREG(&clk_dummy, "pxa3xx-pwri2c.1", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
INIT_CLKREG(&clk_pxa95x_lcd, "pxa2xx-fb", NULL),
INIT_CLKREG(&clk_pxa95x_ffuart, "pxa2xx-uart.0", NULL),
INIT_CLKREG(&clk_pxa95x_btuart, "pxa2xx-uart.1", NULL),
diff --git a/arch/arm/mach-realview/hotplug.c b/arch/arm/mach-realview/hotplug.c
index ac1aed2..eb55f05 100644
--- a/arch/arm/mach-realview/hotplug.c
+++ b/arch/arm/mach-realview/hotplug.c
@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
diff --git a/arch/arm/mach-realview/include/mach/board-eb.h b/arch/arm/mach-realview/include/mach/board-eb.h
index 794a8d9..124bce6 100644
--- a/arch/arm/mach-realview/include/mach/board-eb.h
+++ b/arch/arm/mach-realview/include/mach/board-eb.h
@@ -47,21 +47,23 @@
#define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */
#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
-#define REALVIEW_EB11MP_SCU_BASE 0x10100000 /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE 0x10100100 /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE 0x10100600
-#define REALVIEW_EB11MP_GIC_DIST_BASE 0x10101000 /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000
#define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */
#else
-#define REALVIEW_EB11MP_SCU_BASE 0x1F000000 /* SCU registers */
-#define REALVIEW_EB11MP_GIC_CPU_BASE 0x1F000100 /* Generic interrupt controller CPU interface */
-#define REALVIEW_EB11MP_TWD_BASE 0x1F000600
-#define REALVIEW_EB11MP_GIC_DIST_BASE 0x1F001000 /* Generic interrupt controller distributor */
+#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000
#define REALVIEW_EB11MP_L220_BASE 0x1F002000 /* L220 registers */
#define REALVIEW_EB11MP_SYS_PLD_CTRL1 0x74 /* Register offset for MPCore sysctl */
#endif
+#define REALVIEW_EB11MP_PRIV_MEM_SIZE SZ_8K
+#define REALVIEW_EB11MP_PRIV_MEM_OFF(x) (REALVIEW_EB11MP_PRIV_MEM_BASE + (x))
+
+#define REALVIEW_EB11MP_SCU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0) /* SCU registers */
+#define REALVIEW_EB11MP_GIC_CPU_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0100) /* Generic interrupt controller CPU interface */
+#define REALVIEW_EB11MP_TWD_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x0600)
+#define REALVIEW_EB11MP_GIC_DIST_BASE REALVIEW_EB11MP_PRIV_MEM_OFF(0x1000) /* Generic interrupt controller distributor */
+
/*
* Core tile identification (REALVIEW_SYS_PROCID)
*/
diff --git a/arch/arm/mach-realview/include/mach/board-pb11mp.h b/arch/arm/mach-realview/include/mach/board-pb11mp.h
index 7abf918..aa2d4e0 100644
--- a/arch/arm/mach-realview/include/mach/board-pb11mp.h
+++ b/arch/arm/mach-realview/include/mach/board-pb11mp.h
@@ -75,6 +75,8 @@
/*
* Testchip peripheral and fpga gic regions
*/
+#define REALVIEW_TC11MP_PRIV_MEM_BASE 0x1F000000
+#define REALVIEW_TC11MP_PRIV_MEM_SIZE SZ_8K
#define REALVIEW_TC11MP_SCU_BASE 0x1F000000 /* IRQ, Test chip */
#define REALVIEW_TC11MP_GIC_CPU_BASE 0x1F000100 /* Test chip interrupt controller CPU interface */
#define REALVIEW_TC11MP_TWD_BASE 0x1F000600
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index e629621..9578145 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -91,14 +91,9 @@
static struct map_desc realview_eb11mp_io_desc[] __initdata = {
{
- .virtual = IO_ADDRESS(REALVIEW_EB11MP_SCU_BASE),
- .pfn = __phys_to_pfn(REALVIEW_EB11MP_SCU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
- .pfn = __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
- .length = SZ_4K,
+ .virtual = IO_ADDRESS(REALVIEW_EB11MP_PRIV_MEM_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_EB11MP_PRIV_MEM_BASE),
+ .length = REALVIEW_EB11MP_PRIV_MEM_SIZE,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 127a3fd..2147335 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -64,15 +64,10 @@
.pfn = __phys_to_pfn(REALVIEW_PB11MP_GIC_DIST_BASE),
.length = SZ_4K,
.type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_CPU_BASE),
- .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_CPU_BASE),
- .length = SZ_4K,
- .type = MT_DEVICE,
- }, {
- .virtual = IO_ADDRESS(REALVIEW_TC11MP_GIC_DIST_BASE),
- .pfn = __phys_to_pfn(REALVIEW_TC11MP_GIC_DIST_BASE),
- .length = SZ_4K,
+ }, { /* Maps the SCU, GIC CPU interface, TWD, GIC DIST */
+ .virtual = IO_ADDRESS(REALVIEW_TC11MP_PRIV_MEM_BASE),
+ .pfn = __phys_to_pfn(REALVIEW_TC11MP_PRIV_MEM_BASE),
+ .length = REALVIEW_TC11MP_PRIV_MEM_SIZE,
.type = MT_DEVICE,
}, {
.virtual = IO_ADDRESS(REALVIEW_SCTL_BASE),
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index ebafe8a..0c4b76a 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -202,7 +202,6 @@
static struct mcp_plat_data assabet_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init assabet_init(void)
@@ -253,17 +252,6 @@
sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
ARRAY_SIZE(assabet_flash_resources));
sa11x0_register_irda(&assabet_irda_data);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
- ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
sa11x0_register_mcp(&assabet_mcp_data);
}
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index d12d0f4..11bb6d0 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -124,23 +124,12 @@
static struct mcp_plat_data cerf_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init cerf_init(void)
{
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&cerf_mcp_data);
}
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index d6df9f6..dab3c63 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -11,39 +11,17 @@
#include <linux/clk.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
#include <mach/hardware.h>
-struct clkops {
- void (*enable)(struct clk *);
- void (*disable)(struct clk *);
- unsigned long (*getrate)(struct clk *);
-};
-
+/*
+ * Very simple clock implementation - we only have one clock to deal with.
+ */
struct clk {
- const struct clkops *ops;
- unsigned long rate;
unsigned int enabled;
};
-#define INIT_CLKREG(_clk, _devname, _conname) \
- { \
- .clk = _clk, \
- .dev_id = _devname, \
- .con_id = _conname, \
- }
-
-#define DEFINE_CLK(_name, _ops, _rate) \
-struct clk clk_##_name = { \
- .ops = _ops, \
- .rate = _rate, \
- }
-
-static DEFINE_SPINLOCK(clocks_lock);
-
-static void clk_gpio27_enable(struct clk *clk)
+static void clk_gpio27_enable(void)
{
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -54,22 +32,38 @@
TUCR = TUCR_3_6864MHz;
}
-static void clk_gpio27_disable(struct clk *clk)
+static void clk_gpio27_disable(void)
{
TUCR = 0;
GPDR &= ~GPIO_32_768kHz;
GAFR &= ~GPIO_32_768kHz;
}
+static struct clk clk_gpio27;
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ const char *devname = dev_name(dev);
+
+ return strcmp(devname, "sa1111.0") ? ERR_PTR(-ENOENT) : &clk_gpio27;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
int clk_enable(struct clk *clk)
{
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
if (clk->enabled++ == 0)
- clk->ops->enable(clk);
+ clk_gpio27_enable();
spin_unlock_irqrestore(&clocks_lock, flags);
-
return 0;
}
EXPORT_SYMBOL(clk_enable);
@@ -82,48 +76,13 @@
spin_lock_irqsave(&clocks_lock, flags);
if (--clk->enabled == 0)
- clk->ops->disable(clk);
+ clk_gpio27_disable();
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
- unsigned long rate;
-
- rate = clk->rate;
- if (clk->ops->getrate)
- rate = clk->ops->getrate(clk);
-
- return rate;
+ return 3686400;
}
EXPORT_SYMBOL(clk_get_rate);
-
-const struct clkops clk_gpio27_ops = {
- .enable = clk_gpio27_enable,
- .disable = clk_gpio27_disable,
-};
-
-static void clk_dummy_enable(struct clk *clk) { }
-static void clk_dummy_disable(struct clk *clk) { }
-
-const struct clkops clk_dummy_ops = {
- .enable = clk_dummy_enable,
- .disable = clk_dummy_disable,
-};
-
-static DEFINE_CLK(gpio27, &clk_gpio27_ops, 3686400);
-static DEFINE_CLK(dummy, &clk_dummy_ops, 0);
-
-static struct clk_lookup sa11xx_clkregs[] = {
- INIT_CLKREG(&clk_gpio27, "sa1111.0", NULL),
- INIT_CLKREG(&clk_dummy, "sa1100-rtc", NULL),
-};
-
-static int __init sa11xx_clk_init(void)
-{
- clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs));
- return 0;
-}
-
-postcore_initcall(sa11xx_clk_init);
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index c483912..fd56521 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -27,7 +27,6 @@
#include <linux/timer.h>
#include <linux/gpio.h>
#include <linux/pda_power.h>
-#include <linux/mfd/ucb1x00.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -86,15 +85,10 @@
.num_devs = 1,
};
-static struct ucb1x00_plat_data collie_ucb1x00_data = {
- .gpio_base = COLLIE_TC35143_GPIO_BASE,
-};
-
static struct mcp_plat_data collie_mcp_data = {
.mccr0 = MCCR0_ADM | MCCR0_ExtClk,
.sclk_rate = 9216000,
- .codec = "ucb1x00",
- .codec_pdata = &collie_ucb1x00_data,
+ .gpio_base = COLLIE_TC35143_GPIO_BASE,
};
/*
@@ -144,8 +138,6 @@
static struct resource collie_power_resource[] = {
{
.name = "ac",
- .start = gpio_to_irq(COLLIE_GPIO_AC_IN),
- .end = gpio_to_irq(COLLIE_GPIO_AC_IN),
.flags = IORESOURCE_IRQ |
IORESOURCE_IRQ_HIGHEDGE |
IORESOURCE_IRQ_LOWEDGE,
@@ -347,7 +339,8 @@
GPSR |= _COLLIE_GPIO_UCB1x00_RESET;
-
+ collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
+ collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
platform_scoop_config = &collie_pcmcia_config;
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -357,16 +350,6 @@
sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
ARRAY_SIZE(collie_flash_resources));
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&collie_mcp_data);
sharpsl_save_param();
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
index aaa8acf..19b2053 100644
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c
@@ -228,7 +228,7 @@
return 0;
}
-static struct cpufreq_driver sa1100_driver = {
+static struct cpufreq_driver sa1100_driver __refdata = {
.flags = CPUFREQ_STICKY,
.verify = sa11x0_verify_speed,
.target = sa1100_target,
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index e3a28ca..bb10ee2 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -217,15 +217,10 @@
static struct resource sa11x0mcp_resources[] = {
[0] = {
.start = __PREG(Ser4MCCR0),
- .end = __PREG(Ser4MCCR0) + 0x1C - 1,
+ .end = __PREG(Ser4MCCR0) + 0xffff,
.flags = IORESOURCE_MEM,
},
[1] = {
- .start = __PREG(Ser4MCCR1),
- .end = __PREG(Ser4MCCR1) + 0x4 - 1,
- .flags = IORESOURCE_MEM,
- },
- [2] = {
.start = IRQ_Ser4MCP,
.end = IRQ_Ser4MCP,
.flags = IORESOURCE_IRQ,
@@ -350,29 +345,9 @@
sa11x0_register_device(&sa11x0ir_device, irda);
}
-static struct resource sa11x0rtc_resources[] = {
- [0] = {
- .start = 0x90010000,
- .end = 0x900100ff,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_RTC1Hz,
- .end = IRQ_RTC1Hz,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = IRQ_RTCAlrm,
- .end = IRQ_RTCAlrm,
- .flags = IORESOURCE_IRQ,
- },
-};
-
static struct platform_device sa11x0rtc_device = {
.name = "sa1100-rtc",
.id = -1,
- .resource = sa11x0rtc_resources,
- .num_resources = ARRAY_SIZE(sa11x0rtc_resources),
};
static struct platform_device *sa11x0_devices[] __initdata = {
diff --git a/arch/arm/mach-sa1100/include/mach/mcp.h b/arch/arm/mach-sa1100/include/mach/mcp.h
index 586cec8..ed1a331 100644
--- a/arch/arm/mach-sa1100/include/mach/mcp.h
+++ b/arch/arm/mach-sa1100/include/mach/mcp.h
@@ -17,8 +17,6 @@
u32 mccr1;
unsigned int sclk_rate;
int gpio_base;
- const char *codec;
- void *codec_pdata;
};
#endif
diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c
index f50b00b..b412fc0 100644
--- a/arch/arm/mach-sa1100/jornada720_ssp.c
+++ b/arch/arm/mach-sa1100/jornada720_ssp.c
@@ -198,3 +198,5 @@
{
return platform_driver_register(&jornadassp_driver);
}
+
+module_init(jornada_ssp_init);
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index d117cea..af4e276 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -24,20 +24,10 @@
static struct mcp_plat_data lart_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init lart_init(void)
{
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&lart_mcp_data);
}
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 748d344..318b2b7 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -55,22 +55,11 @@
static struct mcp_plat_data shannon_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1x00",
};
static void __init shannon_init(void)
{
sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&shannon_mcp_data);
}
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 458ecec..e17c04d 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -14,7 +14,6 @@
#include <linux/mtd/partitions.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/mfd/ucb1x00.h>
#include <asm/irq.h>
#include <mach/hardware.h>
@@ -188,15 +187,10 @@
}
};
-static struct ucb1x00_plat_data simpad_ucb1x00_data = {
- .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
-};
-
static struct mcp_plat_data simpad_mcp_data = {
.mccr0 = MCCR0_ADM,
.sclk_rate = 11981000,
- .codec = "ucb1300",
- .codec_pdata = &simpad_ucb1x00_data,
+ .gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
};
@@ -384,16 +378,6 @@
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
ARRAY_SIZE(simpad_flash_resources));
-
- /*
- * Setup the PPC unit correctly.
- */
- PPDR &= ~PPC_RXD4;
- PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
- PSDR |= PPC_RXD4;
- PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
- PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
-
sa11x0_register_mcp(&simpad_mcp_data);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index 6fcf304..a83cf51 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -662,6 +662,7 @@
.dmaor_is_32bit = 1,
.needs_tend_set = 1,
.no_dmars = 1,
+ .slave_only = 1,
};
static struct resource sh7372_usb_dmae0_resources[] = {
@@ -723,6 +724,7 @@
.dmaor_is_32bit = 1,
.needs_tend_set = 1,
.no_dmars = 1,
+ .slave_only = 1,
};
static struct resource sh7372_usb_dmae1_resources[] = {
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index cc97ef8..4fe2e9e 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <mach/common.h>
#include <mach/r8a7779.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index be1ade7..0d159d6 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <mach/common.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <asm/smp_twd.h>
#include <asm/hardware/gic.h>
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index a3e0c86..52af004 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -7,6 +7,7 @@
select HAS_MTU
select ARM_ERRATA_753970
select ARM_ERRATA_754322
+ select ARM_ERRATA_764369
menu "Ux500 SoC"
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 23be34b..5dde4d4 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -261,6 +261,8 @@
void __init snowball_sdi_init(void)
{
+ /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
+ mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED;
/* On-board eMMC */
db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
/* External Micro SD slot */
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c
index 122ddde..da5569d 100644
--- a/arch/arm/mach-ux500/cache-l2x0.c
+++ b/arch/arm/mach-ux500/cache-l2x0.c
@@ -12,44 +12,6 @@
static void __iomem *l2x0_base;
-static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
-{
- /* wait for the operation to complete */
- while (readl_relaxed(reg) & mask)
- cpu_relax();
-}
-
-static inline void ux500_cache_sync(void)
-{
- writel_relaxed(0, l2x0_base + L2X0_CACHE_SYNC);
- ux500_cache_wait(l2x0_base + L2X0_CACHE_SYNC, 1);
-}
-
-/*
- * The L2 cache cannot be turned off in the non-secure world.
- * Dummy until a secure service is in place.
- */
-static void ux500_l2x0_disable(void)
-{
-}
-
-/*
- * This is only called when doing a kexec, just after turning off the L2
- * and L1 cache, and it is surrounded by a spinlock in the generic version.
- * However, we're not really turning off the L2 cache right now and the
- * PL310 does not support exclusive accesses (used to implement the spinlock).
- * So, the invalidation needs to be done without the spinlock.
- */
-static void ux500_l2x0_inv_all(void)
-{
- uint32_t l2x0_way_mask = (1<<16) - 1; /* Bitmask of active ways */
-
- /* invalidate all ways */
- writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_INV_WAY);
- ux500_cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask);
- ux500_cache_sync();
-}
-
static int __init ux500_l2x0_unlock(void)
{
int i;
@@ -85,9 +47,13 @@
/* 64KB way size, 8 way associativity, force WA */
l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff);
- /* Override invalidate function */
- outer_cache.disable = ux500_l2x0_disable;
- outer_cache.inv_all = ux500_l2x0_inv_all;
+ /*
+ * We can't disable l2 as we are in non secure mode, currently
+ * this seems be called only during kexec path. So let's
+ * override outer.disable with nasty assignment until we have
+ * some SMI service available.
+ */
+ outer_cache.disable = NULL;
return 0;
}
diff --git a/arch/arm/mach-ux500/hotplug.c b/arch/arm/mach-ux500/hotplug.c
index 572015e..c76f0f4 100644
--- a/arch/arm/mach-ux500/hotplug.c
+++ b/arch/arm/mach-ux500/hotplug.c
@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
extern volatile int pen_release;
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index a19e398..d2058ef 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -19,6 +19,7 @@
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <mach/hardware.h>
#include <mach/setup.h>
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c
index 0a01cbd..9f9e1c2 100644
--- a/arch/arm/mach-ux500/usb.c
+++ b/arch/arm/mach-ux500/usb.c
@@ -95,13 +95,7 @@
};
static struct musb_hdrc_platform_data musb_platform_data = {
-#if defined(CONFIG_USB_MUSB_OTG)
.mode = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
- .mode = MUSB_PERIPHERAL,
-#else /* defined(CONFIG_USB_MUSB_HOST) */
- .mode = MUSB_HOST,
-#endif
.config = &musb_hdrc_config,
.board_data = &musb_board_data,
};
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 2b1e836..b1e87c1 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -217,7 +217,7 @@
}
#ifdef CONFIG_SMP
-static void ct_ca9x4_init_cpu_map(void)
+static void __init ct_ca9x4_init_cpu_map(void)
{
int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
@@ -233,7 +233,7 @@
set_smp_cross_call(gic_raise_softirq);
}
-static void ct_ca9x4_smp_enable(unsigned int max_cpus)
+static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
{
scu_enable(MMIO_P2V(A9_MPCORE_SCU));
}
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
index 813ee08..3034a4d 100644
--- a/arch/arm/mach-vexpress/hotplug.c
+++ b/arch/arm/mach-vexpress/hotplug.c
@@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/system.h>
extern volatile int pen_release;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 4cefb57..1a3ca24 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -882,6 +882,7 @@
config ARM_L1_CACHE_SHIFT_6
bool
+ default y if CPU_V7
help
Setting ARM L1 cache line size to 64 Bytes.
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 6ec1226..5dc7d12 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -310,7 +310,7 @@
static bool arm_memblock_steal_permitted = true;
-phys_addr_t arm_memblock_steal(phys_addr_t size, phys_addr_t align)
+phys_addr_t __init arm_memblock_steal(phys_addr_t size, phys_addr_t align)
{
phys_addr_t phys;
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 7e9b5bf..0404ccb 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -148,10 +148,6 @@
* Initialise TLB, Caches, and MMU state ready to switch the MMU
* on. Return in r0 the new CP15 C1 control register setting.
*
- * We automatically detect if we have a Harvard cache, and use the
- * Harvard cache control instructions insead of the unified cache
- * control instructions.
- *
* This should be able to cover all ARMv7 cores.
*
* It is assumed that:
@@ -251,9 +247,7 @@
#endif
3: mov r10, #0
-#ifdef HARVARD_CACHE
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
-#endif
dsb
#ifdef CONFIG_MMU
mcr p15, 0, r10, c8, c7, 0 @ invalidate I + D TLBs
@@ -330,16 +324,6 @@
.size __v7_ca5mp_proc_info, . - __v7_ca5mp_proc_info
/*
- * ARM Ltd. Cortex A7 processor.
- */
- .type __v7_ca7mp_proc_info, #object
-__v7_ca7mp_proc_info:
- .long 0x410fc070
- .long 0xff0ffff0
- __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
- .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
-
- /*
* ARM Ltd. Cortex A9 processor.
*/
.type __v7_ca9mp_proc_info, #object
@@ -351,6 +335,16 @@
#endif /* CONFIG_ARM_LPAE */
/*
+ * ARM Ltd. Cortex A7 processor.
+ */
+ .type __v7_ca7mp_proc_info, #object
+__v7_ca7mp_proc_info:
+ .long 0x410fc070
+ .long 0xff0ffff0
+ __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+ .size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
+
+ /*
* ARM Ltd. Cortex A15 processor.
*/
.type __v7_ca15mp_proc_info, #object
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v1.h b/arch/arm/plat-mxc/include/mach/iomux-v1.h
index 6fa8a70..f7d1804 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v1.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v1.h
@@ -96,6 +96,6 @@
extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
const char *label);
-extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
+extern int imx_iomuxv1_init(void __iomem *base, int numports);
#endif /* __MACH_IOMUX_V1_H__ */
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index 92f18d3..49c7db4 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -16,6 +16,7 @@
#include <linux/smp.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/hardware/gic.h>
/*
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index 197e96f..3dea7231 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -8,6 +8,7 @@
select HAVE_KPROBES
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_PROBE
+ select GENERIC_ATOMIC64
select HARDIRQS_SW_RESEND
select GENERIC_IRQ_SHOW
select ARCH_HAVE_NMI_SAFE_CMPXCHG
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 4203d10..c4ac15c 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -414,9 +414,9 @@
* FDC val = 4 -> Supervisor only */
asm volatile ("\n"
" .chip 68030\n"
- " pmove %0@,%/tt1\n"
+ " pmove %0,%/tt1\n"
" .chip 68k"
- : : "a" (&tt1_val));
+ : : "m" (tt1_val));
} else {
asm volatile ("\n"
" .chip 68040\n"
@@ -569,10 +569,10 @@
: "d0");
} else
asm volatile ("\n"
- " pmove %0@,%%tc\n"
+ " pmove %0,%%tc\n"
" jmp %1@"
: /* no outputs */
- : "a" (&tc_val), "a" (reset_addr));
+ : "m" (tc_val), "a" (reset_addr));
}
diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
index 0e89fa0..c1155f0 100644
--- a/arch/m68k/include/asm/irq.h
+++ b/arch/m68k/include/asm/irq.h
@@ -50,19 +50,6 @@
#define IRQ_USER 8
-/*
- * various flags for request_irq() - the Amiga now uses the standard
- * mechanism like all other architectures - IRQF_DISABLED and
- * IRQF_SHARED are your friends.
- */
-#ifndef MACH_AMIGA_ONLY
-#define IRQ_FLG_LOCK (0x0001) /* handler is not replaceable */
-#define IRQ_FLG_REPLACE (0x0002) /* replace existing handler */
-#define IRQ_FLG_FAST (0x0004)
-#define IRQ_FLG_SLOW (0x0008)
-#define IRQ_FLG_STD (0x8000) /* internally used */
-#endif
-
struct irq_data;
struct irq_chip;
struct irq_desc;
diff --git a/arch/m68k/kernel/process_mm.c b/arch/m68k/kernel/process_mm.c
index 125f34e..099283e 100644
--- a/arch/m68k/kernel/process_mm.c
+++ b/arch/m68k/kernel/process_mm.c
@@ -172,7 +172,7 @@
current->thread.fs = __USER_DS;
if (!FPU_IS_EMU)
- asm volatile ("frestore %0@" : : "a" (&zero) : "memory");
+ asm volatile("frestore %0": :"m" (zero));
}
/*
diff --git a/arch/m68k/kernel/process_no.c b/arch/m68k/kernel/process_no.c
index 69c1803..5e1078c 100644
--- a/arch/m68k/kernel/process_no.c
+++ b/arch/m68k/kernel/process_no.c
@@ -163,8 +163,8 @@
#ifdef CONFIG_FPU
if (!FPU_IS_EMU)
asm volatile (".chip 68k/68881\n\t"
- "frestore %0@\n\t"
- ".chip 68k" : : "a" (&zero));
+ "frestore %0\n\t"
+ ".chip 68k" : : "m" (zero));
#endif
}
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index a76452c..daaa918 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -552,13 +552,13 @@
#ifdef DEBUG
asm volatile ("ptestr %3,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr), "d" (ssw));
+ "pmove %%psr,%1"
+ : "=a&" (desc), "=m" (temp)
+ : "a" (addr), "d" (ssw));
#else
asm volatile ("ptestr %2,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr), "d" (ssw));
+ "pmove %%psr,%0"
+ : "=m" (temp) : "a" (addr), "d" (ssw));
#endif
mmusr = temp;
@@ -605,20 +605,18 @@
!(ssw & RW) ? "write" : "read", addr,
fp->ptregs.pc, ssw);
asm volatile ("ptestr #1,%1@,#0\n\t"
- "pmove %%psr,%0@"
- : /* no outputs */
- : "a" (&temp), "a" (addr));
+ "pmove %%psr,%0"
+ : "=m" (temp)
+ : "a" (addr));
mmusr = temp;
printk ("level 0 mmusr is %#x\n", mmusr);
#if 0
- asm volatile ("pmove %%tt0,%0@"
- : /* no outputs */
- : "a" (&tlong));
+ asm volatile ("pmove %%tt0,%0"
+ : "=m" (tlong));
printk("tt0 is %#lx, ", tlong);
- asm volatile ("pmove %%tt1,%0@"
- : /* no outputs */
- : "a" (&tlong));
+ asm volatile ("pmove %%tt1,%0"
+ : "=m" (tlong));
printk("tt1 is %#lx\n", tlong);
#endif
#ifdef DEBUG
@@ -668,13 +666,13 @@
#ifdef DEBUG
asm volatile ("ptestr #1,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (desc)
- : "a" (&temp), "a" (addr));
+ "pmove %%psr,%1"
+ : "=a&" (desc), "=m" (temp)
+ : "a" (addr));
#else
asm volatile ("ptestr #1,%1@,#7\n\t"
- "pmove %%psr,%0@"
- : : "a" (&temp), "a" (addr));
+ "pmove %%psr,%0"
+ : "=m" (temp) : "a" (addr));
#endif
mmusr = temp;
diff --git a/arch/m68k/mm/cache.c b/arch/m68k/mm/cache.c
index 95d0bf6..3d84c1f 100644
--- a/arch/m68k/mm/cache.c
+++ b/arch/m68k/mm/cache.c
@@ -52,9 +52,9 @@
unsigned long *descaddr;
asm volatile ("ptestr %3,%2@,#7,%0\n\t"
- "pmove %%psr,%1@"
- : "=a&" (descaddr)
- : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg));
+ "pmove %%psr,%1"
+ : "=a&" (descaddr), "=m" (mmusr)
+ : "a" (vaddr), "d" (get_fs().seg));
if (mmusr & (MMU_I|MMU_B|MMU_L))
return 0;
descaddr = phys_to_virt((unsigned long)descaddr);
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 74f23a4..c8d6efb 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -19,6 +19,7 @@
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP
select GENERIC_CPU_DEVICES
+ select GENERIC_ATOMIC64
config SWAP
def_bool n
diff --git a/arch/microblaze/include/asm/atomic.h b/arch/microblaze/include/asm/atomic.h
index 6d2e1d4..615f539 100644
--- a/arch/microblaze/include/asm/atomic.h
+++ b/arch/microblaze/include/asm/atomic.h
@@ -2,6 +2,7 @@
#define _ASM_MICROBLAZE_ATOMIC_H
#include <asm-generic/atomic.h>
+#include <asm-generic/atomic64.h>
/*
* Atomically test *v and decrement if it is greater than 0.
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index d4fc1a9..604cd9d 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -26,7 +26,6 @@
#include <linux/cache.h>
#include <linux/of_platform.h>
#include <linux/dma-mapping.h>
-#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/entry.h>
#include <asm/cpuinfo.h>
@@ -227,23 +226,5 @@
return 0;
}
+
arch_initcall(setup_bus_notifier);
-
-static DEFINE_PER_CPU(struct cpu, cpu_devices);
-
-static int __init topology_init(void)
-{
- int i, ret;
-
- for_each_present_cpu(i) {
- struct cpu *c = &per_cpu(cpu_devices, i);
-
- ret = register_cpu(c, i);
- if (ret)
- printk(KERN_WARNING "topology_init: register_cpu %d "
- "failed (%d)\n", i, ret);
- }
-
- return 0;
-}
-subsys_initcall(topology_init);
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index e9f3533..0ad2f1e 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -88,7 +88,6 @@
KBUILD_AFLAGS += $(aflags-y)
OBJCOPYFLAGS := -O binary
-LDFLAGS_vmlinux := -e start
head-y := arch/s390/kernel/head.o
head-y += arch/s390/kernel/$(if $(CONFIG_64BIT),head64.o,head31.o)
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index e4c79eb..21109c6 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -9,12 +9,12 @@
#ifndef CONFIG_64BIT
OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
OUTPUT_ARCH(s390)
-ENTRY(_start)
+ENTRY(startup)
jiffies = jiffies_64 + 4;
#else
OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
OUTPUT_ARCH(s390:64-bit)
-ENTRY(_start)
+ENTRY(startup)
jiffies = jiffies_64;
#endif
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9665799..ca5580e 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -33,6 +33,7 @@
config SPARC32
def_bool !64BIT
select GENERIC_ATOMIC64
+ select CLZ_TAB
config SPARC64
def_bool 64BIT
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 422c16d..e611651 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -399,6 +399,9 @@
timers_global = (void __iomem *)
(unsigned long) addr[num_cpu_timers];
+ /* Every per-cpu timer works in timer mode */
+ sbus_writel(0x00000000, &timers_global->timer_config);
+
sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit);
master_l10_counter = &timers_global->l10_count;
diff --git a/arch/sparc/lib/divdi3.S b/arch/sparc/lib/divdi3.S
index 681b368..d74bc09 100644
--- a/arch/sparc/lib/divdi3.S
+++ b/arch/sparc/lib/divdi3.S
@@ -17,23 +17,9 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
- .data
- .align 8
- .globl __clz_tab
-__clz_tab:
- .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
- .byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
- .size __clz_tab,256
- .global .udiv
-
.text
.align 4
+ .global .udiv
.globl __divdi3
__divdi3:
save %sp,-104,%sp
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 864cc6e..5bed94e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -360,7 +360,6 @@
depends on NUMA
depends on SMP
depends on X86_X2APIC
- depends on !EDAC_AMD64
---help---
Adds support for Numascale NumaChip large-SMP systems. Needed to
enable more than ~168 cores.
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 3a19d04..7116dcb 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -321,6 +321,8 @@
default: /* Ignore other PT_* */ break;
}
}
+
+ free(phdrs);
}
asmlinkage void decompress_kernel(void *rmode, memptr heap,
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index 0c9fa27..b3b7332 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -145,13 +145,13 @@
#ifdef __HAVE_ARCH_CMPXCHG
#define cmpxchg(ptr, old, new) \
- __cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define sync_cmpxchg(ptr, old, new) \
- __sync_cmpxchg((ptr), (old), (new), sizeof(*ptr))
+ __sync_cmpxchg(ptr, old, new, sizeof(*(ptr)))
#define cmpxchg_local(ptr, old, new) \
- __cmpxchg_local((ptr), (old), (new), sizeof(*ptr))
+ __cmpxchg_local(ptr, old, new, sizeof(*(ptr)))
#endif
/*
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
index 17c5d4b..8d67d42 100644
--- a/arch/x86/include/asm/cpufeature.h
+++ b/arch/x86/include/asm/cpufeature.h
@@ -159,6 +159,7 @@
#define X86_FEATURE_WDT (6*32+13) /* Watchdog timer */
#define X86_FEATURE_LWP (6*32+15) /* Light Weight Profiling */
#define X86_FEATURE_FMA4 (6*32+16) /* 4 operands MAC instructions */
+#define X86_FEATURE_TCE (6*32+17) /* translation cache extension */
#define X86_FEATURE_NODEID_MSR (6*32+19) /* NodeId MSR */
#define X86_FEATURE_TBM (6*32+21) /* trailing bit manipulations */
#define X86_FEATURE_TOPOEXT (6*32+22) /* topology extensions CPUID leafs */
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 54a13aa..21f7385 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -318,13 +318,13 @@
/* UV global physical address --> socket phys RAM */
static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
{
- unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+ unsigned long paddr;
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
- gpa = gpa & uv_hub_info->gpa_mask;
+ paddr = gpa & uv_hub_info->gpa_mask;
if (paddr >= remap_base && paddr < remap_base + remap_top)
paddr -= remap_base;
return paddr;
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index 1aae78f..4025fe4 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -252,7 +252,8 @@
unsigned short ss;
unsigned long sp;
#endif
- printk(KERN_EMERG "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
+ printk(KERN_DEFAULT
+ "%s: %04lx [#%d] ", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
printk("PREEMPT ");
#endif
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 6d728d9..17107bd 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -129,7 +129,7 @@
if (!stack) {
if (regs)
stack = (unsigned long *)regs->sp;
- else if (task && task != current)
+ else if (task != current)
stack = (unsigned long *)task->thread.sp;
else
stack = &dummy;
@@ -269,11 +269,11 @@
unsigned char c;
u8 *ip;
- printk(KERN_EMERG "Stack:\n");
+ printk(KERN_DEFAULT "Stack:\n");
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
- 0, KERN_EMERG);
+ 0, KERN_DEFAULT);
- printk(KERN_EMERG "Code: ");
+ printk(KERN_DEFAULT "Code: ");
ip = (u8 *)regs->ip - code_prologue;
if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index fe86493..ac0417b 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -311,13 +311,33 @@
return state;
}
+/*
+ * AMD microcode firmware naming convention, up to family 15h they are in
+ * the legacy file:
+ *
+ * amd-ucode/microcode_amd.bin
+ *
+ * This legacy file is always smaller than 2K in size.
+ *
+ * Starting at family 15h they are in family specific firmware files:
+ *
+ * amd-ucode/microcode_amd_fam15h.bin
+ * amd-ucode/microcode_amd_fam16h.bin
+ * ...
+ *
+ * These might be larger than 2K.
+ */
static enum ucode_state request_microcode_amd(int cpu, struct device *device)
{
- const char *fw_name = "amd-ucode/microcode_amd.bin";
+ char fw_name[36] = "amd-ucode/microcode_amd.bin";
const struct firmware *fw;
enum ucode_state ret = UCODE_NFOUND;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
- if (request_firmware(&fw, fw_name, device)) {
+ if (c->x86 >= 0x15)
+ snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
+
+ if (request_firmware(&fw, (const char *)fw_name, device)) {
pr_err("failed to load file %s\n", fw_name);
goto out;
}
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 37a458b..d840e69 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -39,6 +39,14 @@
enum reboot_type reboot_type = BOOT_ACPI;
int reboot_force;
+/* This variable is used privately to keep track of whether or not
+ * reboot_type is still set to its default value (i.e., reboot= hasn't
+ * been set on the command line). This is needed so that we can
+ * suppress DMI scanning for reboot quirks. Without it, it's
+ * impossible to override a faulty reboot quirk without recompiling.
+ */
+static int reboot_default = 1;
+
#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
static int reboot_cpu = -1;
#endif
@@ -67,6 +75,12 @@
static int __init reboot_setup(char *str)
{
for (;;) {
+ /* Having anything passed on the command line via
+ * reboot= will cause us to disable DMI checking
+ * below.
+ */
+ reboot_default = 0;
+
switch (*str) {
case 'w':
reboot_mode = 0x1234;
@@ -295,14 +309,6 @@
DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
},
},
- { /* Handle problems with rebooting on VersaLogic Menlow boards */
- .callback = set_bios_reboot,
- .ident = "VersaLogic Menlow based board",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "VersaLogic Corporation"),
- DMI_MATCH(DMI_BOARD_NAME, "VersaLogic Menlow board"),
- },
- },
{ /* Handle reboot issue on Acer Aspire one */
.callback = set_kbd_reboot,
.ident = "Acer Aspire One A110",
@@ -316,7 +322,12 @@
static int __init reboot_init(void)
{
- dmi_check_system(reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(reboot_dmi_table);
+ }
return 0;
}
core_initcall(reboot_init);
@@ -465,7 +476,12 @@
static int __init pci_reboot_init(void)
{
- dmi_check_system(pci_reboot_dmi_table);
+ /* Only do the DMI check if reboot_type hasn't been overridden
+ * on the command line
+ */
+ if (reboot_default) {
+ dmi_check_system(pci_reboot_dmi_table);
+ }
return 0;
}
core_initcall(pci_reboot_init);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 9d74824..f0b4caf 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -673,7 +673,7 @@
stackend = end_of_stack(tsk);
if (tsk != &init_task && *stackend != STACK_END_MAGIC)
- printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
+ printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
tsk->thread.cr2 = address;
tsk->thread.trap_no = 14;
@@ -684,7 +684,7 @@
sig = 0;
/* Executive summary in case the body of the oops scrolled away */
- printk(KERN_EMERG "CR2: %016lx\n", address);
+ printk(KERN_DEFAULT "CR2: %016lx\n", address);
oops_end(flags, regs, sig);
}
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 9be4cff..3ae0e61 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1851,6 +1851,8 @@
bcp->cong_reps = congested_reps;
bcp->cong_period = congested_period;
bcp->clocks_per_100_usec = usec_2_cycles(100);
+ spin_lock_init(&bcp->queue_lock);
+ spin_lock_init(&bcp->uvhub_lock);
}
}
diff --git a/arch/x86/platform/uv/uv_irq.c b/arch/x86/platform/uv/uv_irq.c
index 374a05d..f25c276 100644
--- a/arch/x86/platform/uv/uv_irq.c
+++ b/arch/x86/platform/uv/uv_irq.c
@@ -25,7 +25,7 @@
int irq;
};
-static spinlock_t uv_irq_lock;
+static DEFINE_SPINLOCK(uv_irq_lock);
static struct rb_root uv_irq_root;
static int uv_set_irq_affinity(struct irq_data *, const struct cpumask *, bool);
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index cc9b1e1..d69cc6c 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -116,9 +116,26 @@
}
#endif /* CONFIG_XEN_DEBUG_FS */
+/*
+ * Size struct xen_spinlock so it's the same as arch_spinlock_t.
+ */
+#if NR_CPUS < 256
+typedef u8 xen_spinners_t;
+# define inc_spinners(xl) \
+ asm(LOCK_PREFIX " incb %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+ asm(LOCK_PREFIX " decb %0" : "+m" ((xl)->spinners) : : "memory");
+#else
+typedef u16 xen_spinners_t;
+# define inc_spinners(xl) \
+ asm(LOCK_PREFIX " incw %0" : "+m" ((xl)->spinners) : : "memory");
+# define dec_spinners(xl) \
+ asm(LOCK_PREFIX " decw %0" : "+m" ((xl)->spinners) : : "memory");
+#endif
+
struct xen_spinlock {
unsigned char lock; /* 0 -> free; 1 -> locked */
- unsigned short spinners; /* count of waiting cpus */
+ xen_spinners_t spinners; /* count of waiting cpus */
};
static int xen_spin_is_locked(struct arch_spinlock *lock)
@@ -164,8 +181,7 @@
wmb(); /* set lock of interest before count */
- asm(LOCK_PREFIX " incw %0"
- : "+m" (xl->spinners) : : "memory");
+ inc_spinners(xl);
return prev;
}
@@ -176,8 +192,7 @@
*/
static inline void unspinning_lock(struct xen_spinlock *xl, struct xen_spinlock *prev)
{
- asm(LOCK_PREFIX " decw %0"
- : "+m" (xl->spinners) : : "memory");
+ dec_spinners(xl);
wmb(); /* decrement count before restoring lock */
__this_cpu_write(lock_spinners, prev);
}
@@ -373,6 +388,8 @@
void __init xen_init_spinlocks(void)
{
+ BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
+
pv_lock_ops.spin_is_locked = xen_spin_is_locked;
pv_lock_ops.spin_is_contended = xen_spin_is_contended;
pv_lock_ops.spin_lock = xen_spin_lock;
diff --git a/arch/xtensa/include/asm/string.h b/arch/xtensa/include/asm/string.h
index 5fb8c27..405a8c4 100644
--- a/arch/xtensa/include/asm/string.h
+++ b/arch/xtensa/include/asm/string.h
@@ -118,7 +118,4 @@
/* Don't build bcopy at all ... */
#define __HAVE_ARCH_BCOPY
-#define __HAVE_ARCH_MEMSCAN
-#define memscan memchr
-
#endif /* _XTENSA_STRING_H */
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 9ed9f60..88f160b 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -21,8 +21,6 @@
#include <linux/percpu.h>
#include <asm/byteorder.h>
-static DEFINE_PER_CPU(u64[80], msg_schedule);
-
static inline u64 Ch(u64 x, u64 y, u64 z)
{
return z ^ (x & (y ^ z));
@@ -80,7 +78,7 @@
static inline void BLEND_OP(int I, u64 *W)
{
- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]);
}
static void
@@ -89,38 +87,48 @@
u64 a, b, c, d, e, f, g, h, t1, t2;
int i;
- u64 *W = get_cpu_var(msg_schedule);
+ u64 W[16];
/* load the input */
for (i = 0; i < 16; i++)
LOAD_OP(i, W, input);
- for (i = 16; i < 80; i++) {
- BLEND_OP(i, W);
- }
-
/* load the state into our registers */
a=state[0]; b=state[1]; c=state[2]; d=state[3];
e=state[4]; f=state[5]; g=state[6]; h=state[7];
- /* now iterate */
- for (i=0; i<80; i+=8) {
- t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ];
- t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
- t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
- t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
- t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
- t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
- t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
- t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
- t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
- t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
- t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
- t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
- t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
- t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
- t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
- t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
+#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \
+ t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \
+ t2 = e0(a) + Maj(a, b, c); \
+ d += t1; \
+ h = t1 + t2
+
+#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \
+ BLEND_OP(i, W); \
+ t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \
+ t2 = e0(a) + Maj(a, b, c); \
+ d += t1; \
+ h = t1 + t2
+
+ for (i = 0; i < 16; i += 8) {
+ SHA512_0_15(i, a, b, c, d, e, f, g, h);
+ SHA512_0_15(i + 1, h, a, b, c, d, e, f, g);
+ SHA512_0_15(i + 2, g, h, a, b, c, d, e, f);
+ SHA512_0_15(i + 3, f, g, h, a, b, c, d, e);
+ SHA512_0_15(i + 4, e, f, g, h, a, b, c, d);
+ SHA512_0_15(i + 5, d, e, f, g, h, a, b, c);
+ SHA512_0_15(i + 6, c, d, e, f, g, h, a, b);
+ SHA512_0_15(i + 7, b, c, d, e, f, g, h, a);
+ }
+ for (i = 16; i < 80; i += 8) {
+ SHA512_16_79(i, a, b, c, d, e, f, g, h);
+ SHA512_16_79(i + 1, h, a, b, c, d, e, f, g);
+ SHA512_16_79(i + 2, g, h, a, b, c, d, e, f);
+ SHA512_16_79(i + 3, f, g, h, a, b, c, d, e);
+ SHA512_16_79(i + 4, e, f, g, h, a, b, c, d);
+ SHA512_16_79(i + 5, d, e, f, g, h, a, b, c);
+ SHA512_16_79(i + 6, c, d, e, f, g, h, a, b);
+ SHA512_16_79(i + 7, b, c, d, e, f, g, h, a);
}
state[0] += a; state[1] += b; state[2] += c; state[3] += d;
@@ -128,8 +136,6 @@
/* erase our data */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
- memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
- put_cpu_var(msg_schedule);
}
static int
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 2c8272d..610f999 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,6 +1,6 @@
# Makefile for the Linux device tree
-obj-y := core.o sys.o bus.o dd.o syscore.o \
+obj-y := core.o bus.o dd.o syscore.o \
driver.o class.o platform.o \
cpu.o firmware.o init.o map.o devres.o \
attribute_container.o transport_class.o \
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4a67cc0..74dda4f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -632,6 +632,11 @@
* may be used for reference counting of @dev after calling this
* function.
*
+ * All fields in @dev must be initialized by the caller to 0, except
+ * for those explicitly set to some other value. The simplest
+ * approach is to use kzalloc() to allocate the structure containing
+ * @dev.
+ *
* NOTE: Use put_device() to give up your reference instead of freeing
* @dev directly once you have called this function.
*/
@@ -930,6 +935,13 @@
* to the global and sibling lists for the device, then
* adds it to the other relevant subsystems of the driver model.
*
+ * Do not call this routine or device_register() more than once for
+ * any device structure. The driver model core is not designed to work
+ * with devices that get unregistered and then spring back to life.
+ * (Among other things, it's very hard to guarantee that all references
+ * to the previous incarnation of @dev have been dropped.) Allocate
+ * and register a fresh new struct device instead.
+ *
* NOTE: _Never_ directly free @dev after calling this function, even
* if it returned an error! Always use put_device() to give up your
* reference instead.
@@ -1022,7 +1034,7 @@
device_pm_add(dev);
/* Notify clients of device addition. This call must come
- * after dpm_sysf_add() and before kobject_uevent().
+ * after dpm_sysfs_add() and before kobject_uevent().
*/
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
@@ -1090,6 +1102,9 @@
* have a clearly defined need to use and refcount the device
* before it is added to the hierarchy.
*
+ * For more information, see the kerneldoc for device_initialize()
+ * and device_add().
+ *
* NOTE: _Never_ directly free @dev after calling this function, even
* if it returned an error! Always use put_device() to give up the
* reference initialized in this function instead.
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index be10a4f..6555803 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -284,6 +284,9 @@
map->precious_reg = config->precious_reg;
map->cache_type = config->cache_type;
+ map->cache_bypass = false;
+ map->cache_only = false;
+
ret = regcache_init(map, config);
mutex_unlock(&map->lock);
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
deleted file mode 100644
index 409f5ce..0000000
--- a/drivers/base/sys.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * sys.c - pseudo-bus for system 'devices' (cpus, PICs, timers, etc)
- *
- * Copyright (c) 2002-3 Patrick Mochel
- * 2002-3 Open Source Development Lab
- *
- * This file is released under the GPLv2
- *
- * This exports a 'system' bus type.
- * By default, a 'sys' bus gets added to the root of the system. There will
- * always be core system devices. Devices can use sysdev_register() to
- * add themselves as children of the system bus.
- */
-
-#include <linux/sysdev.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/string.h>
-#include <linux/pm.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-
-#include "base.h"
-
-#define to_sysdev(k) container_of(k, struct sys_device, kobj)
-#define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
-
-
-static ssize_t
-sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
-{
- struct sys_device *sysdev = to_sysdev(kobj);
- struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
- if (sysdev_attr->show)
- return sysdev_attr->show(sysdev, sysdev_attr, buffer);
- return -EIO;
-}
-
-
-static ssize_t
-sysdev_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct sys_device *sysdev = to_sysdev(kobj);
- struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
-
- if (sysdev_attr->store)
- return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
- return -EIO;
-}
-
-static const struct sysfs_ops sysfs_ops = {
- .show = sysdev_show,
- .store = sysdev_store,
-};
-
-static struct kobj_type ktype_sysdev = {
- .sysfs_ops = &sysfs_ops,
-};
-
-
-int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
-{
- return sysfs_create_file(&s->kobj, &a->attr);
-}
-
-
-void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
-{
- sysfs_remove_file(&s->kobj, &a->attr);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_create_file);
-EXPORT_SYMBOL_GPL(sysdev_remove_file);
-
-#define to_sysdev_class(k) container_of(k, struct sysdev_class, kset.kobj)
-#define to_sysdev_class_attr(a) container_of(a, \
- struct sysdev_class_attribute, attr)
-
-static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
- char *buffer)
-{
- struct sysdev_class *class = to_sysdev_class(kobj);
- struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
- if (class_attr->show)
- return class_attr->show(class, class_attr, buffer);
- return -EIO;
-}
-
-static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
- const char *buffer, size_t count)
-{
- struct sysdev_class *class = to_sysdev_class(kobj);
- struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
-
- if (class_attr->store)
- return class_attr->store(class, class_attr, buffer, count);
- return -EIO;
-}
-
-static const struct sysfs_ops sysfs_class_ops = {
- .show = sysdev_class_show,
- .store = sysdev_class_store,
-};
-
-static struct kobj_type ktype_sysdev_class = {
- .sysfs_ops = &sysfs_class_ops,
-};
-
-int sysdev_class_create_file(struct sysdev_class *c,
- struct sysdev_class_attribute *a)
-{
- return sysfs_create_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_create_file);
-
-void sysdev_class_remove_file(struct sysdev_class *c,
- struct sysdev_class_attribute *a)
-{
- sysfs_remove_file(&c->kset.kobj, &a->attr);
-}
-EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
-
-extern struct kset *system_kset;
-
-int sysdev_class_register(struct sysdev_class *cls)
-{
- int retval;
-
- pr_debug("Registering sysdev class '%s'\n", cls->name);
-
- INIT_LIST_HEAD(&cls->drivers);
- memset(&cls->kset.kobj, 0x00, sizeof(struct kobject));
- cls->kset.kobj.parent = &system_kset->kobj;
- cls->kset.kobj.ktype = &ktype_sysdev_class;
- cls->kset.kobj.kset = system_kset;
-
- retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
- if (retval)
- return retval;
-
- retval = kset_register(&cls->kset);
- if (!retval && cls->attrs)
- retval = sysfs_create_files(&cls->kset.kobj,
- (const struct attribute **)cls->attrs);
- return retval;
-}
-
-void sysdev_class_unregister(struct sysdev_class *cls)
-{
- pr_debug("Unregistering sysdev class '%s'\n",
- kobject_name(&cls->kset.kobj));
- if (cls->attrs)
- sysfs_remove_files(&cls->kset.kobj,
- (const struct attribute **)cls->attrs);
- kset_unregister(&cls->kset);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_class_register);
-EXPORT_SYMBOL_GPL(sysdev_class_unregister);
-
-static DEFINE_MUTEX(sysdev_drivers_lock);
-
-/*
- * @dev != NULL means that we're unwinding because some drv->add()
- * failed for some reason. You need to grab sysdev_drivers_lock before
- * calling this.
- */
-static void __sysdev_driver_remove(struct sysdev_class *cls,
- struct sysdev_driver *drv,
- struct sys_device *from_dev)
-{
- struct sys_device *dev = from_dev;
-
- list_del_init(&drv->entry);
- if (!cls)
- return;
-
- if (!drv->remove)
- goto kset_put;
-
- if (dev)
- list_for_each_entry_continue_reverse(dev, &cls->kset.list,
- kobj.entry)
- drv->remove(dev);
- else
- list_for_each_entry(dev, &cls->kset.list, kobj.entry)
- drv->remove(dev);
-
-kset_put:
- kset_put(&cls->kset);
-}
-
-/**
- * sysdev_driver_register - Register auxiliary driver
- * @cls: Device class driver belongs to.
- * @drv: Driver.
- *
- * @drv is inserted into @cls->drivers to be
- * called on each operation on devices of that class. The refcount
- * of @cls is incremented.
- */
-int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
-{
- struct sys_device *dev = NULL;
- int err = 0;
-
- if (!cls) {
- WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
- __func__);
- return -EINVAL;
- }
-
- /* Check whether this driver has already been added to a class. */
- if (drv->entry.next && !list_empty(&drv->entry))
- WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already"
- " been registered to a class, something is wrong, but "
- "will forge on!\n", cls->name, drv);
-
- mutex_lock(&sysdev_drivers_lock);
- if (cls && kset_get(&cls->kset)) {
- list_add_tail(&drv->entry, &cls->drivers);
-
- /* If devices of this class already exist, tell the driver */
- if (drv->add) {
- list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
- err = drv->add(dev);
- if (err)
- goto unwind;
- }
- }
- } else {
- err = -EINVAL;
- WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
- }
-
- goto unlock;
-
-unwind:
- __sysdev_driver_remove(cls, drv, dev);
-
-unlock:
- mutex_unlock(&sysdev_drivers_lock);
- return err;
-}
-
-/**
- * sysdev_driver_unregister - Remove an auxiliary driver.
- * @cls: Class driver belongs to.
- * @drv: Driver.
- */
-void sysdev_driver_unregister(struct sysdev_class *cls,
- struct sysdev_driver *drv)
-{
- mutex_lock(&sysdev_drivers_lock);
- __sysdev_driver_remove(cls, drv, NULL);
- mutex_unlock(&sysdev_drivers_lock);
-}
-EXPORT_SYMBOL_GPL(sysdev_driver_register);
-EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
-
-/**
- * sysdev_register - add a system device to the tree
- * @sysdev: device in question
- *
- */
-int sysdev_register(struct sys_device *sysdev)
-{
- int error;
- struct sysdev_class *cls = sysdev->cls;
-
- if (!cls)
- return -EINVAL;
-
- pr_debug("Registering sys device of class '%s'\n",
- kobject_name(&cls->kset.kobj));
-
- /* initialize the kobject to 0, in case it had previously been used */
- memset(&sysdev->kobj, 0x00, sizeof(struct kobject));
-
- /* Make sure the kset is set */
- sysdev->kobj.kset = &cls->kset;
-
- /* Register the object */
- error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
- "%s%d", kobject_name(&cls->kset.kobj),
- sysdev->id);
-
- if (!error) {
- struct sysdev_driver *drv;
-
- pr_debug("Registering sys device '%s'\n",
- kobject_name(&sysdev->kobj));
-
- mutex_lock(&sysdev_drivers_lock);
- /* Generic notification is implicit, because it's that
- * code that should have called us.
- */
-
- /* Notify class auxiliary drivers */
- list_for_each_entry(drv, &cls->drivers, entry) {
- if (drv->add)
- drv->add(sysdev);
- }
- mutex_unlock(&sysdev_drivers_lock);
- kobject_uevent(&sysdev->kobj, KOBJ_ADD);
- }
-
- return error;
-}
-
-void sysdev_unregister(struct sys_device *sysdev)
-{
- struct sysdev_driver *drv;
-
- mutex_lock(&sysdev_drivers_lock);
- list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
- if (drv->remove)
- drv->remove(sysdev);
- }
- mutex_unlock(&sysdev_drivers_lock);
-
- kobject_put(&sysdev->kobj);
-}
-
-EXPORT_SYMBOL_GPL(sysdev_register);
-EXPORT_SYMBOL_GPL(sysdev_unregister);
-
-#define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
-
-ssize_t sysdev_store_ulong(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- const char *buf, size_t size)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- char *end;
- unsigned long new = simple_strtoul(buf, &end, 0);
- if (end == buf)
- return -EINVAL;
- *(unsigned long *)(ea->var) = new;
- /* Always return full write size even if we didn't consume all */
- return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_ulong);
-
-ssize_t sysdev_show_ulong(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- char *buf)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_ulong);
-
-ssize_t sysdev_store_int(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- const char *buf, size_t size)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- char *end;
- long new = simple_strtol(buf, &end, 0);
- if (end == buf || new > INT_MAX || new < INT_MIN)
- return -EINVAL;
- *(int *)(ea->var) = new;
- /* Always return full write size even if we didn't consume all */
- return size;
-}
-EXPORT_SYMBOL_GPL(sysdev_store_int);
-
-ssize_t sysdev_show_int(struct sys_device *sysdev,
- struct sysdev_attribute *attr,
- char *buf)
-{
- struct sysdev_ext_attribute *ea = to_ext_attr(attr);
- return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
-}
-EXPORT_SYMBOL_GPL(sysdev_show_int);
-
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 3fd31de..a6278e7 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -380,6 +380,7 @@
rbdc = __rbd_client_find(opt);
if (rbdc) {
ceph_destroy_options(opt);
+ kfree(rbd_opts);
/* using an existing client */
kref_get(&rbdc->kref);
@@ -406,15 +407,15 @@
/*
* Destroy ceph client
+ *
+ * Caller must hold node_lock.
*/
static void rbd_client_release(struct kref *kref)
{
struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref);
dout("rbd_release_client %p\n", rbdc);
- spin_lock(&node_lock);
list_del(&rbdc->node);
- spin_unlock(&node_lock);
ceph_destroy_client(rbdc->client);
kfree(rbdc->rbd_opts);
@@ -427,7 +428,9 @@
*/
static void rbd_put_client(struct rbd_device *rbd_dev)
{
+ spin_lock(&node_lock);
kref_put(&rbd_dev->rbd_client->kref, rbd_client_release);
+ spin_unlock(&node_lock);
rbd_dev->rbd_client = NULL;
rbd_dev->client = NULL;
}
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 4b71647..317c28c 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -194,10 +194,10 @@
err_out:
if (bridge->driver->needs_scratch_page) {
- void *va = page_address(bridge->scratch_page_page);
+ struct page *page = bridge->scratch_page_page;
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
@@ -221,10 +221,10 @@
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page) {
- void *va = page_address(bridge->scratch_page_page);
+ struct page *page = bridge->scratch_page_page;
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP);
- bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP);
+ bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE);
}
}
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 97f87b2..f4aed5f 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -1343,7 +1343,7 @@
tasklet_init(&atchan->tasklet, atc_tasklet,
(unsigned long)atchan);
- atc_enable_irq(atchan);
+ atc_enable_chan_irq(atdma, i);
}
/* set base routines */
@@ -1410,7 +1410,7 @@
struct at_dma_chan *atchan = to_at_dma_chan(chan);
/* Disable interrupts */
- atc_disable_irq(atchan);
+ atc_disable_chan_irq(atdma, chan->chan_id);
tasklet_disable(&atchan->tasklet);
tasklet_kill(&atchan->tasklet);
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index dcaedfc..a8d3277 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -327,28 +327,27 @@
}
-static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
{
- struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
- u32 ebci;
+ u32 ebci;
/* enable interrupts on buffer transfer completion & error */
- ebci = AT_DMA_BTC(atchan->chan_common.chan_id)
- | AT_DMA_ERR(atchan->chan_common.chan_id);
+ ebci = AT_DMA_BTC(chan_id)
+ | AT_DMA_ERR(chan_id);
if (on)
dma_writel(atdma, EBCIER, ebci);
else
dma_writel(atdma, EBCIDR, ebci);
}
-static inline void atc_enable_irq(struct at_dma_chan *atchan)
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 1);
+ atc_setup_irq(atdma, chan_id, 1);
}
-static inline void atc_disable_irq(struct at_dma_chan *atchan)
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 0);
+ atc_setup_irq(atdma, chan_id, 0);
}
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 2b8661b..24225f0 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -599,7 +599,7 @@
}
if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
cnt = dmatest_add_threads(dtc, DMA_PQ);
- thread_count += cnt > 0 ?: 0;
+ thread_count += cnt > 0 ? cnt : 0;
}
pr_info("dmatest: Started %u threads using %s\n",
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index a8af379..8bc5acf 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1102,11 +1102,13 @@
case DMA_SLAVE_CONFIG:
if (dmaengine_cfg->direction == DMA_DEV_TO_MEM) {
sdmac->per_address = dmaengine_cfg->src_addr;
- sdmac->watermark_level = dmaengine_cfg->src_maxburst;
+ sdmac->watermark_level = dmaengine_cfg->src_maxburst *
+ dmaengine_cfg->src_addr_width;
sdmac->word_size = dmaengine_cfg->src_addr_width;
} else {
sdmac->per_address = dmaengine_cfg->dst_addr;
- sdmac->watermark_level = dmaengine_cfg->dst_maxburst;
+ sdmac->watermark_level = dmaengine_cfg->dst_maxburst *
+ dmaengine_cfg->dst_addr_width;
sdmac->word_size = dmaengine_cfg->dst_addr_width;
}
sdmac->direction = dmaengine_cfg->direction;
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index 54043cd..812fd76 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -1262,7 +1262,8 @@
INIT_LIST_HEAD(&shdev->common.channels);
- dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
+ if (!pdata->slave_only)
+ dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
if (pdata->slave && pdata->slave_num)
dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 6628fea..7f5f0da 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -263,6 +263,7 @@
static char ohci_driver_name[] = KBUILD_MODNAME;
#define PCI_DEVICE_ID_AGERE_FW643 0x5901
+#define PCI_DEVICE_ID_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
#define PCI_DEVICE_ID_TI_TSB12LV26 0x8020
@@ -289,6 +290,9 @@
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+ QUIRK_RESET_PACKET},
+
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
QUIRK_NO_MSI},
@@ -299,7 +303,7 @@
QUIRK_NO_MSI},
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_CYCLE_TIMER},
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
index 5b69480..ddfacc5 100644
--- a/drivers/gpio/gpio-lpc32xx.c
+++ b/drivers/gpio/gpio-lpc32xx.c
@@ -96,7 +96,7 @@
};
static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
- "gpi000", "gpio01", "gpio02", "gpio03",
+ "gpio00", "gpio01", "gpio02", "gpio03",
"gpio04", "gpio05"
};
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 03d6dd5..f0febe5 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -448,6 +448,7 @@
chip->reg = chip->base;
chip->ch = i;
mutex_init(&chip->lock);
+ spin_lock_init(&chip->spinlock);
ioh_gpio_setup(chip, num_ports[i]);
ret = gpiochip_add(&chip->gpio);
if (ret) {
diff --git a/drivers/gpio/gpio-pch.c b/drivers/gpio/gpio-pch.c
index 68fa55e..e8729cc 100644
--- a/drivers/gpio/gpio-pch.c
+++ b/drivers/gpio/gpio-pch.c
@@ -392,6 +392,7 @@
chip->reg = chip->base;
pci_set_drvdata(pdev, chip);
mutex_init(&chip->lock);
+ spin_lock_init(&chip->spinlock);
pch_gpio_setup(chip);
ret = gpiochip_add(&chip->gpio);
if (ret) {
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index a766177..0a79a11 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2387,27 +2387,30 @@
};
#if defined(CONFIG_ARCH_EXYNOS4) && defined(CONFIG_OF)
-static int exynos4_gpio_xlate(struct gpio_chip *gc, struct device_node *np,
- const void *gpio_spec, u32 *flags)
+static int exynos4_gpio_xlate(struct gpio_chip *gc,
+ const struct of_phandle_args *gpiospec, u32 *flags)
{
- const __be32 *gpio = gpio_spec;
- const u32 n = be32_to_cpup(gpio);
- unsigned int pin = gc->base + be32_to_cpu(gpio[0]);
+ unsigned int pin;
if (WARN_ON(gc->of_gpio_n_cells < 4))
return -EINVAL;
- if (n > gc->ngpio)
+ if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
- if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(be32_to_cpu(gpio[1]))))
+ if (gpiospec->args[0] > gc->ngpio)
+ return -EINVAL;
+
+ pin = gc->base + gpiospec->args[0];
+
+ if (s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(gpiospec->args[1])))
pr_warn("gpio_xlate: failed to set pin function\n");
- if (s3c_gpio_setpull(pin, be32_to_cpu(gpio[2])))
+ if (s3c_gpio_setpull(pin, gpiospec->args[2]))
pr_warn("gpio_xlate: failed to set pin pull up/down\n");
- if (s5p_gpio_set_drvstr(pin, be32_to_cpu(gpio[3])))
+ if (s5p_gpio_set_drvstr(pin, gpiospec->args[3]))
pr_warn("gpio_xlate: failed to set pin drive strength\n");
- return n;
+ return gpiospec->args[0];
}
static const struct of_device_id exynos4_gpio_dt_match[] __initdata = {
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 3f46772..ba23790 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -101,7 +101,7 @@
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock.
*/
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{
struct drm_magic_entry *pt;
struct drm_hash_item *hash;
@@ -136,6 +136,8 @@
* If there is a magic number in drm_file::magic then use it, otherwise
* searches an unique non-zero magic number and add it associating it with \p
* file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
@@ -173,6 +175,8 @@
* \return zero if authentication successed, or a negative number otherwise.
*
* Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index c00cf15..6263b01 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -487,6 +487,11 @@
(long)old_encode_dev(file_priv->minor->device),
dev->open_count);
+ /* Release any auth tokens that might point to this file_priv,
+ (do that under the drm_global_mutex) */
+ if (file_priv->magic)
+ (void) drm_remove_magic(file_priv->master, file_priv->magic);
+
/* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master)
drm_master_release(dev, filp);
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 396e60c..f8625e2 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -140,7 +140,7 @@
obj->dev = dev;
obj->filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
if (IS_ERR(obj->filp))
- return -ENOMEM;
+ return PTR_ERR(obj->filp);
kref_init(&obj->refcount);
atomic_set(&obj->handle_count, 0);
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index f9aaa56..b9e5266 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -13,7 +13,7 @@
config DRM_EXYNOS_FIMD
tristate "Exynos DRM FIMD"
- depends on DRM_EXYNOS
+ depends on DRM_EXYNOS && !FB_S3C
default n
help
Choose this option if you want to use Exynos FIMD for DRM.
@@ -21,7 +21,7 @@
config DRM_EXYNOS_HDMI
tristate "Exynos DRM HDMI"
- depends on DRM_EXYNOS
+ depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_TV
help
Choose this option if you want to use Exynos HDMI for DRM.
If M is selected, the module will be called exynos_drm_hdmi
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ca83139..b6a737d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -158,7 +158,8 @@
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- pm_runtime_put_sync(subdrv_dev);
+ if (!ctx->suspended)
+ pm_runtime_put_sync(subdrv_dev);
break;
default:
DRM_DEBUG_KMS("unspecified mode %d\n", mode);
@@ -734,6 +735,46 @@
writel(val, ctx->regs + SHADOWCON);
}
+static int fimd_power_on(struct fimd_context *ctx, bool enable)
+{
+ struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+ struct device *dev = subdrv->manager.dev;
+
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ if (enable != false && enable != true)
+ return -EINVAL;
+
+ if (enable) {
+ int ret;
+
+ ret = clk_enable(ctx->bus_clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_enable(ctx->lcd_clk);
+ if (ret < 0) {
+ clk_disable(ctx->bus_clk);
+ return ret;
+ }
+
+ ctx->suspended = false;
+
+ /* if vblank was enabled status, enable it again. */
+ if (test_and_clear_bit(0, &ctx->irq_flags))
+ fimd_enable_vblank(dev);
+
+ fimd_apply(dev);
+ } else {
+ clk_disable(ctx->lcd_clk);
+ clk_disable(ctx->bus_clk);
+
+ ctx->suspended = true;
+ }
+
+ return 0;
+}
+
static int __devinit fimd_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -911,39 +952,30 @@
#ifdef CONFIG_PM_SLEEP
static int fimd_suspend(struct device *dev)
{
- int ret;
+ struct fimd_context *ctx = get_fimd_context(dev);
if (pm_runtime_suspended(dev))
return 0;
- ret = pm_runtime_suspend(dev);
- if (ret < 0)
- return ret;
-
- return 0;
+ /*
+ * do not use pm_runtime_suspend(). if pm_runtime_suspend() is
+ * called here, an error would be returned by that interface
+ * because the usage_count of pm runtime is more than 1.
+ */
+ return fimd_power_on(ctx, false);
}
static int fimd_resume(struct device *dev)
{
- int ret;
+ struct fimd_context *ctx = get_fimd_context(dev);
- ret = pm_runtime_resume(dev);
- if (ret < 0) {
- DRM_ERROR("failed to resume runtime pm.\n");
- return ret;
- }
-
- pm_runtime_disable(dev);
-
- ret = pm_runtime_set_active(dev);
- if (ret < 0) {
- DRM_ERROR("failed to active runtime pm.\n");
- pm_runtime_enable(dev);
- pm_runtime_suspend(dev);
- return ret;
- }
-
- pm_runtime_enable(dev);
+ /*
+ * if entered to sleep when lcd panel was on, the usage_count
+ * of pm runtime would still be 1 so in this case, fimd driver
+ * should be on directly not drawing on pm runtime interface.
+ */
+ if (!pm_runtime_suspended(dev))
+ return fimd_power_on(ctx, true);
return 0;
}
@@ -956,39 +988,16 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- clk_disable(ctx->lcd_clk);
- clk_disable(ctx->bus_clk);
-
- ctx->suspended = true;
- return 0;
+ return fimd_power_on(ctx, false);
}
static int fimd_runtime_resume(struct device *dev)
{
struct fimd_context *ctx = get_fimd_context(dev);
- int ret;
DRM_DEBUG_KMS("%s\n", __FILE__);
- ret = clk_enable(ctx->bus_clk);
- if (ret < 0)
- return ret;
-
- ret = clk_enable(ctx->lcd_clk);
- if (ret < 0) {
- clk_disable(ctx->bus_clk);
- return ret;
- }
-
- ctx->suspended = false;
-
- /* if vblank was enabled status, enable it again. */
- if (test_and_clear_bit(0, &ctx->irq_flags))
- fimd_enable_vblank(dev);
-
- fimd_apply(dev);
-
- return 0;
+ return fimd_power_on(ctx, true);
}
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index f48f7ce..3429d3f 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1116,8 +1116,8 @@
err_iomap:
iounmap(hdata->regs);
err_req_region:
- release_resource(hdata->regs_res);
- kfree(hdata->regs_res);
+ release_mem_region(hdata->regs_res->start,
+ resource_size(hdata->regs_res));
err_resource:
hdmi_resources_cleanup(hdata);
err_data:
@@ -1145,8 +1145,8 @@
iounmap(hdata->regs);
- release_resource(hdata->regs_res);
- kfree(hdata->regs_res);
+ release_mem_region(hdata->regs_res->start,
+ resource_size(hdata->regs_res));
/* hdmiphy i2c driver */
i2c_del_driver(&hdmiphy_driver);
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index 791c0ef..830dfdd6b 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -113,12 +113,12 @@
void psbfb_suspend(struct drm_device *dev)
{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct drm_framebuffer *fb;
console_lock();
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct fb_info *info = psbfb->fbdev;
fb_set_suspend(info, 1);
drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
@@ -129,12 +129,12 @@
void psbfb_resume(struct drm_device *dev)
{
- struct drm_framebuffer *fb = 0;
- struct psb_framebuffer *psbfb = to_psb_fb(fb);
+ struct drm_framebuffer *fb;
console_lock();
mutex_lock(&dev->mode_config.mutex);
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
+ struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct fb_info *info = psbfb->fbdev;
fb_set_suspend(info, 0);
drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index f7c17b2..7f4b4e1 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -886,7 +886,7 @@
}
/* Must be called with the lock held */
-void i810_driver_reclaim_buffers(struct drm_device *dev,
+static void i810_reclaim_buffers(struct drm_device *dev,
struct drm_file *file_priv)
{
struct drm_device_dma *dma = dev->dma;
@@ -1223,17 +1223,12 @@
if (dev_priv->page_flipping)
i810_do_cleanup_pageflip(dev);
}
+}
- if (file_priv->master && file_priv->master->lock.hw_lock) {
- drm_idlelock_take(&file_priv->master->lock);
- i810_driver_reclaim_buffers(dev, file_priv);
- drm_idlelock_release(&file_priv->master->lock);
- } else {
- /* master disappeared, clean up stuff anyway and hope nothing
- * goes wrong */
- i810_driver_reclaim_buffers(dev, file_priv);
- }
-
+void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv)
+{
+ i810_reclaim_buffers(dev, file_priv);
}
int i810_driver_dma_quiescent(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c
index 053f1ee..ec12f7d 100644
--- a/drivers/gpu/drm/i810/i810_drv.c
+++ b/drivers/gpu/drm/i810/i810_drv.c
@@ -63,6 +63,7 @@
.lastclose = i810_driver_lastclose,
.preclose = i810_driver_preclose,
.device_is_agp = i810_driver_device_is_agp,
+ .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked,
.dma_quiescent = i810_driver_dma_quiescent,
.ioctls = i810_ioctls,
.fops = &i810_driver_fops,
diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h
index 6e0acad..c9339f4 100644
--- a/drivers/gpu/drm/i810/i810_drv.h
+++ b/drivers/gpu/drm/i810/i810_drv.h
@@ -116,12 +116,14 @@
/* i810_dma.c */
extern int i810_driver_dma_quiescent(struct drm_device *dev);
-void i810_driver_reclaim_buffers(struct drm_device *dev,
- struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv);
extern int i810_driver_load(struct drm_device *, unsigned long flags);
extern void i810_driver_lastclose(struct drm_device *dev);
extern void i810_driver_preclose(struct drm_device *dev,
struct drm_file *file_priv);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
+ struct drm_file *file_priv);
extern int i810_driver_device_is_agp(struct drm_device *dev);
extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 1180798..deaa657 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -121,11 +121,11 @@
static void
describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
{
- seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s%s",
+ seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s",
&obj->base,
get_pin_flag(obj),
get_tiling_flag(obj),
- obj->base.size,
+ obj->base.size / 1024,
obj->base.read_domains,
obj->base.write_domain,
obj->last_rendering_seqno,
@@ -653,7 +653,7 @@
seq_printf(m, " Size : %08x\n", ring->size);
seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring));
seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring));
- if (IS_GEN6(dev)) {
+ if (IS_GEN6(dev) || IS_GEN7(dev)) {
seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring));
seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring));
}
@@ -1075,6 +1075,7 @@
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 rpmodectl1, gt_core_status, rcctl1;
+ unsigned forcewake_count;
int count=0, ret;
@@ -1082,9 +1083,13 @@
if (ret)
return ret;
- if (atomic_read(&dev_priv->forcewake_count)) {
- seq_printf(m, "RC information inaccurate because userspace "
- "holds a reference \n");
+ spin_lock_irq(&dev_priv->gt_lock);
+ forcewake_count = dev_priv->forcewake_count;
+ spin_unlock_irq(&dev_priv->gt_lock);
+
+ if (forcewake_count) {
+ seq_printf(m, "RC information inaccurate because somebody "
+ "holds a forcewake reference \n");
} else {
/* NB: we cannot use forcewake, else we read the wrong values */
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
@@ -1106,7 +1111,7 @@
seq_printf(m, "SW control enabled: %s\n",
yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) ==
GEN6_RP_MEDIA_SW_MODE));
- seq_printf(m, "RC6 Enabled: %s\n",
+ seq_printf(m, "RC1e Enabled: %s\n",
yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE));
seq_printf(m, "RC6 Enabled: %s\n",
yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
@@ -1398,9 +1403,13 @@
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned forcewake_count;
- seq_printf(m, "forcewake count = %d\n",
- atomic_read(&dev_priv->forcewake_count));
+ spin_lock_irq(&dev_priv->gt_lock);
+ forcewake_count = dev_priv->forcewake_count;
+ spin_unlock_irq(&dev_priv->gt_lock);
+
+ seq_printf(m, "forcewake count = %u\n", forcewake_count);
return 0;
}
@@ -1665,7 +1674,7 @@
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- if (!IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen < 6)
return 0;
ret = mutex_lock_interruptible(&dev->struct_mutex);
@@ -1682,7 +1691,7 @@
struct drm_device *dev = inode->i_private;
struct drm_i915_private *dev_priv = dev->dev_private;
- if (!IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen < 6)
return 0;
/*
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 5f4d589..ddfe3d9 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -2045,6 +2045,7 @@
if (!IS_I945G(dev) && !IS_I945GM(dev))
pci_enable_msi(dev->pdev);
+ spin_lock_init(&dev_priv->gt_lock);
spin_lock_init(&dev_priv->irq_lock);
spin_lock_init(&dev_priv->error_lock);
spin_lock_init(&dev_priv->rps_lock);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 8f71879..308f819 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -368,11 +368,12 @@
*/
void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{
- WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+ unsigned long irqflags;
- /* Forcewake is atomic in case we get in here without the lock */
- if (atomic_add_return(1, &dev_priv->forcewake_count) == 1)
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+ if (dev_priv->forcewake_count++ == 0)
dev_priv->display.force_wake_get(dev_priv);
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
}
void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
@@ -392,10 +393,12 @@
*/
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
{
- WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+ unsigned long irqflags;
- if (atomic_dec_and_test(&dev_priv->forcewake_count))
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+ if (--dev_priv->forcewake_count == 0)
dev_priv->display.force_wake_put(dev_priv);
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
}
void __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
@@ -597,9 +600,36 @@
static int gen6_do_reset(struct drm_device *dev, u8 flags)
{
struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+ unsigned long irqflags;
- I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL);
- return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+ /* Hold gt_lock across reset to prevent any register access
+ * with forcewake not set correctly
+ */
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags);
+
+ /* Reset the chip */
+
+ /* GEN6_GDRST is not in the gt power well, no need to check
+ * for fifo space for the write or forcewake the chip for
+ * the read
+ */
+ I915_WRITE_NOTRACE(GEN6_GDRST, GEN6_GRDOM_FULL);
+
+ /* Spin waiting for the device to ack the reset request */
+ ret = wait_for((I915_READ_NOTRACE(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
+
+ /* If reset with a user forcewake, try to restore, otherwise turn it off */
+ if (dev_priv->forcewake_count)
+ dev_priv->display.force_wake_get(dev_priv);
+ else
+ dev_priv->display.force_wake_put(dev_priv);
+
+ /* Restore fifo count */
+ dev_priv->gt_fifo_count = I915_READ_NOTRACE(GT_FIFO_FREE_ENTRIES);
+
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags);
+ return ret;
}
/**
@@ -643,9 +673,6 @@
case 7:
case 6:
ret = gen6_do_reset(dev, flags);
- /* If reset with a user forcewake, try to restore */
- if (atomic_read(&dev_priv->forcewake_count))
- __gen6_gt_force_wake_get(dev_priv);
break;
case 5:
ret = ironlake_do_reset(dev, flags);
@@ -927,9 +954,14 @@
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
u##x val = 0; \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
- gen6_gt_force_wake_get(dev_priv); \
+ unsigned long irqflags; \
+ spin_lock_irqsave(&dev_priv->gt_lock, irqflags); \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->display.force_wake_get(dev_priv); \
val = read##y(dev_priv->regs + reg); \
- gen6_gt_force_wake_put(dev_priv); \
+ if (dev_priv->forcewake_count == 0) \
+ dev_priv->display.force_wake_put(dev_priv); \
+ spin_unlock_irqrestore(&dev_priv->gt_lock, irqflags); \
} else { \
val = read##y(dev_priv->regs + reg); \
} \
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 602bc80..9689ca3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -288,7 +288,13 @@
int relative_constants_mode;
void __iomem *regs;
- u32 gt_fifo_count;
+ /** gt_fifo_count and the subsequent register write are synchronized
+ * with dev->struct_mutex. */
+ unsigned gt_fifo_count;
+ /** forcewake_count is protected by gt_lock */
+ unsigned forcewake_count;
+ /** gt_lock is also taken in irq contexts. */
+ struct spinlock gt_lock;
struct intel_gmbus {
struct i2c_adapter adapter;
@@ -741,8 +747,6 @@
struct drm_property *broadcast_rgb_property;
struct drm_property *force_audio_property;
-
- atomic_t forcewake_count;
} drm_i915_private_t;
enum i915_cache_level {
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5d433fc..5bd4361 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1751,7 +1751,8 @@
INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
I915_WRITE(HWSTAM, 0xeffe);
- if (IS_GEN6(dev) || IS_GEN7(dev)) {
+
+ if (IS_GEN6(dev)) {
/* Workaround stalls observed on Sandy Bridge GPUs by
* making the blitter command streamer generate a
* write to the Hardware Status Page for
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index 7886e4f..2b5eb22 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -28,14 +28,19 @@
#include "drm.h"
#include "i915_drm.h"
#include "intel_drv.h"
+#include "i915_reg.h"
static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpll_reg;
+ /* On IVB, 3rd pipe shares PLL with another one */
+ if (pipe > 1)
+ return false;
+
if (HAS_PCH_SPLIT(dev))
- dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
+ dpll_reg = PCH_DPLL(pipe);
else
dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
@@ -822,7 +827,7 @@
if (IS_IRONLAKE_M(dev))
ironlake_disable_drps(dev);
- if (IS_GEN6(dev))
+ if (INTEL_INFO(dev)->gen >= 6)
gen6_disable_rps(dev);
/* Cache mode state */
@@ -881,7 +886,7 @@
intel_init_emon(dev);
}
- if (IS_GEN6(dev)) {
+ if (INTEL_INFO(dev)->gen >= 6) {
gen6_enable_rps(dev_priv);
gen6_update_ring_freq(dev_priv);
}
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 8af3735..dbda6e3 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -467,8 +467,12 @@
struct bdb_edp {
struct edp_power_seq power_seqs[16];
u32 color_depth;
- u32 sdrrs_msa_timing_delay;
struct edp_link_params link_params[16];
+ u32 sdrrs_msa_timing_delay;
+
+ /* ith bit indicates enabled/disabled for (i+1)th panel */
+ u16 edp_s3d_feature;
+ u16 edp_t3_optimization;
} __attribute__ ((packed));
void intel_setup_bios(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index fee0ad0..dd729d4 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -24,6 +24,7 @@
* Eric Anholt <eric@anholt.net>
*/
+#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include "drmP.h"
@@ -540,6 +541,24 @@
.destroy = intel_encoder_destroy,
};
+static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id intel_no_crt[] = {
+ {
+ .callback = intel_no_crt_dmi_callback,
+ .ident = "ACER ZGB",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
+ },
+ },
+ { }
+};
+
void intel_crt_init(struct drm_device *dev)
{
struct drm_connector *connector;
@@ -547,6 +566,10 @@
struct intel_connector *intel_connector;
struct drm_i915_private *dev_priv = dev->dev_private;
+ /* Skip machines without VGA that falsely report hotplug events */
+ if (dmi_check_system(intel_no_crt))
+ return;
+
crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
if (!crt)
return;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 2a3f707..b3b51c4 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5808,12 +5808,15 @@
if (is_lvds) {
temp = I915_READ(PCH_LVDS);
temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
- if (HAS_PCH_CPT(dev))
+ if (HAS_PCH_CPT(dev)) {
+ temp &= ~PORT_TRANS_SEL_MASK;
temp |= PORT_TRANS_SEL_CPT(pipe);
- else if (pipe == 1)
- temp |= LVDS_PIPEB_SELECT;
- else
- temp &= ~LVDS_PIPEB_SELECT;
+ } else {
+ if (pipe == 1)
+ temp |= LVDS_PIPEB_SELECT;
+ else
+ temp &= ~LVDS_PIPEB_SELECT;
+ }
/* set the corresponsding LVDS_BORDER bit */
temp |= dev_priv->lvds_border_bits;
@@ -9025,12 +9028,9 @@
for (i = 0; i < dev_priv->num_pipe; i++) {
intel_crtc_init(dev, i);
- if (HAS_PCH_SPLIT(dev)) {
- ret = intel_plane_init(dev, i);
- if (ret)
- DRM_ERROR("plane %d init failed: %d\n",
- i, ret);
- }
+ ret = intel_plane_init(dev, i);
+ if (ret)
+ DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret);
}
/* Just disable it once at startup */
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e441911..798f6e1 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -708,6 +708,14 @@
},
},
{
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "Clientron E830",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
+ },
+ },
+ {
.callback = intel_no_lvds_dmi_callback,
.ident = "Asus EeeBox PC EB1007",
.matches = {
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 77e729d..1ab842c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -636,6 +636,19 @@
}
static u32
+gen6_ring_get_seqno(struct intel_ring_buffer *ring)
+{
+ struct drm_device *dev = ring->dev;
+
+ /* Workaround to force correct ordering between irq and seqno writes on
+ * ivb (and maybe also on snb) by reading from a CS register (like
+ * ACTHD) before reading the status page. */
+ if (IS_GEN7(dev))
+ intel_ring_get_active_head(ring);
+ return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
+}
+
+static u32
ring_get_seqno(struct intel_ring_buffer *ring)
{
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
@@ -792,17 +805,6 @@
}
static bool
-gen7_blt_ring_get_irq(struct intel_ring_buffer *ring)
-{
- /* The BLT ring on IVB appears to have broken synchronization
- * between the seqno write and the interrupt, so that the
- * interrupt appears first. Returning false here makes
- * i915_wait_request() do a polling loop, instead.
- */
- return false;
-}
-
-static bool
gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
{
struct drm_device *dev = ring->dev;
@@ -811,6 +813,12 @@
if (!dev->irq_enabled)
return false;
+ /* It looks like we need to prevent the gt from suspending while waiting
+ * for an notifiy irq, otherwise irqs seem to get lost on at least the
+ * blt/bsd rings on ivb. */
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_get(dev_priv);
+
spin_lock(&ring->irq_lock);
if (ring->irq_refcount++ == 0) {
ring->irq_mask &= ~rflag;
@@ -835,6 +843,9 @@
ironlake_disable_irq(dev_priv, gflag);
}
spin_unlock(&ring->irq_lock);
+
+ if (IS_GEN7(dev))
+ gen6_gt_force_wake_put(dev_priv);
}
static bool
@@ -1341,7 +1352,7 @@
.write_tail = gen6_bsd_ring_write_tail,
.flush = gen6_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = gen6_bsd_ring_get_irq,
.irq_put = gen6_bsd_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
@@ -1476,7 +1487,7 @@
.write_tail = ring_write_tail,
.flush = blt_ring_flush,
.add_request = gen6_add_request,
- .get_seqno = ring_get_seqno,
+ .get_seqno = gen6_ring_get_seqno,
.irq_get = blt_ring_get_irq,
.irq_put = blt_ring_put_irq,
.dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
@@ -1499,6 +1510,7 @@
ring->flush = gen6_render_ring_flush;
ring->irq_get = gen6_render_ring_get_irq;
ring->irq_put = gen6_render_ring_put_irq;
+ ring->get_seqno = gen6_ring_get_seqno;
} else if (IS_GEN5(dev)) {
ring->add_request = pc_render_add_request;
ring->get_seqno = pc_render_get_seqno;
@@ -1577,8 +1589,5 @@
*ring = gen6_blt_ring;
- if (IS_GEN7(dev))
- ring->irq_get = gen7_blt_ring_get_irq;
-
return intel_init_ring_buffer(dev, ring);
}
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index f7b9268..e334ec3 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1066,15 +1066,13 @@
/* Set the SDVO control regs. */
if (INTEL_INFO(dev)->gen >= 4) {
- sdvox = 0;
+ /* The real mode polarity is set by the SDVO commands, using
+ * struct intel_sdvo_dtd. */
+ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
if (intel_sdvo->is_hdmi)
sdvox |= intel_sdvo->color_range;
if (INTEL_INFO(dev)->gen < 5)
sdvox |= SDVO_BORDER_ENABLE;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
} else {
sdvox = I915_READ(intel_sdvo->sdvo_reg);
switch (intel_sdvo->sdvo_reg) {
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index d13989f..2288abf 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -466,10 +466,8 @@
mutex_lock(&dev->struct_mutex);
ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
- if (ret) {
- DRM_ERROR("failed to pin object\n");
+ if (ret)
goto out_unlock;
- }
intel_plane->obj = obj;
@@ -632,10 +630,8 @@
unsigned long possible_crtcs;
int ret;
- if (!(IS_GEN6(dev) || IS_GEN7(dev))) {
- DRM_ERROR("new plane code only for SNB+\n");
+ if (!(IS_GEN6(dev) || IS_GEN7(dev)))
return -ENODEV;
- }
intel_plane = kzalloc(sizeof(struct intel_plane), GFP_KERNEL);
if (!intel_plane)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index f3c6a9a..1571be3 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -417,7 +417,7 @@
{
.name = "NTSC-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
@@ -460,7 +460,7 @@
{
.name = "NTSC-443",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
@@ -502,7 +502,7 @@
{
.name = "NTSC-J",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -545,7 +545,7 @@
{
.name = "PAL-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -589,7 +589,7 @@
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL-N",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -634,7 +634,7 @@
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -674,78 +674,6 @@
.filter_table = filter_table,
},
{
- .name = "480p@59.94Hz",
- .clock = 107520,
- .refresh = 59940,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 122,
- .hblank_start = 842, .htotal = 857,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 12, .vsync_start_f2 = 12,
- .vsync_len = 12,
-
- .veq_ena = false,
-
- .vi_end_f1 = 44, .vi_end_f2 = 44,
- .nbr_end = 479,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
- .name = "480p@60Hz",
- .clock = 107520,
- .refresh = 60000,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 122,
- .hblank_start = 842, .htotal = 856,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 12, .vsync_start_f2 = 12,
- .vsync_len = 12,
-
- .veq_ena = false,
-
- .vi_end_f1 = 44, .vi_end_f2 = 44,
- .nbr_end = 479,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
- .name = "576p",
- .clock = 107520,
- .refresh = 50000,
- .oversample = TV_OVERSAMPLE_4X,
- .component_only = 1,
-
- .hsync_end = 64, .hblank_end = 139,
- .hblank_start = 859, .htotal = 863,
-
- .progressive = true, .trilevel_sync = false,
-
- .vsync_start_f1 = 10, .vsync_start_f2 = 10,
- .vsync_len = 10,
-
- .veq_ena = false,
-
- .vi_end_f1 = 48, .vi_end_f2 = 48,
- .nbr_end = 575,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
.name = "720p@60Hz",
.clock = 148800,
.refresh = 60000,
@@ -770,30 +698,6 @@
.filter_table = filter_table,
},
{
- .name = "720p@59.94Hz",
- .clock = 148800,
- .refresh = 59940,
- .oversample = TV_OVERSAMPLE_2X,
- .component_only = 1,
-
- .hsync_end = 80, .hblank_end = 300,
- .hblank_start = 1580, .htotal = 1651,
-
- .progressive = true, .trilevel_sync = true,
-
- .vsync_start_f1 = 10, .vsync_start_f2 = 10,
- .vsync_len = 10,
-
- .veq_ena = false,
-
- .vi_end_f1 = 29, .vi_end_f2 = 29,
- .nbr_end = 719,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
- {
.name = "720p@50Hz",
.clock = 148800,
.refresh = 50000,
@@ -821,7 +725,7 @@
{
.name = "1080i@50Hz",
.clock = 148800,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
@@ -847,7 +751,7 @@
{
.name = "1080i@60Hz",
.clock = 148800,
- .refresh = 30000,
+ .refresh = 60000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
@@ -870,32 +774,6 @@
.filter_table = filter_table,
},
- {
- .name = "1080i@59.94Hz",
- .clock = 148800,
- .refresh = 29970,
- .oversample = TV_OVERSAMPLE_2X,
- .component_only = 1,
-
- .hsync_end = 88, .hblank_end = 235,
- .hblank_start = 2155, .htotal = 2201,
-
- .progressive = false, .trilevel_sync = true,
-
- .vsync_start_f1 = 4, .vsync_start_f2 = 5,
- .vsync_len = 10,
-
- .veq_ena = true, .veq_start_f1 = 4,
- .veq_start_f2 = 4, .veq_len = 10,
-
-
- .vi_end_f1 = 21, .vi_end_f2 = 22,
- .nbr_end = 539,
-
- .burst_ena = false,
-
- .filter_table = filter_table,
- },
};
static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h
index 1e382ad..a37c31e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.h
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.h
@@ -54,9 +54,10 @@
int bit_table(struct drm_device *, u8 id, struct bit_entry *);
enum dcb_gpio_tag {
- DCB_GPIO_TVDAC0 = 0xc,
+ DCB_GPIO_PANEL_POWER = 0x01,
+ DCB_GPIO_TVDAC0 = 0x0c,
DCB_GPIO_TVDAC1 = 0x2d,
- DCB_GPIO_PWM_FAN = 0x9,
+ DCB_GPIO_PWM_FAN = 0x09,
DCB_GPIO_FAN_SENSE = 0x3d,
DCB_GPIO_UNUSED = 0xff
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 724b41a..ec54364 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -812,6 +812,10 @@
struct nouveau_bo *nvbo = nouveau_bo(bo);
struct nouveau_vma *vma;
+ /* ttm can now (stupidly) pass the driver bos it didn't create... */
+ if (bo->destroy != nouveau_bo_del_ttm)
+ return;
+
list_for_each_entry(vma, &nvbo->vma_list, head) {
if (new_mem && new_mem->mem_type == TTM_PL_VRAM) {
nouveau_vm_map(vma, new_mem->mm_node);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 3cb52bc..795a9e3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -219,6 +219,16 @@
if (ret)
return ret;
+ /* power on internal panel if it's not already. the init tables of
+ * some vbios default this to off for some reason, causing the
+ * panel to not work after resume
+ */
+ if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) {
+ nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true);
+ msleep(300);
+ }
+
+ /* enable polling for external displays */
drm_kms_helper_poll_enable(dev);
/* enable hotplug interrupts */
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index e4a7cfe..81d7962 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -124,7 +124,7 @@
int nouveau_ctxfw;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
-MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n");
+MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n");
int nouveau_mxmdcb = 1;
module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 5f0bc57..7ce3fde 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -380,6 +380,25 @@
}
static int
+validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
+{
+ struct nouveau_fence *fence = NULL;
+ int ret = 0;
+
+ spin_lock(&nvbo->bo.bdev->fence_lock);
+ if (nvbo->bo.sync_obj)
+ fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+ spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+ if (fence) {
+ ret = nouveau_fence_sync(fence, chan);
+ nouveau_fence_unref(&fence);
+ }
+
+ return ret;
+}
+
+static int
validate_list(struct nouveau_channel *chan, struct list_head *list,
struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
{
@@ -393,7 +412,7 @@
list_for_each_entry(nvbo, list, entry) {
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail pre-validate sync\n");
return ret;
@@ -416,7 +435,7 @@
return ret;
}
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail post-validate sync\n");
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mxm.c b/drivers/gpu/drm/nouveau/nouveau_mxm.c
index 8bccddf..e5a64f0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mxm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mxm.c
@@ -656,7 +656,16 @@
if (mxm_shadow(dev, mxm[0])) {
MXM_MSG(dev, "failed to locate valid SIS\n");
+#if 0
+ /* we should, perhaps, fall back to some kind of limited
+ * mode here if the x86 vbios hasn't already done the
+ * work for us (so we prevent loading with completely
+ * whacked vbios tables).
+ */
return -EINVAL;
+#else
+ return 0;
+#endif
}
MXM_MSG(dev, "MXMS Version %d.%d\n",
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index 0393721..ec5481d 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -495,9 +495,9 @@
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nv50_pm_state *info;
struct pll_lims pll;
- int ret = -EINVAL;
+ int clk, ret = -EINVAL;
int N, M, P1, P2;
- u32 clk, out;
+ u32 out;
if (dev_priv->chipset == 0xaa ||
dev_priv->chipset == 0xac)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 0fda830..742f17f 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -355,15 +355,12 @@
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
-static void atombios_disable_ss(struct drm_crtc *crtc)
+static void atombios_disable_ss(struct radeon_device *rdev, int pll_id)
{
- struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
u32 ss_cntl;
if (ASIC_IS_DCE4(rdev)) {
- switch (radeon_crtc->pll_id) {
+ switch (pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(EVERGREEN_P1PLL_SS_CNTL);
ss_cntl &= ~EVERGREEN_PxPLL_SS_EN;
@@ -379,7 +376,7 @@
return;
}
} else if (ASIC_IS_AVIVO(rdev)) {
- switch (radeon_crtc->pll_id) {
+ switch (pll_id) {
case ATOM_PPLL1:
ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
ss_cntl &= ~1;
@@ -406,13 +403,11 @@
ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 v3;
};
-static void atombios_crtc_program_ss(struct drm_crtc *crtc,
+static void atombios_crtc_program_ss(struct radeon_device *rdev,
int enable,
int pll_id,
struct radeon_atom_ss *ss)
{
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL);
union atom_enable_ss args;
@@ -479,7 +474,7 @@
} else if (ASIC_IS_AVIVO(rdev)) {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) {
- atombios_disable_ss(crtc);
+ atombios_disable_ss(rdev, pll_id);
return;
}
args.lvds_ss_2.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
@@ -491,7 +486,7 @@
} else {
if ((enable == ATOM_DISABLE) || (ss->percentage == 0) ||
(ss->type & ATOM_EXTERNAL_SS_MASK)) {
- atombios_disable_ss(crtc);
+ atombios_disable_ss(rdev, pll_id);
return;
}
args.lvds_ss.usSpreadSpectrumPercentage = cpu_to_le16(ss->percentage);
@@ -523,6 +518,7 @@
int encoder_mode = 0;
u32 dp_clock = mode->clock;
int bpc = 8;
+ bool is_duallink = false;
/* reset the pll flags */
pll->flags = 0;
@@ -557,6 +553,7 @@
if (connector && connector->display_info.bpc)
bpc = connector->display_info.bpc;
encoder_mode = atombios_get_encoder_mode(encoder);
+ is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
(radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
if (connector) {
@@ -652,7 +649,7 @@
if (dig->coherent_mode)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE;
- if (mode->clock > 165000)
+ if (is_duallink)
args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_DUAL_LINK;
}
@@ -702,11 +699,9 @@
/* on DCE5, make sure the voltage is high enough to support the
* required disp clk.
*/
-static void atombios_crtc_set_dcpll(struct drm_crtc *crtc,
+static void atombios_crtc_set_dcpll(struct radeon_device *rdev,
u32 dispclk)
{
- struct drm_device *dev = crtc->dev;
- struct radeon_device *rdev = dev->dev_private;
u8 frev, crev;
int index;
union set_pixel_clock args;
@@ -996,7 +991,7 @@
radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
&ref_div, &post_div);
- atombios_crtc_program_ss(crtc, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
encoder_mode, radeon_encoder->encoder_id, mode->clock,
@@ -1019,7 +1014,7 @@
ss.step = step_size;
}
- atombios_crtc_program_ss(crtc, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
+ atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss);
}
}
@@ -1189,7 +1184,7 @@
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1358,7 +1353,7 @@
WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1494,6 +1489,24 @@
}
+void radeon_atom_dcpll_init(struct radeon_device *rdev)
+{
+ /* always set DCPLL */
+ if (ASIC_IS_DCE4(rdev)) {
+ struct radeon_atom_ss ss;
+ bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
+ ASIC_INTERNAL_SS_ON_DCPLL,
+ rdev->clock.default_dispclk);
+ if (ss_enabled)
+ atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss);
+ /* XXX: DCE5, make sure voltage, dispclk is high enough */
+ atombios_crtc_set_dcpll(rdev, rdev->clock.default_dispclk);
+ if (ss_enabled)
+ atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss);
+ }
+
+}
+
int atombios_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
@@ -1515,19 +1528,6 @@
}
}
- /* always set DCPLL */
- if (ASIC_IS_DCE4(rdev)) {
- struct radeon_atom_ss ss;
- bool ss_enabled = radeon_atombios_get_asic_ss_info(rdev, &ss,
- ASIC_INTERNAL_SS_ON_DCPLL,
- rdev->clock.default_dispclk);
- if (ss_enabled)
- atombios_crtc_program_ss(crtc, ATOM_DISABLE, ATOM_DCPLL, &ss);
- /* XXX: DCE5, make sure voltage, dispclk is high enough */
- atombios_crtc_set_dcpll(crtc, rdev->clock.default_dispclk);
- if (ss_enabled)
- atombios_crtc_program_ss(crtc, ATOM_ENABLE, ATOM_DCPLL, &ss);
- }
atombios_crtc_set_pll(crtc, adjusted_mode);
if (ASIC_IS_DCE4(rdev))
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 6fb335a..552b436 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -549,8 +549,8 @@
return false;
}
-static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
- struct drm_connector *connector)
+int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+ struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
@@ -558,28 +558,33 @@
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
if (!ASIC_IS_DCE4(rdev))
- return;
+ return panel_mode;
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG)
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
- ENCODER_OBJECT_ID_TRAVIS)
- panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
- else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+ ENCODER_OBJECT_ID_TRAVIS) {
+ u8 id[6];
+ int i;
+ for (i = 0; i < 6; i++)
+ id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
+ if (id[0] == 0x73 &&
+ id[1] == 0x69 &&
+ id[2] == 0x76 &&
+ id[3] == 0x61 &&
+ id[4] == 0x72 &&
+ id[5] == 0x54)
+ panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
+ else
+ panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+ } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
- atombios_dig_encoder_setup(encoder,
- ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
- panel_mode);
-
- if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
- (panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
- radeon_write_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
- }
+ return panel_mode;
}
void radeon_dp_set_link_config(struct drm_connector *connector,
@@ -717,6 +722,8 @@
static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
{
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
u8 tmp;
/* power up the sink */
@@ -732,7 +739,10 @@
radeon_write_dpcd_reg(dp_info->radeon_connector,
DP_DOWNSPREAD_CTRL, 0);
- radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector);
+ if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
+ (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
+ radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+ }
/* set the lane count on the sink */
tmp = dp_info->dp_lane_count;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index f1f06ca..b88c460 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -57,22 +57,6 @@
}
}
-static struct drm_connector *
-radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
-{
- struct drm_device *dev = encoder->dev;
- struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector;
-
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- radeon_connector = to_radeon_connector(connector);
- if (radeon_encoder->devices & radeon_connector->devices)
- return connector;
- }
- return NULL;
-}
-
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -253,7 +237,7 @@
/* R4xx, R5xx */
args.ext_tmds.sXTmdsEncoder.ucEnable = action;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.ext_tmds.sXTmdsEncoder.ucMisc |= PANEL_ENCODER_MISC_DUAL;
args.ext_tmds.sXTmdsEncoder.ucMisc |= ATOM_PANEL_MISC_888RGB;
@@ -265,7 +249,7 @@
/* DFP1, CRT1, TV1 depending on the type of port */
args.dvo.sDVOEncoder.ucDeviceType = ATOM_DEVICE_DFP1_INDEX;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.dvo.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute |= PANEL_ENCODER_MISC_DUAL;
break;
case 3:
@@ -349,7 +333,7 @@
} else {
if (dig->linkb)
args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL;
/*if (pScrn->rgbBits == 8) */
args.v1.ucMisc |= ATOM_PANEL_MISC_888RGB;
@@ -388,7 +372,7 @@
} else {
if (dig->linkb)
args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL;
}
break;
@@ -432,7 +416,7 @@
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
- if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
@@ -443,7 +427,7 @@
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
default:
- if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else
@@ -457,7 +441,7 @@
if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
(dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
return ATOM_ENCODER_MODE_DP;
- else if (drm_detect_monitor_audio(radeon_connector->edid) &&
+ else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
radeon_audio)
return ATOM_ENCODER_MODE_HDMI;
else
@@ -587,7 +571,7 @@
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v1.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucLaneNum = 8;
else
args.v1.ucLaneNum = 4;
@@ -622,7 +606,7 @@
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v3.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
@@ -662,7 +646,7 @@
if (ENCODER_MODE_IS_DP(args.v1.ucEncoderMode))
args.v4.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.ucLaneNum = 8;
else
args.v4.ucLaneNum = 4;
@@ -806,7 +790,7 @@
if (is_dp)
args.v1.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -821,7 +805,8 @@
if ((rdev->flags & RADEON_IS_IGP) &&
(radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY)) {
- if (is_dp || (radeon_encoder->pixel_clock <= 165000)) {
+ if (is_dp ||
+ !radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock)) {
if (igp_lane_info & 0x1)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3;
else if (igp_lane_info & 0x2)
@@ -848,7 +833,7 @@
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK;
}
break;
@@ -863,7 +848,7 @@
if (is_dp)
args.v2.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -891,7 +876,7 @@
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v2.acConfig.fDualLinkConnector = 1;
}
break;
@@ -906,7 +891,7 @@
if (is_dp)
args.v3.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v3.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -914,7 +899,7 @@
if (is_dp)
args.v3.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.ucLaneNum = 8;
else
args.v3.ucLaneNum = 4;
@@ -951,7 +936,7 @@
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v3.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.acConfig.fDualLinkConnector = 1;
}
break;
@@ -966,7 +951,7 @@
if (is_dp)
args.v4.usPixelClock =
cpu_to_le16(dp_clock / 10);
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v4.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
@@ -974,7 +959,7 @@
if (is_dp)
args.v4.ucLaneNum = dp_lane_count;
- else if (radeon_encoder->pixel_clock > 165000)
+ else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.ucLaneNum = 8;
else
args.v4.ucLaneNum = 4;
@@ -1014,7 +999,7 @@
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v4.acConfig.fCoherentMode = 1;
- if (radeon_encoder->pixel_clock > 165000)
+ if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v4.acConfig.fDualLinkConnector = 1;
}
break;
@@ -1137,7 +1122,7 @@
if (dp_clock == 270000)
args.v1.sDigEncoder.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
args.v1.sDigEncoder.ucLaneNum = dp_lane_count;
- } else if (radeon_encoder->pixel_clock > 165000)
+ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v1.sDigEncoder.ucLaneNum = 8;
else
args.v1.sDigEncoder.ucLaneNum = 4;
@@ -1156,7 +1141,7 @@
else if (dp_clock == 540000)
args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ;
args.v3.sExtEncoder.ucLaneNum = dp_lane_count;
- } else if (radeon_encoder->pixel_clock > 165000)
+ } else if (radeon_dig_monitor_is_duallink(encoder, radeon_encoder->pixel_clock))
args.v3.sExtEncoder.ucLaneNum = 8;
else
args.v3.sExtEncoder.ucLaneNum = 4;
@@ -1341,7 +1326,8 @@
switch (mode) {
case DRM_MODE_DPMS_ON:
/* some early dce3.2 boards have a bug in their transmitter control table */
- if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
+ ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
else
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
@@ -1351,8 +1337,6 @@
ATOM_TRANSMITTER_ACTION_POWER_ON);
radeon_dig_connector->edp_on = true;
}
- if (ASIC_IS_DCE4(rdev))
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
radeon_dp_link_train(encoder, connector);
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
@@ -1363,7 +1347,10 @@
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ else
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
@@ -1810,7 +1797,21 @@
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
- if (ASIC_IS_DCE4(rdev)) {
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+
+ if (!connector)
+ dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+ else
+ dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
+
+ /* setup and enable the encoder */
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+ atombios_dig_encoder_setup(encoder,
+ ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
+ dig->panel_mode);
+ } else if (ASIC_IS_DCE4(rdev)) {
/* disable the transmitter */
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
/* setup and enable the encoder */
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 636660f..ae09fe8 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -1455,6 +1455,7 @@
#endif
WREG32(CP_RB_CNTL, tmp);
WREG32(CP_SEM_WAIT_TIMER, 0x0);
+ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0);
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b502216..74713d4 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -108,6 +108,7 @@
#define CP_RB_WPTR_ADDR_HI 0xC11C
#define CP_RB_WPTR_DELAY 0x8704
#define CP_SEM_WAIT_TIMER 0x85BC
+#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_DEBUG 0xC1FC
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 3211372..db09065 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1219,6 +1219,7 @@
RREG32(GRBM_SOFT_RESET);
WREG32(CP_SEM_WAIT_TIMER, 0x0);
+ WREG32(CP_SEM_INCOMPLETE_TIMER_CNTL, 0x0);
/* Set the write pointer delay */
WREG32(CP_RB_WPTR_DELAY, 0);
diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
index f9df2a6..9a7f3b6 100644
--- a/drivers/gpu/drm/radeon/nid.h
+++ b/drivers/gpu/drm/radeon/nid.h
@@ -222,6 +222,7 @@
#define SCRATCH_UMSK 0x8540
#define SCRATCH_ADDR 0x8544
#define CP_SEM_WAIT_TIMER 0x85BC
+#define CP_SEM_INCOMPLETE_TIMER_CNTL 0x85C8
#define CP_COHER_CNTL2 0x85E8
#define CP_ME_CNTL 0x86D8
#define CP_ME_HALT (1 << 28)
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c
index d996f43..accc032 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -468,27 +468,42 @@
radeon_ring_write(ring, sq_stack_resource_mgmt_2);
}
+#define I2F_MAX_BITS 15
+#define I2F_MAX_INPUT ((1 << I2F_MAX_BITS) - 1)
+#define I2F_SHIFT (24 - I2F_MAX_BITS)
+
+/*
+ * Converts unsigned integer into 32-bit IEEE floating point representation.
+ * Conversion is not universal and only works for the range from 0
+ * to 2^I2F_MAX_BITS-1. Currently we only use it with inputs between
+ * 0 and 16384 (inclusive), so I2F_MAX_BITS=15 is enough. If necessary,
+ * I2F_MAX_BITS can be increased, but that will add to the loop iterations
+ * and slow us down. Conversion is done by shifting the input and counting
+ * down until the first 1 reaches bit position 23. The resulting counter
+ * and the shifted input are, respectively, the exponent and the fraction.
+ * The sign is always zero.
+ */
static uint32_t i2f(uint32_t input)
{
u32 result, i, exponent, fraction;
- if ((input & 0x3fff) == 0)
- result = 0; /* 0 is a special case */
+ WARN_ON_ONCE(input > I2F_MAX_INPUT);
+
+ if ((input & I2F_MAX_INPUT) == 0)
+ result = 0;
else {
- exponent = 140; /* exponent biased by 127; */
- fraction = (input & 0x3fff) << 10; /* cheat and only
- handle numbers below 2^^15 */
- for (i = 0; i < 14; i++) {
+ exponent = 126 + I2F_MAX_BITS;
+ fraction = (input & I2F_MAX_INPUT) << I2F_SHIFT;
+
+ for (i = 0; i < I2F_MAX_BITS; i++) {
if (fraction & 0x800000)
break;
else {
- fraction = fraction << 1; /* keep
- shifting left until top bit = 1 */
+ fraction = fraction << 1;
exponent = exponent - 1;
}
}
- result = exponent << 23 | (fraction & 0x7fffff); /* mask
- off top bit; assumed 1 */
+ result = exponent << 23 | (fraction & 0x7fffff);
}
return result;
}
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 73e05cb..1668ec1 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -157,6 +157,47 @@
/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+ struct mutex mutex;
+ struct task_struct *owner;
+ int level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+ mutex_init(&mutex->mutex);
+ mutex->owner = NULL;
+ mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+ if (mutex_trylock(&mutex->mutex)) {
+ /* The mutex was unlocked before, so it's ours now */
+ mutex->owner = current;
+ } else if (mutex->owner != current) {
+ /* Another process locked the mutex, take it */
+ mutex_lock(&mutex->mutex);
+ mutex->owner = current;
+ }
+ /* Otherwise the mutex was already locked by this process */
+
+ mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+ if (--mutex->level > 0)
+ return;
+
+ mutex->owner = NULL;
+ mutex_unlock(&mutex->mutex);
+}
+
+
+/*
* Dummy page
*/
struct radeon_dummy_page {
@@ -598,7 +639,7 @@
* mutex protects scheduled_ibs, ready, alloc_bm
*/
struct radeon_ib_pool {
- struct mutex mutex;
+ struct radeon_mutex mutex;
struct radeon_sa_manager sa_manager;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready;
@@ -1355,47 +1396,6 @@
/*
- * Mutex which allows recursive locking from the same process.
- */
-struct radeon_mutex {
- struct mutex mutex;
- struct task_struct *owner;
- int level;
-};
-
-static inline void radeon_mutex_init(struct radeon_mutex *mutex)
-{
- mutex_init(&mutex->mutex);
- mutex->owner = NULL;
- mutex->level = 0;
-}
-
-static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
-{
- if (mutex_trylock(&mutex->mutex)) {
- /* The mutex was unlocked before, so it's ours now */
- mutex->owner = current;
- } else if (mutex->owner != current) {
- /* Another process locked the mutex, take it */
- mutex_lock(&mutex->mutex);
- mutex->owner = current;
- }
- /* Otherwise the mutex was already locked by this process */
-
- mutex->level++;
-}
-
-static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
-{
- if (--mutex->level > 0)
- return;
-
- mutex->owner = NULL;
- mutex_unlock(&mutex->mutex);
-}
-
-
-/*
* Core structure, functions and helpers.
*/
typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t);
diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
index 9d95792..98724fc 100644
--- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c
+++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c
@@ -58,7 +58,8 @@
}
obj = (union acpi_object *)buffer.pointer;
- memcpy(bios+offset, obj->buffer.pointer, len);
+ memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
+ len = obj->buffer.length;
kfree(buffer.pointer);
return len;
}
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 229a20f..501f488 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -120,7 +120,7 @@
ret = radeon_atrm_get_bios_chunk(rdev->bios,
(i * ATRM_BIOS_PAGE),
ATRM_BIOS_PAGE);
- if (ret <= 0)
+ if (ret < ATRM_BIOS_PAGE)
break;
}
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 0afb13b..49f7cb7 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -720,7 +720,7 @@
/* mutex initialization are all done here so we
* can recall function without having locking issues */
radeon_mutex_init(&rdev->cs_mutex);
- mutex_init(&rdev->ib_pool.mutex);
+ radeon_mutex_init(&rdev->ib_pool.mutex);
for (i = 0; i < RADEON_NUM_RINGS; ++i)
mutex_init(&rdev->ring[i].mutex);
mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -883,6 +883,8 @@
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
+ drm_kms_helper_poll_disable(dev);
+
/* turn off display hw */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
@@ -959,9 +961,11 @@
radeon_fbdev_set_suspend(rdev, 0);
console_unlock();
- /* init dig PHYs */
- if (rdev->is_atom_bios)
+ /* init dig PHYs, disp eng pll */
+ if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev);
+ radeon_atom_dcpll_init(rdev);
+ }
/* reset hpd state */
radeon_hpd_init(rdev);
/* blat the mode back in */
@@ -970,6 +974,8 @@
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}
+
+ drm_kms_helper_poll_enable(dev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index d3ffc18..8c49fef 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1305,9 +1305,11 @@
return ret;
}
- /* init dig PHYs */
- if (rdev->is_atom_bios)
+ /* init dig PHYs, disp eng pll */
+ if (rdev->is_atom_bios) {
radeon_atom_encoder_init(rdev);
+ radeon_atom_dcpll_init(rdev);
+ }
/* initialize hpd */
radeon_hpd_init(rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index 4b27efa..9419c51 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -202,6 +202,22 @@
return NULL;
}
+struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder)
+{
+ struct drm_device *dev = encoder->dev;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+ struct drm_connector *connector;
+ struct radeon_connector *radeon_connector;
+
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ radeon_connector = to_radeon_connector(connector);
+ if (radeon_encoder->devices & radeon_connector->devices)
+ return connector;
+ }
+ return NULL;
+}
+
struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
@@ -288,3 +304,64 @@
}
+bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+ u32 pixel_clock)
+{
+ struct drm_device *dev = encoder->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ struct drm_connector *connector;
+ struct radeon_connector *radeon_connector;
+ struct radeon_connector_atom_dig *dig_connector;
+
+ connector = radeon_get_connector_for_encoder(encoder);
+ /* if we don't have an active device yet, just use one of
+ * the connectors tied to the encoder.
+ */
+ if (!connector)
+ connector = radeon_get_connector_for_encoder_init(encoder);
+ radeon_connector = to_radeon_connector(connector);
+
+ switch (connector->connector_type) {
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ if (radeon_connector->use_digital) {
+ /* HDMI 1.3 supports up to 340 Mhz over single link */
+ if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (pixel_clock > 340000)
+ return true;
+ else
+ return false;
+ } else {
+ if (pixel_clock > 165000)
+ return true;
+ else
+ return false;
+ }
+ } else
+ return false;
+ case DRM_MODE_CONNECTOR_DVID:
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ dig_connector = radeon_connector->con_priv;
+ if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
+ (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP))
+ return false;
+ else {
+ /* HDMI 1.3 supports up to 340 Mhz over single link */
+ if (ASIC_IS_DCE3(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+ if (pixel_clock > 340000)
+ return true;
+ else
+ return false;
+ } else {
+ if (pixel_clock > 165000)
+ return true;
+ else
+ return false;
+ }
+ }
+ default:
+ return false;
+ }
+}
+
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 7bb1b07..98a8ad6 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -897,6 +897,7 @@
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
+ i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
i2c_set_adapdata(&i2c->adapter, i2c);
if (rec->mm_i2c ||
@@ -957,6 +958,7 @@
i2c->rec = *rec;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.class = I2C_CLASS_DDC;
+ i2c->adapter.dev.parent = &dev->pdev->dev;
i2c->dev = dev;
snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
"Radeon aux bus %s", name);
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index be38921..66d5fe1 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -138,6 +138,12 @@
/* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) &&
+ (rdev->pdev->subsystem_device == 0x01fc))
+ return true;
+
+ /* Dell RS690 only seems to work with MSIs. */
+ if ((rdev->pdev->device == 0x791f) &&
+ (rdev->pdev->subsystem_vendor == 0x1028) &&
(rdev->pdev->subsystem_device == 0x01fd))
return true;
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 08ff857..4330e32 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -362,6 +362,7 @@
struct backlight_device *bl_dev;
int dpms_mode;
uint8_t backlight_level;
+ int panel_mode;
};
struct radeon_encoder_atom_dac {
@@ -466,6 +467,10 @@
extern struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder *encoder);
+extern struct drm_connector *
+radeon_get_connector_for_encoder_init(struct drm_encoder *encoder);
+extern bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
+ u32 pixel_clock);
extern u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder);
extern u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *connector);
@@ -482,8 +487,11 @@
extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector);
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
+extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
+ struct drm_connector *connector);
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
extern void radeon_atom_encoder_init(struct radeon_device *rdev);
+extern void radeon_atom_dcpll_init(struct radeon_device *rdev);
extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
int action, uint8_t lane_num,
uint8_t lane_set);
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index e8bc709..30a4c50 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -109,12 +109,12 @@
return r;
}
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
idx = rdev->ib_pool.head_id;
retry:
if (cretry > 5) {
dev_err(rdev->dev, "failed to get an ib after 5 retry\n");
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence);
return -ENOMEM;
}
@@ -139,7 +139,7 @@
*/
rdev->ib_pool.head_id = (1 + idx);
rdev->ib_pool.head_id &= (RADEON_IB_POOL_SIZE - 1);
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
}
@@ -158,7 +158,7 @@
}
idx = (idx + 1) & (RADEON_IB_POOL_SIZE - 1);
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
radeon_fence_unref(&fence);
return r;
}
@@ -171,12 +171,12 @@
if (tmp == NULL) {
return;
}
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
if (tmp->fence && !tmp->fence->emitted) {
radeon_sa_bo_free(rdev, &tmp->sa_bo);
radeon_fence_unref(&tmp->fence);
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
}
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
@@ -204,22 +204,25 @@
int radeon_ib_pool_init(struct radeon_device *rdev)
{
+ struct radeon_sa_manager tmp;
int i, r;
- mutex_lock(&rdev->ib_pool.mutex);
- if (rdev->ib_pool.ready) {
- mutex_unlock(&rdev->ib_pool.mutex);
- return 0;
- }
-
- r = radeon_sa_bo_manager_init(rdev, &rdev->ib_pool.sa_manager,
+ r = radeon_sa_bo_manager_init(rdev, &tmp,
RADEON_IB_POOL_SIZE*64*1024,
RADEON_GEM_DOMAIN_GTT);
if (r) {
- mutex_unlock(&rdev->ib_pool.mutex);
return r;
}
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
+ if (rdev->ib_pool.ready) {
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_sa_bo_manager_fini(rdev, &tmp);
+ return 0;
+ }
+
+ rdev->ib_pool.sa_manager = tmp;
+ INIT_LIST_HEAD(&rdev->ib_pool.sa_manager.sa_bo);
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
rdev->ib_pool.ibs[i].fence = NULL;
rdev->ib_pool.ibs[i].idx = i;
@@ -236,7 +239,7 @@
if (radeon_debugfs_ring_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for rings !\n");
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
return 0;
}
@@ -244,7 +247,7 @@
{
unsigned i;
- mutex_lock(&rdev->ib_pool.mutex);
+ radeon_mutex_lock(&rdev->ib_pool.mutex);
if (rdev->ib_pool.ready) {
for (i = 0; i < RADEON_IB_POOL_SIZE; i++) {
radeon_sa_bo_free(rdev, &rdev->ib_pool.ibs[i].sa_bo);
@@ -253,7 +256,7 @@
radeon_sa_bo_manager_fini(rdev, &rdev->ib_pool.sa_manager);
rdev->ib_pool.ready = false;
}
- mutex_unlock(&rdev->ib_pool.mutex);
+ radeon_mutex_unlock(&rdev->ib_pool.mutex);
}
int radeon_ib_pool_start(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c
index 06da063..573220c 100644
--- a/drivers/gpu/drm/sis/sis_drv.c
+++ b/drivers/gpu/drm/sis/sis_drv.c
@@ -40,7 +40,6 @@
static int sis_driver_load(struct drm_device *dev, unsigned long chipset)
{
drm_sis_private_t *dev_priv;
- int ret;
dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL);
if (dev_priv == NULL)
@@ -50,7 +49,7 @@
dev_priv->chipset = chipset;
idr_init(&dev->object_name_idr);
- return ret;
+ return 0;
}
static int sis_driver_unload(struct drm_device *dev)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 2f0eab6..7c3a57d 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -404,6 +404,9 @@
}
}
+ if (bdev->driver->move_notify)
+ bdev->driver->move_notify(bo, mem);
+
if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
ret = ttm_bo_move_ttm(bo, evict, no_wait_reserve, no_wait_gpu, mem);
@@ -413,11 +416,17 @@
else
ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, mem);
- if (ret)
- goto out_err;
+ if (ret) {
+ if (bdev->driver->move_notify) {
+ struct ttm_mem_reg tmp_mem = *mem;
+ *mem = bo->mem;
+ bo->mem = tmp_mem;
+ bdev->driver->move_notify(bo, mem);
+ bo->mem = *mem;
+ }
- if (bdev->driver->move_notify)
- bdev->driver->move_notify(bo, mem);
+ goto out_err;
+ }
moved:
if (bo->evicted) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 0af6ebd..b66ef0e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -378,7 +378,7 @@
unsigned int *handle)
{
if (handle)
- handle = 0;
+ *handle = 0;
return 0;
}
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 92f9497..6dbfd3e 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -283,11 +283,11 @@
static inline u8 temp_to_reg(long val)
{
- if (val < 0)
- val = 0;
- else if (val > 1000 * 0xff)
- val = 0xff;
- return ((val + 500) / 1000);
+ if (val <= 0)
+ return 0;
+ if (val >= 1000 * 0xff)
+ return 0xff;
+ return (val + 500) / 1000;
}
/*
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index 6ddeae0..91fdd1f 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -883,7 +883,7 @@
static int __devinit sht15_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
u8 status = 0;
@@ -901,6 +901,7 @@
init_waitqueue_head(&data->wait_queue);
if (pdev->dev.platform_data == NULL) {
+ ret = -EINVAL;
dev_err(&pdev->dev, "no platform data supplied\n");
goto err_free_data;
}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 0e0af04..4d383e7 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1319,6 +1319,7 @@
{
struct w83627ehf_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct w83627ehf_sio_data *sio_data = dev->platform_data;
int nr = sensor_attr->index;
unsigned long val;
int err;
@@ -1330,6 +1331,11 @@
if (val > 1)
return -EINVAL;
+
+ /* On NCT67766F, DC mode is only supported for pwm1 */
+ if (sio_data->kind == nct6776 && nr && val != 1)
+ return -EINVAL;
+
mutex_lock(&data->update_lock);
reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
data->pwm_mode[nr] = val;
@@ -1914,9 +1920,26 @@
fan4min = 0;
fan5pin = 0;
} else if (sio_data->kind == nct6776) {
- fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
- fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
- fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+ bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+ superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+ regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+ if (regval & 0x80)
+ fan3pin = gpok;
+ else
+ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+ if (regval & 0x40)
+ fan4pin = gpok;
+ else
+ fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+
+ if (regval & 0x20)
+ fan5pin = gpok;
+ else
+ fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+
fan4min = fan4pin;
} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
fan3pin = 1;
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index f713eac..801df60 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1018,7 +1018,7 @@
goto err_release_region;
}
- match = of_match_device(omap_i2c_of_match, &pdev->dev);
+ match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev);
if (match) {
u32 freq = 100000; /* default to 100000 Hz */
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index b37b0c0..5034a87 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -808,9 +808,12 @@
return PTR_ERR(ctx);
if (cmd.conn_param.valid) {
- ctx->uid = cmd.uid;
ucma_copy_conn_param(&conn_param, &cmd.conn_param);
+ mutex_lock(&file->mut);
ret = rdma_accept(ctx->cm_id, &conn_param);
+ if (!ret)
+ ctx->uid = cmd.uid;
+ mutex_unlock(&file->mut);
} else
ret = rdma_accept(ctx->cm_id, NULL);
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index b930da4..4d27e4c 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -1485,6 +1485,7 @@
qp->event_handler = attr.event_handler;
qp->qp_context = attr.qp_context;
qp->qp_type = attr.qp_type;
+ atomic_set(&qp->usecnt, 0);
atomic_inc(&pd->usecnt);
atomic_inc(&attr.send_cq->usecnt);
if (attr.recv_cq)
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 602b1bd..575b780 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -421,6 +421,7 @@
qp->uobject = NULL;
qp->qp_type = qp_init_attr->qp_type;
+ atomic_set(&qp->usecnt, 0);
if (qp_init_attr->qp_type == IB_QPT_XRC_TGT) {
qp->event_handler = __ib_shared_qp_event_handler;
qp->qp_context = qp;
@@ -430,7 +431,6 @@
qp->xrcd = qp_init_attr->xrcd;
atomic_inc(&qp_init_attr->xrcd->usecnt);
INIT_LIST_HEAD(&qp->open_list);
- atomic_set(&qp->usecnt, 0);
real_qp = qp;
qp = __ib_open_qp(real_qp, qp_init_attr->event_handler,
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
index b7d4216..a4de9d5 100644
--- a/drivers/infiniband/hw/ipath/ipath_fs.c
+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
@@ -89,7 +89,7 @@
error = ipathfs_mknod(parent->d_inode, *dentry,
mode, fops, data);
else
- error = PTR_ERR(dentry);
+ error = PTR_ERR(*dentry);
mutex_unlock(&parent->d_inode->i_mutex);
return error;
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 95c94d8..259b067 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -257,12 +257,9 @@
return IB_MAD_RESULT_SUCCESS;
/*
- * Don't process SMInfo queries or vendor-specific
- * MADs -- the SMA can't handle them.
+ * Don't process SMInfo queries -- the SMA can't handle them.
*/
- if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
- ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
- IB_SMP_ATTR_VENDOR_MASK))
+ if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
return IB_MAD_RESULT_SUCCESS;
} else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 ||
diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index 7013da5..7140199 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
index 568b4f1..c438e46 100644
--- a/drivers/infiniband/hw/nes/nes.h
+++ b/drivers/infiniband/hw/nes/nes.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 425065b..a4972ab 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -233,6 +233,7 @@
u8 *start_ptr = &start_addr;
u8 **start_buff = &start_ptr;
u16 buff_len = 0;
+ struct ietf_mpa_v1 *mpa_frame;
skb = dev_alloc_skb(MAX_CM_BUFFER);
if (!skb) {
@@ -242,6 +243,8 @@
/* send an MPA reject frame */
cm_build_mpa_frame(cm_node, start_buff, &buff_len, NULL, MPA_KEY_REPLY);
+ mpa_frame = (struct ietf_mpa_v1 *)*start_buff;
+ mpa_frame->flags |= IETF_MPA_FLAGS_REJECT;
form_cm_frame(skb, cm_node, NULL, 0, *start_buff, buff_len, SET_ACK | SET_FIN);
cm_node->state = NES_CM_STATE_FIN_WAIT1;
@@ -1360,8 +1363,7 @@
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
neigh->ha, ETH_ALEN)) {
/* Mac address same as in nes_arp_table */
- ip_rt_put(rt);
- return rc;
+ goto out;
}
nes_manage_arp_cache(nesvnic->netdev,
@@ -1377,6 +1379,8 @@
neigh_event_send(neigh, NULL);
}
}
+
+out:
rcu_read_unlock();
ip_rt_put(rt);
return rc;
diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
index bdfa1fb..4646e66 100644
--- a/drivers/infiniband/hw/nes/nes_cm.h
+++ b/drivers/infiniband/hw/nes/nes_cm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h
index b4393a1..a69eef1 100644
--- a/drivers/infiniband/hw/nes/nes_context.h
+++ b/drivers/infiniband/hw/nes/nes_context.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 055f4b5..d42c9f4 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 0b590e1..d748e4b 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index b3b2a24..3ba7be3 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel-NE, Inc. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_mgt.h b/drivers/infiniband/hw/nes/nes_mgt.h
index 8c8af25..4f7f701 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.h
+++ b/drivers/infiniband/hw/nes/nes_mgt.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2010 Intel-NE, Inc. All rights reserved.
+* Copyright (c) 2006 - 2011 Intel-NE, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 4b3fa71..f3a3ecf 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h
index 71e133a..4926de7 100644
--- a/drivers/infiniband/hw/nes/nes_user.h
+++ b/drivers/infiniband/hw/nes/nes_user.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Cisco Systems. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
index 8b4c2ff..e98f4fc 100644
--- a/drivers/infiniband/hw/nes/nes_utils.c
+++ b/drivers/infiniband/hw/nes/nes_utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 5095bc4..0927b5c 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -3428,6 +3428,8 @@
NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX,
ib_wr->wr.fast_reg.length);
set_wqe_32bit_value(wqe->wqe_words,
+ NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX, 0);
+ set_wqe_32bit_value(wqe->wqe_words,
NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX,
ib_wr->wr.fast_reg.rkey);
/* Set page size: */
@@ -3724,7 +3726,7 @@
entry->opcode = IB_WC_SEND;
break;
case NES_IWARP_SQ_OP_LOCINV:
- entry->opcode = IB_WR_LOCAL_INV;
+ entry->opcode = IB_WC_LOCAL_INV;
break;
case NES_IWARP_SQ_OP_FAST_REG:
entry->opcode = IB_WC_FAST_REG_MR;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
index fe6b6e9..0eff7c4 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.h
+++ b/drivers/infiniband/hw/nes/nes_verbs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2009 Intel Corporation. All rights reserved.
+ * Copyright (c) 2006 - 2011 Intel Corporation. All rights reserved.
* Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 4f18e2d..d0c64d5 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2105,7 +2105,7 @@
dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
dd->rcd[0]->rcvhdrq_size,
&dd->cspec->dummy_hdrq_phys,
- GFP_KERNEL | __GFP_COMP);
+ GFP_ATOMIC | __GFP_COMP);
if (!dd->cspec->dummy_hdrq) {
qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
/* fallback to just 0'ing */
diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c
index f695061..0fde788 100644
--- a/drivers/infiniband/hw/qib/qib_pcie.c
+++ b/drivers/infiniband/hw/qib/qib_pcie.c
@@ -560,7 +560,7 @@
* BIOS may not set PCIe bus-utilization parameters for best performance.
* Check and optionally adjust them to maximize our throughput.
*/
-static int qib_pcie_caps = 0x51;
+static int qib_pcie_caps;
module_param_named(pcie_caps, qib_pcie_caps, int, S_IRUGO);
MODULE_PARM_DESC(pcie_caps, "Max PCIe tuning: Payload (0..3), ReadReq (4..7)");
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 76457d5..afc166f 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -386,7 +386,7 @@
struct evdev_client *client = file->private_data;
struct evdev *evdev = client->evdev;
struct input_event event;
- int retval;
+ int retval = 0;
if (count < input_event_size())
return -EINVAL;
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c
index a588578..67bec14 100644
--- a/drivers/input/keyboard/twl4030_keypad.c
+++ b/drivers/input/keyboard/twl4030_keypad.c
@@ -34,7 +34,6 @@
#include <linux/i2c/twl.h>
#include <linux/slab.h>
-
/*
* The TWL4030 family chips include a keypad controller that supports
* up to an 8x8 switch matrix. The controller can issue system wakeup
@@ -302,7 +301,7 @@
if (twl4030_kpwrite_u8(kp, i, KEYP_DEB) < 0)
return -EIO;
- /* Set timeout period to 100 ms */
+ /* Set timeout period to 200 ms */
i = KEYP_PERIOD_US(200000, PTV_PRESCALER);
if (twl4030_kpwrite_u8(kp, (i & 0xFF), KEYP_TIMEOUT_L) < 0)
return -EIO;
@@ -466,4 +465,3 @@
MODULE_DESCRIPTION("TWL4030 Keypad Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:twl4030_keypad");
-
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index b4cfc6c..5ec774d 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -512,6 +512,13 @@
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"),
},
},
+ {
+ /* Lenovo Ideapad U455 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
+ },
+ },
{ }
};
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 8250299..4494233 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -164,7 +164,8 @@
struct serio_raw_client *client = file->private_data;
struct serio_raw *serio_raw = client->serio_raw;
char uninitialized_var(c);
- ssize_t retval = 0;
+ ssize_t read = 0;
+ int retval;
if (serio_raw->dead)
return -ENODEV;
@@ -180,13 +181,15 @@
if (serio_raw->dead)
return -ENODEV;
- while (retval < count && serio_raw_fetch_byte(serio_raw, &c)) {
- if (put_user(c, buffer++))
- return -EFAULT;
- retval++;
+ while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
+ if (put_user(c, buffer++)) {
+ retval = -EFAULT;
+ break;
+ }
+ read++;
}
- return retval;
+ return read ?: retval;
}
static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c
index 1455e26..cf0c318 100644
--- a/drivers/media/dvb/dvb-usb/anysee.c
+++ b/drivers/media/dvb/dvb-usb/anysee.c
@@ -887,8 +887,7 @@
/* attach demod */
adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
- &anysee_cxd2820r_config, &adap->dev->i2c_adap,
- NULL);
+ &anysee_cxd2820r_config, &adap->dev->i2c_adap);
state->has_ci = true;
@@ -1189,6 +1188,14 @@
if (ret)
return ret;
+ ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 2)|(0 << 1)|(0 << 0), 0x07);
+ if (ret)
+ return ret;
+
+ ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 2)|(1 << 1)|(1 << 0), 0x07);
+ if (ret)
+ return ret;
+
ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1);
if (ret)
return ret;
diff --git a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
index 8a57ed8..1efc028 100644
--- a/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
+++ b/drivers/media/dvb/dvb-usb/cinergyT2-fe.c
@@ -276,14 +276,15 @@
param.flags = 0;
switch (fep->bandwidth_hz) {
+ default:
case 8000000:
- param.bandwidth = 0;
+ param.bandwidth = 8;
break;
case 7000000:
- param.bandwidth = 1;
+ param.bandwidth = 7;
break;
case 6000000:
- param.bandwidth = 2;
+ param.bandwidth = 6;
break;
}
diff --git a/drivers/media/dvb/frontends/cxd2820r.h b/drivers/media/dvb/frontends/cxd2820r.h
index cf0f546..5aa306e 100644
--- a/drivers/media/dvb/frontends/cxd2820r.h
+++ b/drivers/media/dvb/frontends/cxd2820r.h
@@ -77,14 +77,12 @@
(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
extern struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe
+ struct i2c_adapter *i2c
);
#else
static inline struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe
+ struct i2c_adapter *i2c
)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
diff --git a/drivers/media/dvb/frontends/cxd2820r_core.c b/drivers/media/dvb/frontends/cxd2820r_core.c
index caae7f7..5c7c2aa 100644
--- a/drivers/media/dvb/frontends/cxd2820r_core.c
+++ b/drivers/media/dvb/frontends/cxd2820r_core.c
@@ -482,10 +482,19 @@
/* switch between DVB-T and DVB-T2 when tune fails */
if (priv->last_tune_failed) {
- if (priv->delivery_system == SYS_DVBT)
+ if (priv->delivery_system == SYS_DVBT) {
+ ret = cxd2820r_sleep_t(fe);
+ if (ret)
+ goto error;
+
c->delivery_system = SYS_DVBT2;
- else if (priv->delivery_system == SYS_DVBT2)
+ } else if (priv->delivery_system == SYS_DVBT2) {
+ ret = cxd2820r_sleep_t2(fe);
+ if (ret)
+ goto error;
+
c->delivery_system = SYS_DVBT;
+ }
}
/* set frontend */
@@ -562,7 +571,7 @@
.delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
/* default: DVB-T/T2 */
.info = {
- .name = "Sony CXD2820R (DVB-T/T2)",
+ .name = "Sony CXD2820R",
.caps = FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 |
@@ -572,7 +581,9 @@
FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_QAM_16 |
+ FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
+ FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_QAM_AUTO |
FE_CAN_TRANSMISSION_MODE_AUTO |
@@ -602,8 +613,7 @@
};
struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
- struct i2c_adapter *i2c,
- struct dvb_frontend *fe)
+ struct i2c_adapter *i2c)
{
struct cxd2820r_priv *priv = NULL;
int ret;
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c
index 9fe4519..ec3f6a0 100644
--- a/drivers/media/video/atmel-isi.c
+++ b/drivers/media/video/atmel-isi.c
@@ -922,7 +922,9 @@
isi->fb_descriptors_phys);
iounmap(isi->regs);
+ clk_unprepare(isi->mck);
clk_put(isi->mck);
+ clk_unprepare(isi->pclk);
clk_put(isi->pclk);
kfree(isi);
@@ -955,6 +957,10 @@
if (IS_ERR(pclk))
return PTR_ERR(pclk);
+ ret = clk_prepare(pclk);
+ if (ret)
+ goto err_clk_prepare_pclk;
+
isi = kzalloc(sizeof(struct atmel_isi), GFP_KERNEL);
if (!isi) {
ret = -ENOMEM;
@@ -978,6 +984,10 @@
goto err_clk_get;
}
+ ret = clk_prepare(isi->mck);
+ if (ret)
+ goto err_clk_prepare_mck;
+
/* Set ISI_MCK's frequency, it should be faster than pixel clock */
ret = clk_set_rate(isi->mck, pdata->mck_hz);
if (ret < 0)
@@ -1059,10 +1069,14 @@
isi->fb_descriptors_phys);
err_alloc_descriptors:
err_set_mck_rate:
+ clk_unprepare(isi->mck);
+err_clk_prepare_mck:
clk_put(isi->mck);
err_clk_get:
kfree(isi);
err_alloc_isi:
+ clk_unprepare(pclk);
+err_clk_prepare_pclk:
clk_put(pclk);
return ret;
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
index 9449423..aabbf48 100644
--- a/drivers/media/video/em28xx/em28xx-dvb.c
+++ b/drivers/media/video/em28xx/em28xx-dvb.c
@@ -853,8 +853,7 @@
case EM28174_BOARD_PCTV_290E:
dvb->fe[0] = dvb_attach(cxd2820r_attach,
&em28xx_cxd2820r_config,
- &dev->i2c_adap,
- NULL);
+ &dev->i2c_adap);
if (dvb->fe[0]) {
/* FE 0 attach tuner */
if (!dvb_attach(tda18271_attach,
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 63be60b..86cc3f7 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -26,35 +26,9 @@
#define to_mcp(d) container_of(d, struct mcp, attached_device)
#define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
-static const struct mcp_device_id *mcp_match_id(const struct mcp_device_id *id,
- const char *codec)
-{
- while (id->name[0]) {
- if (strcmp(codec, id->name) == 0)
- return id;
- id++;
- }
- return NULL;
-}
-
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp)
-{
- const struct mcp_driver *driver =
- to_mcp_driver(mcp->attached_device.driver);
-
- return mcp_match_id(driver->id_table, mcp->codec);
-}
-EXPORT_SYMBOL(mcp_get_device_id);
-
static int mcp_bus_match(struct device *dev, struct device_driver *drv)
{
- const struct mcp *mcp = to_mcp(dev);
- const struct mcp_driver *driver = to_mcp_driver(drv);
-
- if (driver->id_table)
- return !!mcp_match_id(driver->id_table, mcp->codec);
-
- return 0;
+ return 1;
}
static int mcp_bus_probe(struct device *dev)
@@ -100,18 +74,9 @@
return ret;
}
-static int mcp_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct mcp *mcp = to_mcp(dev);
-
- add_uevent_var(env, "MODALIAS=%s%s", MCP_MODULE_PREFIX, mcp->codec);
- return 0;
-}
-
static struct bus_type mcp_bus_type = {
.name = "mcp",
.match = mcp_bus_match,
- .uevent = mcp_bus_uevent,
.probe = mcp_bus_probe,
.remove = mcp_bus_remove,
.suspend = mcp_bus_suspend,
@@ -128,9 +93,11 @@
*/
void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
mcp->ops->set_telecom_divisor(mcp, div);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_set_telecom_divisor);
@@ -143,9 +110,11 @@
*/
void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&mcp->lock, flags);
mcp->ops->set_audio_divisor(mcp, div);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_set_audio_divisor);
@@ -198,10 +167,11 @@
*/
void mcp_enable(struct mcp *mcp)
{
- spin_lock_irq(&mcp->lock);
+ unsigned long flags;
+ spin_lock_irqsave(&mcp->lock, flags);
if (mcp->use_count++ == 0)
mcp->ops->enable(mcp);
- spin_unlock_irq(&mcp->lock);
+ spin_unlock_irqrestore(&mcp->lock, flags);
}
EXPORT_SYMBOL(mcp_enable);
@@ -247,14 +217,9 @@
}
EXPORT_SYMBOL(mcp_host_alloc);
-int mcp_host_register(struct mcp *mcp, void *pdata)
+int mcp_host_register(struct mcp *mcp)
{
- if (!mcp->codec)
- return -EINVAL;
-
- mcp->attached_device.platform_data = pdata;
dev_set_name(&mcp->attached_device, "mcp0");
- request_module("%s%s", MCP_MODULE_PREFIX, mcp->codec);
return device_register(&mcp->attached_device);
}
EXPORT_SYMBOL(mcp_host_register);
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 9adc2eb..02c53a0 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -19,7 +19,6 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/mfd/mcp.h>
-#include <linux/io.h>
#include <mach/dma.h>
#include <mach/hardware.h>
@@ -27,19 +26,12 @@
#include <asm/system.h>
#include <mach/mcp.h>
-/* Register offsets */
-#define MCCR0 0x00
-#define MCDR0 0x08
-#define MCDR1 0x0C
-#define MCDR2 0x10
-#define MCSR 0x18
-#define MCCR1 0x00
+#include <mach/assabet.h>
+
struct mcp_sa11x0 {
- u32 mccr0;
- u32 mccr1;
- unsigned char *mccr0_base;
- unsigned char *mccr1_base;
+ u32 mccr0;
+ u32 mccr1;
};
#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
@@ -47,25 +39,25 @@
static void
mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
{
- struct mcp_sa11x0 *priv = priv(mcp);
+ unsigned int mccr0;
divisor /= 32;
- priv->mccr0 &= ~0x00007f00;
- priv->mccr0 |= divisor << 8;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ mccr0 = Ser4MCCR0 & ~0x00007f00;
+ mccr0 |= divisor << 8;
+ Ser4MCCR0 = mccr0;
}
static void
mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
{
- struct mcp_sa11x0 *priv = priv(mcp);
+ unsigned int mccr0;
divisor /= 32;
- priv->mccr0 &= ~0x0000007f;
- priv->mccr0 |= divisor;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ mccr0 = Ser4MCCR0 & ~0x0000007f;
+ mccr0 |= divisor;
+ Ser4MCCR0 = mccr0;
}
/*
@@ -79,16 +71,12 @@
{
int ret = -ETIME;
int i;
- u32 mcpreg;
- struct mcp_sa11x0 *priv = priv(mcp);
- mcpreg = reg << 17 | MCDR2_Wr | (val & 0xffff);
- __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+ Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- mcpreg = __raw_readl(priv->mccr0_base + MCSR);
- if (mcpreg & MCSR_CWC) {
+ if (Ser4MCSR & MCSR_CWC) {
ret = 0;
break;
}
@@ -109,18 +97,13 @@
{
int ret = -ETIME;
int i;
- u32 mcpreg;
- struct mcp_sa11x0 *priv = priv(mcp);
- mcpreg = reg << 17 | MCDR2_Rd;
- __raw_writel(mcpreg, priv->mccr0_base + MCDR2);
+ Ser4MCDR2 = reg << 17 | MCDR2_Rd;
for (i = 0; i < 2; i++) {
udelay(mcp->rw_timeout);
- mcpreg = __raw_readl(priv->mccr0_base + MCSR);
- if (mcpreg & MCSR_CRC) {
- ret = __raw_readl(priv->mccr0_base + MCDR2)
- & 0xffff;
+ if (Ser4MCSR & MCSR_CRC) {
+ ret = Ser4MCDR2 & 0xffff;
break;
}
}
@@ -133,19 +116,13 @@
static void mcp_sa11x0_enable(struct mcp *mcp)
{
- struct mcp_sa11x0 *priv = priv(mcp);
-
- __raw_writel(-1, priv->mccr0_base + MCSR);
- priv->mccr0 |= MCCR0_MCE;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ Ser4MCSR = -1;
+ Ser4MCCR0 |= MCCR0_MCE;
}
static void mcp_sa11x0_disable(struct mcp *mcp)
{
- struct mcp_sa11x0 *priv = priv(mcp);
-
- priv->mccr0 &= ~MCCR0_MCE;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
+ Ser4MCCR0 &= ~MCCR0_MCE;
}
/*
@@ -165,69 +142,50 @@
struct mcp_plat_data *data = pdev->dev.platform_data;
struct mcp *mcp;
int ret;
- struct mcp_sa11x0 *priv;
- struct resource *res_mem0, *res_mem1;
- u32 size0, size1;
if (!data)
return -ENODEV;
- if (!data->codec)
- return -ENODEV;
-
- res_mem0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res_mem0)
- return -ENODEV;
- size0 = res_mem0->end - res_mem0->start + 1;
-
- res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res_mem1)
- return -ENODEV;
- size1 = res_mem1->end - res_mem1->start + 1;
-
- if (!request_mem_region(res_mem0->start, size0, "sa11x0-mcp"))
+ if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
return -EBUSY;
- if (!request_mem_region(res_mem1->start, size1, "sa11x0-mcp")) {
- ret = -EBUSY;
- goto release;
- }
-
mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
if (!mcp) {
ret = -ENOMEM;
- goto release2;
+ goto release;
}
- priv = priv(mcp);
-
mcp->owner = THIS_MODULE;
mcp->ops = &mcp_sa11x0;
mcp->sclk_rate = data->sclk_rate;
- mcp->dma_audio_rd = DDAR_DevAdd(res_mem0->start + MCDR0)
- + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_audio_wr = DDAR_DevAdd(res_mem0->start + MCDR0)
- + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_telco_rd = DDAR_DevAdd(res_mem0->start + MCDR1)
- + DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev;
- mcp->dma_telco_wr = DDAR_DevAdd(res_mem0->start + MCDR1)
- + DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev;
- mcp->codec = data->codec;
+ mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
+ mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
+ mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
+ mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
+ mcp->gpio_base = data->gpio_base;
platform_set_drvdata(pdev, mcp);
+ if (machine_is_assabet()) {
+ ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
+ }
+
+ /*
+ * Setup the PPC unit correctly.
+ */
+ PPDR &= ~PPC_RXD4;
+ PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
+ PSDR |= PPC_RXD4;
+ PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+ PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
+
/*
* Initialise device. Note that we initially
* set the sampling rate to minimum.
*/
- priv->mccr0_base = ioremap(res_mem0->start, size0);
- priv->mccr1_base = ioremap(res_mem1->start, size1);
-
- __raw_writel(-1, priv->mccr0_base + MCSR);
- priv->mccr1 = data->mccr1;
- priv->mccr0 = data->mccr0 | 0x7f7f;
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
- __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+ Ser4MCSR = -1;
+ Ser4MCCR1 = data->mccr1;
+ Ser4MCCR0 = data->mccr0 | 0x7f7f;
/*
* Calculate the read/write timeout (us) from the bit clock
@@ -237,53 +195,36 @@
mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
mcp->sclk_rate;
- ret = mcp_host_register(mcp, data->codec_pdata);
+ ret = mcp_host_register(mcp);
if (ret == 0)
goto out;
- release2:
- release_mem_region(res_mem1->start, size1);
release:
- release_mem_region(res_mem0->start, size0);
+ release_mem_region(0x80060000, 0x60);
platform_set_drvdata(pdev, NULL);
out:
return ret;
}
-static int mcp_sa11x0_remove(struct platform_device *pdev)
+static int mcp_sa11x0_remove(struct platform_device *dev)
{
- struct mcp *mcp = platform_get_drvdata(pdev);
- struct mcp_sa11x0 *priv = priv(mcp);
- struct resource *res_mem;
- u32 size;
+ struct mcp *mcp = platform_get_drvdata(dev);
- platform_set_drvdata(pdev, NULL);
+ platform_set_drvdata(dev, NULL);
mcp_host_unregister(mcp);
+ release_mem_region(0x80060000, 0x60);
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res_mem) {
- size = res_mem->end - res_mem->start + 1;
- release_mem_region(res_mem->start, size);
- }
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (res_mem) {
- size = res_mem->end - res_mem->start + 1;
- release_mem_region(res_mem->start, size);
- }
- iounmap(priv->mccr0_base);
- iounmap(priv->mccr1_base);
return 0;
}
static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
{
struct mcp *mcp = platform_get_drvdata(dev);
- struct mcp_sa11x0 *priv = priv(mcp);
- u32 mccr0;
- mccr0 = priv->mccr0 & ~MCCR0_MCE;
- __raw_writel(mccr0, priv->mccr0_base + MCCR0);
+ priv(mcp)->mccr0 = Ser4MCCR0;
+ priv(mcp)->mccr1 = Ser4MCCR1;
+ Ser4MCCR0 &= ~MCCR0_MCE;
return 0;
}
@@ -291,10 +232,9 @@
static int mcp_sa11x0_resume(struct platform_device *dev)
{
struct mcp *mcp = platform_get_drvdata(dev);
- struct mcp_sa11x0 *priv = priv(mcp);
- __raw_writel(priv->mccr0, priv->mccr0_base + MCCR0);
- __raw_writel(priv->mccr1, priv->mccr1_base + MCCR1);
+ Ser4MCCR1 = priv(mcp)->mccr1;
+ Ser4MCCR0 = priv(mcp)->mccr0;
return 0;
}
@@ -311,7 +251,6 @@
.resume = mcp_sa11x0_resume,
.driver = {
.name = "sa11x0-mcp",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 91c4f25..febc90c 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -36,15 +36,6 @@
static LIST_HEAD(ucb1x00_drivers);
static LIST_HEAD(ucb1x00_devices);
-static struct mcp_device_id ucb1x00_id[] = {
- { "ucb1x00", 0 }, /* auto-detection */
- { "ucb1200", UCB_ID_1200 },
- { "ucb1300", UCB_ID_1300 },
- { "tc35143", UCB_ID_TC35143 },
- { }
-};
-MODULE_DEVICE_TABLE(mcp, ucb1x00_id);
-
/**
* ucb1x00_io_set_dir - set IO direction
* @ucb: UCB1x00 structure describing chip
@@ -157,16 +148,22 @@
{
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
unsigned long flags;
+ unsigned old, mask = 1 << offset;
spin_lock_irqsave(&ucb->io_lock, flags);
- ucb->io_dir |= (1 << offset);
- ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
-
+ old = ucb->io_out;
if (value)
- ucb->io_out |= 1 << offset;
+ ucb->io_out |= mask;
else
- ucb->io_out &= ~(1 << offset);
- ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+ ucb->io_out &= ~mask;
+
+ if (old != ucb->io_out)
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
+
+ if (!(ucb->io_dir & mask)) {
+ ucb->io_dir |= mask;
+ ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
+ }
spin_unlock_irqrestore(&ucb->io_lock, flags);
return 0;
@@ -536,33 +533,17 @@
static int ucb1x00_probe(struct mcp *mcp)
{
- const struct mcp_device_id *mid;
struct ucb1x00 *ucb;
struct ucb1x00_driver *drv;
- struct ucb1x00_plat_data *pdata;
unsigned int id;
int ret = -ENODEV;
int temp;
mcp_enable(mcp);
id = mcp_reg_read(mcp, UCB_ID);
- mid = mcp_get_device_id(mcp);
- if (mid && mid->driver_data) {
- if (id != mid->driver_data) {
- printk(KERN_WARNING "%s wrong ID %04x found: %04x\n",
- mid->name, (unsigned int) mid->driver_data, id);
- goto err_disable;
- }
- } else {
- mid = &ucb1x00_id[1];
- while (mid->driver_data) {
- if (id == mid->driver_data)
- break;
- mid++;
- }
- printk(KERN_WARNING "%s ID not found: %04x\n",
- ucb1x00_id[0].name, id);
+ if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
+ printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
goto err_disable;
}
@@ -571,28 +552,28 @@
if (!ucb)
goto err_disable;
- pdata = mcp->attached_device.platform_data;
+
ucb->dev.class = &ucb1x00_class;
ucb->dev.parent = &mcp->attached_device;
- dev_set_name(&ucb->dev, mid->name);
+ dev_set_name(&ucb->dev, "ucb1x00");
spin_lock_init(&ucb->lock);
spin_lock_init(&ucb->io_lock);
sema_init(&ucb->adc_sem, 1);
- ucb->id = mid;
+ ucb->id = id;
ucb->mcp = mcp;
ucb->irq = ucb1x00_detect_irq(ucb);
if (ucb->irq == NO_IRQ) {
- printk(KERN_ERR "%s: IRQ probe failed\n", mid->name);
+ printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
ret = -ENODEV;
goto err_free;
}
ucb->gpio.base = -1;
- if (pdata && (pdata->gpio_base >= 0)) {
+ if (mcp->gpio_base != 0) {
ucb->gpio.label = dev_name(&ucb->dev);
- ucb->gpio.base = pdata->gpio_base;
+ ucb->gpio.base = mcp->gpio_base;
ucb->gpio.ngpio = 10;
ucb->gpio.set = ucb1x00_gpio_set;
ucb->gpio.get = ucb1x00_gpio_get;
@@ -605,10 +586,10 @@
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
- mid->name, ucb);
+ "UCB1x00", ucb);
if (ret) {
- printk(KERN_ERR "%s: unable to grab irq%d: %d\n",
- mid->name, ucb->irq, ret);
+ printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
+ ucb->irq, ret);
goto err_gpio;
}
@@ -712,6 +693,7 @@
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
struct ucb1x00_dev *dev;
+ ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
mutex_lock(&ucb1x00_mutex);
list_for_each_entry(dev, &ucb->devs, dev_node) {
@@ -730,7 +712,6 @@
.remove = ucb1x00_remove,
.suspend = ucb1x00_suspend,
.resume = ucb1x00_resume,
- .id_table = ucb1x00_id,
};
static int __init ucb1x00_init(void)
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c
index 40ec3c1..63a3cbd 100644
--- a/drivers/mfd/ucb1x00-ts.c
+++ b/drivers/mfd/ucb1x00-ts.c
@@ -47,7 +47,6 @@
u16 x_res;
u16 y_res;
- unsigned int restart:1;
unsigned int adcsync:1;
};
@@ -207,15 +206,17 @@
{
struct ucb1x00_ts *ts = _ts;
DECLARE_WAITQUEUE(wait, current);
+ bool frozen, ignore = false;
int valid = 0;
set_freezable();
add_wait_queue(&ts->irq_wait, &wait);
- while (!kthread_should_stop()) {
+ while (!kthread_freezable_should_stop(&frozen)) {
unsigned int x, y, p;
signed long timeout;
- ts->restart = 0;
+ if (frozen)
+ ignore = true;
ucb1x00_adc_enable(ts->ucb);
@@ -258,7 +259,7 @@
* space. We therefore leave it to user space
* to do any filtering they please.
*/
- if (!ts->restart) {
+ if (!ignore) {
ucb1x00_ts_evt_add(ts, p, x, y);
valid = 1;
}
@@ -267,8 +268,6 @@
timeout = HZ / 100;
}
- try_to_freeze();
-
schedule_timeout(timeout);
}
@@ -340,26 +339,6 @@
ucb1x00_disable(ts->ucb);
}
-#ifdef CONFIG_PM
-static int ucb1x00_ts_resume(struct ucb1x00_dev *dev)
-{
- struct ucb1x00_ts *ts = dev->priv;
-
- if (ts->rtask != NULL) {
- /*
- * Restart the TS thread to ensure the
- * TS interrupt mode is set up again
- * after sleep.
- */
- ts->restart = 1;
- wake_up(&ts->irq_wait);
- }
- return 0;
-}
-#else
-#define ucb1x00_ts_resume NULL
-#endif
-
/*
* Initialisation.
@@ -382,7 +361,7 @@
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
idev->name = "Touchscreen panel";
- idev->id.product = ts->ucb->id->driver_data;
+ idev->id.product = ts->ucb->id;
idev->open = ucb1x00_ts_open;
idev->close = ucb1x00_ts_close;
@@ -425,7 +404,6 @@
static struct ucb1x00_driver ucb1x00_ts_driver = {
.add = ucb1x00_ts_add,
.remove = ucb1x00_ts_remove,
- .resume = ucb1x00_ts_resume,
};
static int __init ucb1x00_ts_init(void)
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 150cd70..28adefe 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -354,6 +354,7 @@
static void lkdtm_handler(void)
{
unsigned long flags;
+ bool do_it = false;
spin_lock_irqsave(&count_lock, flags);
count--;
@@ -361,10 +362,13 @@
cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
if (count == 0) {
- lkdtm_do_action(cptype);
+ do_it = true;
count = cpoint_count;
}
spin_unlock_irqrestore(&count_lock, flags);
+
+ if (do_it)
+ lkdtm_do_action(cptype);
}
static int lkdtm_register_cpoint(enum cname which)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 6ae9ca0..9a9ce71 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -119,7 +119,7 @@
{
struct mtd_info *mtd = dev_get_drvdata(dev);
- return mtd_suspend(mtd);
+ return mtd ? mtd_suspend(mtd) : 0;
}
static int mtd_cls_resume(struct device *dev)
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 4dd056e..35b4fb5 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -161,6 +161,37 @@
!!host->board->rdy_pin_active_low;
}
+/*
+ * Minimal-overhead PIO for data access.
+ */
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
+}
+
+static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+}
+
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
+}
+
+static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+
+ __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+}
+
static void dma_complete_func(void *completion)
{
complete(completion);
@@ -235,27 +266,33 @@
static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
if (use_dma && len > mtd->oobsize)
/* only use DMA for bigger than oob size: better performances */
if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
return;
- /* if no DMA operation possible, use PIO */
- memcpy_fromio(buf, chip->IO_ADDR_R, len);
+ if (host->board->bus_width_16)
+ atmel_read_buf16(mtd, buf, len);
+ else
+ atmel_read_buf8(mtd, buf, len);
}
static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
struct nand_chip *chip = mtd->priv;
+ struct atmel_nand_host *host = chip->priv;
if (use_dma && len > mtd->oobsize)
/* only use DMA for bigger than oob size: better performances */
if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
return;
- /* if no DMA operation possible, use PIO */
- memcpy_toio(chip->IO_ADDR_W, buf, len);
+ if (host->board->bus_width_16)
+ atmel_write_buf16(mtd, buf, len);
+ else
+ atmel_write_buf8(mtd, buf, len);
}
/*
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
index 7f68042..7db6555 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c
@@ -69,17 +69,19 @@
* [1] enable the module.
* [2] reset the module.
*
- * In most of the cases, it's ok. But there is a hardware bug in the BCH block.
+ * In most of the cases, it's ok.
+ * But in MX23, there is a hardware bug in the BCH block (see erratum #2847).
* If you try to soft reset the BCH block, it becomes unusable until
* the next hard reset. This case occurs in the NAND boot mode. When the board
* boots by NAND, the ROM of the chip will initialize the BCH blocks itself.
* So If the driver tries to reset the BCH again, the BCH will not work anymore.
- * You will see a DMA timeout in this case.
+ * You will see a DMA timeout in this case. The bug has been fixed
+ * in the following chips, such as MX28.
*
* To avoid this bug, just add a new parameter `just_enable` for
* the mxs_reset_block(), and rewrite it here.
*/
-int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
+static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
{
int ret;
int timeout = 0x400;
@@ -206,7 +208,15 @@
if (ret)
goto err_out;
- ret = gpmi_reset_block(r->bch_regs, true);
+ /*
+ * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
+ * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
+ * On the other hand, the MX28 needs the reset, because one case has been
+ * seen where the BCH produced ECC errors constantly after 10000
+ * consecutive reboots. The latter case has not been seen on the MX23 yet,
+ * still we don't know if it could happen there as well.
+ */
+ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
if (ret)
goto err_out;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 35b4565..8a393f9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2588,7 +2588,7 @@
instr->state = MTD_ERASING;
while (len) {
- /* Heck if we have a bad block, we do not erase bad blocks! */
+ /* Check if we have a bad block, we do not erase bad blocks! */
if (nand_block_checkbad(mtd, ((loff_t) page) <<
chip->page_shift, 0, allowbbt)) {
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 752493f..65d1f05 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -972,11 +972,11 @@
}
#endif
- spin_unlock_irqrestore(&trans->shrd->lock, flags);
-
/* saved interrupt in inta variable now we can reset trans_pcie->inta */
trans_pcie->inta = 0;
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
/* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) {
IWL_ERR(trans, "Hardware error detected. Restarting.\n");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index fa67905..698b905 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -68,7 +68,7 @@
#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
-#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
+#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
struct netfront_stats {
u64 rx_packets;
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index 5986690..27f2fe3 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -205,7 +205,8 @@
dev_set_drvdata(&dev->dev, NULL);
- for (; next = s->next, s; s = next) {
+ for (; s; s = next) {
+ next = s->next;
soc_pcmcia_remove_one(&s->soc);
kfree(s);
}
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 569bdb3..8fe15cf 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -510,10 +510,12 @@
static void pinctrl_init_device_debugfs(struct pinctrl_dev *pctldev)
{
- static struct dentry *device_root;
+ struct dentry *device_root;
device_root = debugfs_create_dir(dev_name(pctldev->dev),
debugfs_root);
+ pctldev->device_root = device_root;
+
if (IS_ERR(device_root) || !device_root) {
pr_warn("failed to create debugfs directory for %s\n",
dev_name(pctldev->dev));
@@ -529,6 +531,11 @@
pinconf_init_device_debugfs(device_root, pctldev);
}
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+ debugfs_remove_recursive(pctldev->device_root);
+}
+
static void pinctrl_init_debugfs(void)
{
debugfs_root = debugfs_create_dir("pinctrl", NULL);
@@ -553,6 +560,10 @@
{
}
+static void pinctrl_remove_device_debugfs(struct pinctrl_dev *pctldev)
+{
+}
+
#endif
/**
@@ -572,26 +583,6 @@
if (pctldesc->name == NULL)
return NULL;
- /* If we're implementing pinmuxing, check the ops for sanity */
- if (pctldesc->pmxops) {
- ret = pinmux_check_ops(pctldesc->pmxops);
- if (ret) {
- pr_err("%s pinmux ops lacks necessary functions\n",
- pctldesc->name);
- return NULL;
- }
- }
-
- /* If we're implementing pinconfig, check the ops for sanity */
- if (pctldesc->confops) {
- ret = pinconf_check_ops(pctldesc->confops);
- if (ret) {
- pr_err("%s pin config ops lacks necessary functions\n",
- pctldesc->name);
- return NULL;
- }
- }
-
pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
if (pctldev == NULL)
return NULL;
@@ -606,6 +597,26 @@
mutex_init(&pctldev->gpio_ranges_lock);
pctldev->dev = dev;
+ /* If we're implementing pinmuxing, check the ops for sanity */
+ if (pctldesc->pmxops) {
+ ret = pinmux_check_ops(pctldev);
+ if (ret) {
+ pr_err("%s pinmux ops lacks necessary functions\n",
+ pctldesc->name);
+ goto out_err;
+ }
+ }
+
+ /* If we're implementing pinconfig, check the ops for sanity */
+ if (pctldesc->confops) {
+ ret = pinconf_check_ops(pctldev);
+ if (ret) {
+ pr_err("%s pin config ops lacks necessary functions\n",
+ pctldesc->name);
+ goto out_err;
+ }
+ }
+
/* Register all the pins */
pr_debug("try to register %d pins on %s...\n",
pctldesc->npins, pctldesc->name);
@@ -641,6 +652,7 @@
if (pctldev == NULL)
return;
+ pinctrl_remove_device_debugfs(pctldev);
pinmux_unhog_maps(pctldev);
/* TODO: check that no pinmuxes are still active? */
mutex_lock(&pinctrldev_list_mutex);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index 177a331..cfa86da 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -41,6 +41,9 @@
struct device *dev;
struct module *owner;
void *driver_data;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *device_root;
+#endif
#ifdef CONFIG_PINMUX
struct mutex pinmux_hogs_lock;
struct list_head pinmux_hogs;
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index 1259872..9fb7545 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -205,8 +205,10 @@
}
EXPORT_SYMBOL(pin_config_group_set);
-int pinconf_check_ops(const struct pinconf_ops *ops)
+int pinconf_check_ops(struct pinctrl_dev *pctldev)
{
+ const struct pinconf_ops *ops = pctldev->desc->confops;
+
/* We must be able to read out pin status */
if (!ops->pin_config_get && !ops->pin_config_group_get)
return -EINVAL;
@@ -236,7 +238,7 @@
seq_puts(s, "Format: pin (name): pinmux setting array\n");
/* The pin number can be retrived from the pin controller descriptor */
- for (i = 0; pin < pctldev->desc->npins; i++) {
+ for (i = 0; i < pctldev->desc->npins; i++) {
struct pin_desc *desc;
pin = pctldev->desc->pins[i].number;
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index e7dc616..006b77f 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -13,7 +13,7 @@
#ifdef CONFIG_PINCONF
-int pinconf_check_ops(const struct pinconf_ops *ops);
+int pinconf_check_ops(struct pinctrl_dev *pctldev);
void pinconf_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
@@ -23,7 +23,7 @@
#else
-static inline int pinconf_check_ops(const struct pinconf_ops *ops)
+static inline int pinconf_check_ops(struct pinctrl_dev *pctldev)
{
return 0;
}
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index a76a348..7c3193f 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -53,11 +53,6 @@
* @dev: the device using this pinmux
* @usecount: the number of active users of this mux setting, used to keep
* track of nested use cases
- * @pins: an array of discrete physical pins used in this mapping, taken
- * from the global pin enumeration space (copied from pinmux map)
- * @num_pins: the number of pins in this mapping array, i.e. the number of
- * elements in .pins so we can iterate over that array (copied from
- * pinmux map)
* @pctldev: pin control device handling this pinmux
* @func_selector: the function selector for the pinmux device handling
* this pinmux
@@ -152,8 +147,7 @@
status = 0;
if (status)
- dev_err(pctldev->dev, "->request on device %s failed "
- "for pin %d\n",
+ dev_err(pctldev->dev, "->request on device %s failed for pin %d\n",
pctldev->desc->name, pin);
out_free_pin:
if (status) {
@@ -355,21 +349,20 @@
/* First sanity check the new mapping */
for (i = 0; i < num_maps; i++) {
if (!maps[i].name) {
- pr_err("failed to register map %d: "
- "no map name given\n", i);
+ pr_err("failed to register map %d: no map name given\n",
+ i);
return -EINVAL;
}
if (!maps[i].ctrl_dev && !maps[i].ctrl_dev_name) {
- pr_err("failed to register map %s (%d): "
- "no pin control device given\n",
+ pr_err("failed to register map %s (%d): no pin control device given\n",
maps[i].name, i);
return -EINVAL;
}
if (!maps[i].function) {
- pr_err("failed to register map %s (%d): "
- "no function ID given\n", maps[i].name, i);
+ pr_err("failed to register map %s (%d): no function ID given\n",
+ maps[i].name, i);
return -EINVAL;
}
@@ -411,7 +404,7 @@
}
/**
- * acquire_pins() - acquire all the pins for a certain funcion on a pinmux
+ * acquire_pins() - acquire all the pins for a certain function on a pinmux
* @pctldev: the device to take the pins on
* @func_selector: the function selector to acquire the pins for
* @group_selector: the group selector containing the pins to acquire
@@ -442,8 +435,7 @@
ret = pin_request(pctldev, pins[i], func, NULL);
if (ret) {
dev_err(pctldev->dev,
- "could not get pin %d for function %s "
- "on device %s - conflicting mux mappings?\n",
+ "could not get pin %d for function %s on device %s - conflicting mux mappings?\n",
pins[i], func ? : "(undefined)",
pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
@@ -458,7 +450,7 @@
/**
* release_pins() - release pins taken by earlier acquirement
- * @pctldev: the device to free the pinx on
+ * @pctldev: the device to free the pins on
* @group_selector: the group selector containing the pins to free
*/
static void release_pins(struct pinctrl_dev *pctldev,
@@ -473,8 +465,7 @@
ret = pctlops->get_group_pins(pctldev, group_selector,
&pins, &num_pins);
if (ret) {
- dev_err(pctldev->dev, "could not get pins to release for "
- "group selector %d\n",
+ dev_err(pctldev->dev, "could not get pins to release for group selector %d\n",
group_selector);
return;
}
@@ -526,8 +517,7 @@
ret = pinctrl_get_group_selector(pctldev, groups[0]);
if (ret < 0) {
dev_err(pctldev->dev,
- "function %s wants group %s but the pin "
- "controller does not seem to have that group\n",
+ "function %s wants group %s but the pin controller does not seem to have that group\n",
pmxops->get_function_name(pctldev, func_selector),
groups[0]);
return ret;
@@ -535,8 +525,7 @@
if (num_groups > 1)
dev_dbg(pctldev->dev,
- "function %s support more than one group, "
- "default-selecting first group %s (%d)\n",
+ "function %s support more than one group, default-selecting first group %s (%d)\n",
pmxops->get_function_name(pctldev, func_selector),
groups[0],
ret);
@@ -628,10 +617,8 @@
if (pmx->pctldev && pmx->pctldev != pctldev) {
dev_err(pctldev->dev,
- "different pin control devices given for device %s, "
- "function %s\n",
- devname,
- map->function);
+ "different pin control devices given for device %s, function %s\n",
+ devname, map->function);
return -EINVAL;
}
pmx->dev = dev;
@@ -695,7 +682,6 @@
*/
struct pinmux *pinmux_get(struct device *dev, const char *name)
{
-
struct pinmux_map const *map = NULL;
struct pinctrl_dev *pctldev = NULL;
const char *devname = NULL;
@@ -745,8 +731,7 @@
else if (map->ctrl_dev_name)
devname = map->ctrl_dev_name;
- pr_warning("could not find a pinctrl device for pinmux "
- "function %s, fishy, they shall all have one\n",
+ pr_warning("could not find a pinctrl device for pinmux function %s, fishy, they shall all have one\n",
map->function);
pr_warning("given pinctrl device name: %s",
devname ? devname : "UNDEFINED");
@@ -904,8 +889,11 @@
}
EXPORT_SYMBOL_GPL(pinmux_disable);
-int pinmux_check_ops(const struct pinmux_ops *ops)
+int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
+ const struct pinmux_ops *ops = pctldev->desc->pmxops;
+ unsigned selector = 0;
+
/* Check that we implement required operations */
if (!ops->list_functions ||
!ops->get_function_name ||
@@ -914,6 +902,18 @@
!ops->disable)
return -EINVAL;
+ /* Check that all functions registered have names */
+ while (ops->list_functions(pctldev, selector) >= 0) {
+ const char *fname = ops->get_function_name(pctldev,
+ selector);
+ if (!fname) {
+ pr_err("pinmux ops has no name for function%u\n",
+ selector);
+ return -EINVAL;
+ }
+ selector++;
+ }
+
return 0;
}
@@ -932,8 +932,8 @@
* without any problems, so then we can hog pinmuxes for
* all devices that just want a static pin mux at this point.
*/
- dev_err(pctldev->dev, "map %s wants to hog a non-system "
- "pinmux, this is not going to work\n", map->name);
+ dev_err(pctldev->dev, "map %s wants to hog a non-system pinmux, this is not going to work\n",
+ map->name);
return -EINVAL;
}
@@ -993,9 +993,12 @@
for (i = 0; i < pinmux_maps_num; i++) {
struct pinmux_map const *map = &pinmux_maps[i];
- if (((map->ctrl_dev == dev) ||
- !strcmp(map->ctrl_dev_name, devname)) &&
- map->hog_on_boot) {
+ if (!map->hog_on_boot)
+ continue;
+
+ if ((map->ctrl_dev == dev) ||
+ (map->ctrl_dev_name &&
+ !strcmp(map->ctrl_dev_name, devname))) {
/* OK time to hog! */
ret = pinmux_hog_map(pctldev, map);
if (ret)
@@ -1122,13 +1125,15 @@
seq_printf(s, "device: %s function: %s (%u),",
pinctrl_dev_get_name(pmx->pctldev),
- pmxops->get_function_name(pctldev, pmx->func_selector),
+ pmxops->get_function_name(pctldev,
+ pmx->func_selector),
pmx->func_selector);
seq_printf(s, " groups: [");
list_for_each_entry(grp, &pmx->groups, node) {
seq_printf(s, " %s (%u)",
- pctlops->get_group_name(pctldev, grp->group_selector),
+ pctlops->get_group_name(pctldev,
+ grp->group_selector),
grp->group_selector);
}
seq_printf(s, " ]");
diff --git a/drivers/pinctrl/pinmux.h b/drivers/pinctrl/pinmux.h
index 844500b..97f5222 100644
--- a/drivers/pinctrl/pinmux.h
+++ b/drivers/pinctrl/pinmux.h
@@ -12,7 +12,7 @@
*/
#ifdef CONFIG_PINMUX
-int pinmux_check_ops(const struct pinmux_ops *ops);
+int pinmux_check_ops(struct pinctrl_dev *pctldev);
void pinmux_init_device_debugfs(struct dentry *devroot,
struct pinctrl_dev *pctldev);
void pinmux_init_debugfs(struct dentry *subsys_root);
@@ -21,7 +21,7 @@
#else
-static inline int pinmux_check_ops(const struct pinmux_ops *ops)
+static inline int pinmux_check_ops(struct pinctrl_dev *pctldev)
{
return 0;
}
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index f1651eb..679734d 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -35,7 +35,7 @@
if (constraints->min_uV != constraints->max_uV)
constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE;
/* Only one voltage? Then make sure it's set. */
- if (constraints->min_uV == constraints->max_uV)
+ if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
constraints->apply_uV = true;
uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index e19a403..3a125b8 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -774,7 +774,7 @@
config RTC_DRV_SA1100
tristate "SA11x0/PXA2xx"
- depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+ depends on ARCH_SA1100 || ARCH_PXA
help
If you say Y here you will get access to the real time clock
built into your SA11x0 or PXA2xx CPU.
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 4595d3e..cb9a585 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -27,42 +27,34 @@
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
+#include <linux/string.h>
#include <linux/pm.h>
-#include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/io.h>
+#include <linux/bitops.h>
#include <mach/hardware.h>
#include <asm/irq.h>
+#ifdef CONFIG_ARCH_PXA
+#include <mach/regs-rtc.h>
+#endif
+
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
-#define RTC_FREQ 1024
-#define RCNR 0x00 /* RTC Count Register */
-#define RTAR 0x04 /* RTC Alarm Register */
-#define RTSR 0x08 /* RTC Status Register */
-#define RTTR 0x0c /* RTC Timer Trim Register */
+static const unsigned long RTC_FREQ = 1024;
+static struct rtc_time rtc_alarm;
+static DEFINE_SPINLOCK(sa1100_rtc_lock);
-#define RTSR_HZE (1 << 3) /* HZ interrupt enable */
-#define RTSR_ALE (1 << 2) /* RTC alarm interrupt enable */
-#define RTSR_HZ (1 << 1) /* HZ rising-edge detected */
-#define RTSR_AL (1 << 0) /* RTC alarm detected */
+static inline int rtc_periodic_alarm(struct rtc_time *tm)
+{
+ return (tm->tm_year == -1) ||
+ ((unsigned)tm->tm_mon >= 12) ||
+ ((unsigned)(tm->tm_mday - 1) >= 31) ||
+ ((unsigned)tm->tm_hour > 23) ||
+ ((unsigned)tm->tm_min > 59) ||
+ ((unsigned)tm->tm_sec > 59);
+}
-#define rtc_readl(sa1100_rtc, reg) \
- readl_relaxed((sa1100_rtc)->base + (reg))
-#define rtc_writel(sa1100_rtc, reg, value) \
- writel_relaxed((value), (sa1100_rtc)->base + (reg))
-
-struct sa1100_rtc {
- struct resource *ress;
- void __iomem *base;
- struct clk *clk;
- int irq_1Hz;
- int irq_Alrm;
- struct rtc_device *rtc;
- spinlock_t lock; /* Protects this structure */
-};
/*
* Calculate the next alarm time given the requested alarm time mask
* and the current time.
@@ -90,26 +82,46 @@
}
}
+static int rtc_update_alarm(struct rtc_time *alrm)
+{
+ struct rtc_time alarm_tm, now_tm;
+ unsigned long now, time;
+ int ret;
+
+ do {
+ now = RCNR;
+ rtc_time_to_tm(now, &now_tm);
+ rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
+ ret = rtc_tm_to_time(&alarm_tm, &time);
+ if (ret != 0)
+ break;
+
+ RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
+ RTAR = time;
+ } while (now != RCNR);
+
+ return ret;
+}
+
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
{
struct platform_device *pdev = to_platform_device(dev_id);
- struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
unsigned int rtsr;
unsigned long events = 0;
- spin_lock(&sa1100_rtc->lock);
+ spin_lock(&sa1100_rtc_lock);
+ rtsr = RTSR;
/* clear interrupt sources */
- rtsr = rtc_readl(sa1100_rtc, RTSR);
- rtc_writel(sa1100_rtc, RTSR, 0);
-
+ RTSR = 0;
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
/* This is the original code, before there was the if test
* above. This code does not clear interrupts that were not
* enabled. */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2));
+ RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
} else {
/* For some reason, it is possible to enter this routine
* without interruptions enabled, it has been tested with
@@ -118,13 +130,13 @@
* This situation leads to an infinite "loop" of interrupt
* routine calling and as a result the processor seems to
* lock on its first call to open(). */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+ RTSR = RTSR_AL | RTSR_HZ;
}
/* clear alarm interrupt if it has occurred */
if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE));
+ RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
/* update irq data & counter */
if (rtsr & RTSR_AL)
@@ -132,100 +144,89 @@
if (rtsr & RTSR_HZ)
events |= RTC_UF | RTC_IRQF;
- rtc_update_irq(sa1100_rtc->rtc, 1, events);
+ rtc_update_irq(rtc, 1, events);
- spin_unlock(&sa1100_rtc->lock);
+ if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
+ rtc_update_alarm(&rtc_alarm);
+
+ spin_unlock(&sa1100_rtc_lock);
return IRQ_HANDLED;
}
static int sa1100_rtc_open(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
int ret;
+ struct platform_device *plat_dev = to_platform_device(dev);
+ struct rtc_device *rtc = platform_get_drvdata(plat_dev);
- ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt,
- IRQF_DISABLED, "rtc 1Hz", dev);
+ ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
+ "rtc 1Hz", dev);
if (ret) {
- dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_1Hz);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
goto fail_ui;
}
- ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt,
- IRQF_DISABLED, "rtc Alrm", dev);
+ ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
+ "rtc Alrm", dev);
if (ret) {
- dev_err(dev, "IRQ %d already in use.\n", sa1100_rtc->irq_Alrm);
+ dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
goto fail_ai;
}
- sa1100_rtc->rtc->max_user_freq = RTC_FREQ;
- rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ);
+ rtc->max_user_freq = RTC_FREQ;
+ rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
return 0;
fail_ai:
- free_irq(sa1100_rtc->irq_1Hz, dev);
+ free_irq(IRQ_RTC1Hz, dev);
fail_ui:
return ret;
}
static void sa1100_rtc_release(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
+ spin_lock_irq(&sa1100_rtc_lock);
+ RTSR = 0;
+ spin_unlock_irq(&sa1100_rtc_lock);
- spin_lock_irq(&sa1100_rtc->lock);
- rtc_writel(sa1100_rtc, RTSR, 0);
- spin_unlock_irq(&sa1100_rtc->lock);
-
- free_irq(sa1100_rtc->irq_Alrm, dev);
- free_irq(sa1100_rtc->irq_1Hz, dev);
+ free_irq(IRQ_RTCAlrm, dev);
+ free_irq(IRQ_RTC1Hz, dev);
}
static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- unsigned int rtsr;
-
- spin_lock_irq(&sa1100_rtc->lock);
-
- rtsr = rtc_readl(sa1100_rtc, RTSR);
+ spin_lock_irq(&sa1100_rtc_lock);
if (enabled)
- rtsr |= RTSR_ALE;
+ RTSR |= RTSR_ALE;
else
- rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr);
-
- spin_unlock_irq(&sa1100_rtc->lock);
+ RTSR &= ~RTSR_ALE;
+ spin_unlock_irq(&sa1100_rtc_lock);
return 0;
}
static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
- rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm);
+ rtc_time_to_tm(RCNR, tm);
return 0;
}
static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
unsigned long time;
int ret;
ret = rtc_tm_to_time(tm, &time);
if (ret == 0)
- rtc_writel(sa1100_rtc, RCNR, time);
+ RCNR = time;
return ret;
}
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- unsigned long time;
- unsigned int rtsr;
+ u32 rtsr;
- time = rtc_readl(sa1100_rtc, RCNR);
- rtc_time_to_tm(time, &alrm->time);
- rtsr = rtc_readl(sa1100_rtc, RTSR);
+ memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
+ rtsr = RTSR;
alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
return 0;
@@ -233,39 +234,26 @@
static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
- struct rtc_time now_tm, alarm_tm;
- unsigned long time, alarm;
- unsigned int rtsr;
+ int ret;
- spin_lock_irq(&sa1100_rtc->lock);
+ spin_lock_irq(&sa1100_rtc_lock);
+ ret = rtc_update_alarm(&alrm->time);
+ if (ret == 0) {
+ if (alrm->enabled)
+ RTSR |= RTSR_ALE;
+ else
+ RTSR &= ~RTSR_ALE;
+ }
+ spin_unlock_irq(&sa1100_rtc_lock);
- time = rtc_readl(sa1100_rtc, RCNR);
- rtc_time_to_tm(time, &now_tm);
- rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
- rtc_tm_to_time(&alarm_tm, &alarm);
- rtc_writel(sa1100_rtc, RTAR, alarm);
-
- rtsr = rtc_readl(sa1100_rtc, RTSR);
- if (alrm->enabled)
- rtsr |= RTSR_ALE;
- else
- rtsr &= ~RTSR_ALE;
- rtc_writel(sa1100_rtc, RTSR, rtsr);
-
- spin_unlock_irq(&sa1100_rtc->lock);
-
- return 0;
+ return ret;
}
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
+ seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+ seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
- seq_printf(seq, "trim/divider\t\t: 0x%08x\n",
- rtc_readl(sa1100_rtc, RTTR));
- seq_printf(seq, "RTSR\t\t\t: 0x%08x\n",
- rtc_readl(sa1100_rtc, RTSR));
return 0;
}
@@ -282,51 +270,7 @@
static int sa1100_rtc_probe(struct platform_device *pdev)
{
- struct sa1100_rtc *sa1100_rtc;
- unsigned int rttr;
- int ret;
-
- sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
- if (!sa1100_rtc)
- return -ENOMEM;
-
- spin_lock_init(&sa1100_rtc->lock);
- platform_set_drvdata(pdev, sa1100_rtc);
-
- ret = -ENXIO;
- sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!sa1100_rtc->ress) {
- dev_err(&pdev->dev, "No I/O memory resource defined\n");
- goto err_ress;
- }
-
- sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0);
- if (sa1100_rtc->irq_1Hz < 0) {
- dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n");
- goto err_ress;
- }
- sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1);
- if (sa1100_rtc->irq_Alrm < 0) {
- dev_err(&pdev->dev, "No alarm IRQ resource defined\n");
- goto err_ress;
- }
-
- ret = -ENOMEM;
- sa1100_rtc->base = ioremap(sa1100_rtc->ress->start,
- resource_size(sa1100_rtc->ress));
- if (!sa1100_rtc->base) {
- dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory\n");
- goto err_map;
- }
-
- sa1100_rtc->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(sa1100_rtc->clk)) {
- dev_err(&pdev->dev, "failed to find rtc clock source\n");
- ret = PTR_ERR(sa1100_rtc->clk);
- goto err_clk;
- }
- clk_prepare(sa1100_rtc->clk);
- clk_enable(sa1100_rtc->clk);
+ struct rtc_device *rtc;
/*
* According to the manual we should be able to let RTTR be zero
@@ -335,24 +279,24 @@
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
- if (rtc_readl(sa1100_rtc, RTTR) == 0) {
- rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- rtc_writel(sa1100_rtc, RTTR, rttr);
- dev_warn(&pdev->dev, "warning: initializing default clock"
- " divider/trim value\n");
+ if (RTTR == 0) {
+ RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ dev_warn(&pdev->dev, "warning: "
+ "initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */
- rtc_writel(sa1100_rtc, RCNR, 0);
+ RCNR = 0;
}
device_init_wakeup(&pdev->dev, 1);
- sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
- &sa1100_rtc_ops, THIS_MODULE);
- if (IS_ERR(sa1100_rtc->rtc)) {
- dev_err(&pdev->dev, "Failed to register RTC device -> %d\n",
- ret);
- goto err_rtc_reg;
- }
+ rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
+ THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ platform_set_drvdata(pdev, rtc);
+
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_interrupt().
*
@@ -375,46 +319,33 @@
*
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to
* the corresponding bits in RTSR. */
- rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
+ RTSR = RTSR_AL | RTSR_HZ;
return 0;
-
-err_rtc_reg:
-err_clk:
- iounmap(sa1100_rtc->base);
-err_ress:
-err_map:
- kfree(sa1100_rtc);
- return ret;
}
static int sa1100_rtc_remove(struct platform_device *pdev)
{
- struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
- rtc_device_unregister(sa1100_rtc->rtc);
- clk_disable(sa1100_rtc->clk);
- clk_unprepare(sa1100_rtc->clk);
- iounmap(sa1100_rtc->base);
+ if (rtc)
+ rtc_device_unregister(rtc);
+
return 0;
}
#ifdef CONFIG_PM
static int sa1100_rtc_suspend(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
if (device_may_wakeup(dev))
- enable_irq_wake(sa1100_rtc->irq_Alrm);
+ enable_irq_wake(IRQ_RTCAlrm);
return 0;
}
static int sa1100_rtc_resume(struct device *dev)
{
- struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
-
if (device_may_wakeup(dev))
- disable_irq_wake(sa1100_rtc->irq_Alrm);
+ disable_irq_wake(IRQ_RTCAlrm);
return 0;
}
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index eef27a1..110137e 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -3261,6 +3261,12 @@
device->path_data.tbvpm |= eventlpm;
dasd_schedule_device_bh(device);
}
+ if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+ DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+ "Pathgroup re-established\n");
+ if (device->discipline->kick_validate)
+ device->discipline->kick_validate(device);
+ }
}
dasd_put_device(device);
}
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 553b3c5..b3beed5 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -189,14 +189,12 @@
unsigned long flags;
struct alias_server *server, *newserver;
struct alias_lcu *lcu, *newlcu;
- int is_lcu_known;
struct dasd_uid uid;
private = (struct dasd_eckd_private *) device->private;
device->discipline->get_uid(device, &uid);
spin_lock_irqsave(&aliastree.lock, flags);
- is_lcu_known = 1;
server = _find_server(&uid);
if (!server) {
spin_unlock_irqrestore(&aliastree.lock, flags);
@@ -208,7 +206,6 @@
if (!server) {
list_add(&newserver->server, &aliastree.serverlist);
server = newserver;
- is_lcu_known = 0;
} else {
/* someone was faster */
_free_server(newserver);
@@ -226,12 +223,10 @@
if (!lcu) {
list_add(&newlcu->lcu, &server->lculist);
lcu = newlcu;
- is_lcu_known = 0;
} else {
/* someone was faster */
_free_lcu(newlcu);
}
- is_lcu_known = 0;
}
spin_lock(&lcu->lock);
list_add(&device->alias_list, &lcu->inactive_devices);
@@ -239,64 +234,7 @@
spin_unlock(&lcu->lock);
spin_unlock_irqrestore(&aliastree.lock, flags);
- return is_lcu_known;
-}
-
-/*
- * The first device to be registered on an LCU will have to do
- * some additional setup steps to configure that LCU on the
- * storage server. All further devices should wait with their
- * initialization until the first device is done.
- * To synchronize this work, the first device will call
- * dasd_alias_lcu_setup_complete when it is done, and all
- * other devices will wait for it with dasd_alias_wait_for_lcu_setup.
- */
-void dasd_alias_lcu_setup_complete(struct dasd_device *device)
-{
- unsigned long flags;
- struct alias_server *server;
- struct alias_lcu *lcu;
- struct dasd_uid uid;
-
- device->discipline->get_uid(device, &uid);
- lcu = NULL;
- spin_lock_irqsave(&aliastree.lock, flags);
- server = _find_server(&uid);
- if (server)
- lcu = _find_lcu(server, &uid);
- spin_unlock_irqrestore(&aliastree.lock, flags);
- if (!lcu) {
- DBF_EVENT_DEVID(DBF_ERR, device->cdev,
- "could not find lcu for %04x %02x",
- uid.ssid, uid.real_unit_addr);
- WARN_ON(1);
- return;
- }
- complete_all(&lcu->lcu_setup);
-}
-
-void dasd_alias_wait_for_lcu_setup(struct dasd_device *device)
-{
- unsigned long flags;
- struct alias_server *server;
- struct alias_lcu *lcu;
- struct dasd_uid uid;
-
- device->discipline->get_uid(device, &uid);
- lcu = NULL;
- spin_lock_irqsave(&aliastree.lock, flags);
- server = _find_server(&uid);
- if (server)
- lcu = _find_lcu(server, &uid);
- spin_unlock_irqrestore(&aliastree.lock, flags);
- if (!lcu) {
- DBF_EVENT_DEVID(DBF_ERR, device->cdev,
- "could not find lcu for %04x %02x",
- uid.ssid, uid.real_unit_addr);
- WARN_ON(1);
- return;
- }
- wait_for_completion(&lcu->lcu_setup);
+ return 0;
}
/*
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index bbcd5e9..70880be 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1534,6 +1534,10 @@
struct dasd_eckd_private *private;
int enable_pav;
+ private = (struct dasd_eckd_private *) device->private;
+ if (private->uid.type == UA_BASE_PAV_ALIAS ||
+ private->uid.type == UA_HYPER_PAV_ALIAS)
+ return;
if (dasd_nopav || MACHINE_IS_VM)
enable_pav = 0;
else
@@ -1542,11 +1546,28 @@
/* may be requested feature is not available on server,
* therefore just report error and go ahead */
- private = (struct dasd_eckd_private *) device->private;
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
"returned rc=%d", private->uid.ssid, rc);
}
+/*
+ * worker to do a validate server in case of a lost pathgroup
+ */
+static void dasd_eckd_do_validate_server(struct work_struct *work)
+{
+ struct dasd_device *device = container_of(work, struct dasd_device,
+ kick_validate);
+ dasd_eckd_validate_server(device);
+ dasd_put_device(device);
+}
+
+static void dasd_eckd_kick_validate_server(struct dasd_device *device)
+{
+ dasd_get_device(device);
+ /* queue call to do_validate_server to the kernel event daemon. */
+ schedule_work(&device->kick_validate);
+}
+
static u32 get_fcx_max_data(struct dasd_device *device)
{
#if defined(CONFIG_64BIT)
@@ -1588,10 +1609,13 @@
struct dasd_eckd_private *private;
struct dasd_block *block;
struct dasd_uid temp_uid;
- int is_known, rc, i;
+ int rc, i;
int readonly;
unsigned long value;
+ /* setup work queue for validate server*/
+ INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server);
+
if (!ccw_device_is_pathgroup(device->cdev)) {
dev_warn(&device->cdev->dev,
"A channel path group could not be established\n");
@@ -1651,22 +1675,12 @@
block->base = device;
}
- /* register lcu with alias handling, enable PAV if this is a new lcu */
- is_known = dasd_alias_make_device_known_to_lcu(device);
- if (is_known < 0) {
- rc = is_known;
+ /* register lcu with alias handling, enable PAV */
+ rc = dasd_alias_make_device_known_to_lcu(device);
+ if (rc)
goto out_err2;
- }
- /*
- * dasd_eckd_validate_server is done on the first device that
- * is found for an LCU. All later other devices have to wait
- * for it, so they will read the correct feature codes.
- */
- if (!is_known) {
- dasd_eckd_validate_server(device);
- dasd_alias_lcu_setup_complete(device);
- } else
- dasd_alias_wait_for_lcu_setup(device);
+
+ dasd_eckd_validate_server(device);
/* device may report different configuration data after LCU setup */
rc = dasd_eckd_read_conf(device);
@@ -4098,7 +4112,7 @@
{
struct dasd_eckd_private *private;
struct dasd_eckd_characteristics temp_rdc_data;
- int is_known, rc;
+ int rc;
struct dasd_uid temp_uid;
unsigned long flags;
@@ -4121,14 +4135,10 @@
goto out_err;
/* register lcu with alias handling, enable PAV if this is a new lcu */
- is_known = dasd_alias_make_device_known_to_lcu(device);
- if (is_known < 0)
- return is_known;
- if (!is_known) {
- dasd_eckd_validate_server(device);
- dasd_alias_lcu_setup_complete(device);
- } else
- dasd_alias_wait_for_lcu_setup(device);
+ rc = dasd_alias_make_device_known_to_lcu(device);
+ if (rc)
+ return rc;
+ dasd_eckd_validate_server(device);
/* RE-Read Configuration Data */
rc = dasd_eckd_read_conf(device);
@@ -4270,6 +4280,7 @@
.restore = dasd_eckd_restore_device,
.reload = dasd_eckd_reload_device,
.get_uid = dasd_eckd_get_uid,
+ .kick_validate = dasd_eckd_kick_validate_server,
};
static int __init
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index afe8c33..33a6743 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -355,6 +355,7 @@
int (*reload) (struct dasd_device *);
int (*get_uid) (struct dasd_device *, struct dasd_uid *);
+ void (*kick_validate) (struct dasd_device *);
};
extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -455,6 +456,7 @@
struct work_struct kick_work;
struct work_struct restore_device;
struct work_struct reload_device;
+ struct work_struct kick_validate;
struct timer_list timer;
debug_info_t *debug_area;
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index 4ceeace..70eb1f7 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -565,8 +565,7 @@
esp_chips[dev->id] = esp;
mb();
if (esp_chips[!dev->id] == NULL) {
- err = request_irq(host->irq, mac_scsi_esp_intr, 0,
- "Mac ESP", NULL);
+ err = request_irq(host->irq, mac_scsi_esp_intr, 0, "ESP", NULL);
if (err < 0) {
esp_chips[dev->id] = NULL;
goto fail_free_priv;
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index ea2bde2..2bccfbe 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -339,9 +339,6 @@
printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
- /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
- disable_irq(IRQ_MAC_SCSI);
-
/* get in phase */
NCR5380_write( TARGET_COMMAND_REG,
PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
@@ -357,9 +354,6 @@
for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
barrier();
- /* switch on SCSI IRQ again */
- enable_irq(IRQ_MAC_SCSI);
-
printk(KERN_INFO " done\n" );
}
#endif
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index 70e006b..5443e25 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -1279,3 +1279,4 @@
};
module_usb_driver(go7007_usb_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250/8250.c
similarity index 100%
rename from drivers/tty/serial/8250.c
rename to drivers/tty/serial/8250/8250.c
diff --git a/drivers/tty/serial/8250.h b/drivers/tty/serial/8250/8250.h
similarity index 100%
rename from drivers/tty/serial/8250.h
rename to drivers/tty/serial/8250/8250.h
diff --git a/drivers/tty/serial/8250_accent.c b/drivers/tty/serial/8250/8250_accent.c
similarity index 100%
rename from drivers/tty/serial/8250_accent.c
rename to drivers/tty/serial/8250/8250_accent.c
diff --git a/drivers/tty/serial/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
similarity index 100%
rename from drivers/tty/serial/8250_acorn.c
rename to drivers/tty/serial/8250/8250_acorn.c
diff --git a/drivers/tty/serial/8250_boca.c b/drivers/tty/serial/8250/8250_boca.c
similarity index 100%
rename from drivers/tty/serial/8250_boca.c
rename to drivers/tty/serial/8250/8250_boca.c
diff --git a/drivers/tty/serial/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
similarity index 100%
rename from drivers/tty/serial/8250_dw.c
rename to drivers/tty/serial/8250/8250_dw.c
diff --git a/drivers/tty/serial/8250_early.c b/drivers/tty/serial/8250/8250_early.c
similarity index 100%
rename from drivers/tty/serial/8250_early.c
rename to drivers/tty/serial/8250/8250_early.c
diff --git a/drivers/tty/serial/8250_exar_st16c554.c b/drivers/tty/serial/8250/8250_exar_st16c554.c
similarity index 100%
rename from drivers/tty/serial/8250_exar_st16c554.c
rename to drivers/tty/serial/8250/8250_exar_st16c554.c
diff --git a/drivers/tty/serial/8250_fourport.c b/drivers/tty/serial/8250/8250_fourport.c
similarity index 100%
rename from drivers/tty/serial/8250_fourport.c
rename to drivers/tty/serial/8250/8250_fourport.c
diff --git a/drivers/tty/serial/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
similarity index 100%
rename from drivers/tty/serial/8250_fsl.c
rename to drivers/tty/serial/8250/8250_fsl.c
diff --git a/drivers/tty/serial/8250_gsc.c b/drivers/tty/serial/8250/8250_gsc.c
similarity index 100%
rename from drivers/tty/serial/8250_gsc.c
rename to drivers/tty/serial/8250/8250_gsc.c
diff --git a/drivers/tty/serial/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
similarity index 100%
rename from drivers/tty/serial/8250_hp300.c
rename to drivers/tty/serial/8250/8250_hp300.c
diff --git a/drivers/tty/serial/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
similarity index 100%
rename from drivers/tty/serial/8250_hub6.c
rename to drivers/tty/serial/8250/8250_hub6.c
diff --git a/drivers/tty/serial/8250_mca.c b/drivers/tty/serial/8250/8250_mca.c
similarity index 100%
rename from drivers/tty/serial/8250_mca.c
rename to drivers/tty/serial/8250/8250_mca.c
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
similarity index 100%
rename from drivers/tty/serial/8250_pci.c
rename to drivers/tty/serial/8250/8250_pci.c
diff --git a/drivers/tty/serial/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
similarity index 100%
rename from drivers/tty/serial/8250_pnp.c
rename to drivers/tty/serial/8250/8250_pnp.c
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
new file mode 100644
index 0000000..591f801
--- /dev/null
+++ b/drivers/tty/serial/8250/Kconfig
@@ -0,0 +1,280 @@
+#
+# The 8250/16550 serial drivers. You shouldn't be in this list unless
+# you somehow have an implicit or explicit dependency on SERIAL_8250.
+#
+
+config SERIAL_8250
+ tristate "8250/16550 and compatible serial support"
+ select SERIAL_CORE
+ ---help---
+ This selects whether you want to include the driver for the standard
+ serial ports. The standard answer is Y. People who might say N
+ here are those that are setting up dedicated Ethernet WWW/FTP
+ servers, or users that have one of the various bus mice instead of a
+ serial mouse and don't intend to use their machine's standard serial
+ port for anything. (Note that the Cyclades and Stallion multi
+ serial port drivers do not need this driver built in for them to
+ work.)
+
+ To compile this driver as a module, choose M here: the
+ module will be called 8250.
+ [WARNING: Do not compile this driver as a module if you are using
+ non-standard serial ports, since the configuration information will
+ be lost when the driver is unloaded. This limitation may be lifted
+ in the future.]
+
+ BTW1: If you have a mouseman serial mouse which is not recognized by
+ the X window system, try running gpm first.
+
+ BTW2: If you intend to use a software modem (also called Winmodem)
+ under Linux, forget it. These modems are crippled and require
+ proprietary drivers which are only available under Windows.
+
+ Most people will say Y or M here, so that they can use serial mice,
+ modems and similar devices connecting to the standard serial ports.
+
+config SERIAL_8250_CONSOLE
+ bool "Console on 8250/16550 and compatible serial port"
+ depends on SERIAL_8250=y
+ select SERIAL_CORE_CONSOLE
+ ---help---
+ If you say Y here, it will be possible to use a serial port as the
+ system console (the system console is the device which receives all
+ kernel messages and warnings and which allows logins in single user
+ mode). This could be useful if some terminal or printer is connected
+ to that serial port.
+
+ Even if you say Y here, the currently visible virtual console
+ (/dev/tty0) will still be used as the system console by default, but
+ you can alter that using a kernel command line option such as
+ "console=ttyS1". (Try "man bootparam" or see the documentation of
+ your boot loader (grub or lilo or loadlin) about how to pass options
+ to the kernel at boot time.)
+
+ If you don't have a VGA card installed and you say Y here, the
+ kernel will automatically use the first serial line, /dev/ttyS0, as
+ system console.
+
+ You can set that using a kernel command line option such as
+ "console=uart8250,io,0x3f8,9600n8"
+ "console=uart8250,mmio,0xff5e0000,115200n8".
+ and it will switch to normal serial console when the corresponding
+ port is ready.
+ "earlycon=uart8250,io,0x3f8,9600n8"
+ "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+ it will not only setup early console.
+
+ If unsure, say N.
+
+config FIX_EARLYCON_MEM
+ bool
+ depends on X86
+ default y
+
+config SERIAL_8250_GSC
+ tristate
+ depends on SERIAL_8250 && GSC
+ default SERIAL_8250
+
+config SERIAL_8250_PCI
+ tristate "8250/16550 PCI device support" if EXPERT
+ depends on SERIAL_8250 && PCI
+ default SERIAL_8250
+ help
+ This builds standard PCI serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+ Saves about 9K.
+
+config SERIAL_8250_PNP
+ tristate "8250/16550 PNP device support" if EXPERT
+ depends on SERIAL_8250 && PNP
+ default SERIAL_8250
+ help
+ This builds standard PNP serial support. You may be able to
+ disable this feature if you only need legacy serial support.
+
+config SERIAL_8250_HP300
+ tristate
+ depends on SERIAL_8250 && HP300
+ default SERIAL_8250
+
+config SERIAL_8250_CS
+ tristate "8250/16550 PCMCIA device support"
+ depends on PCMCIA && SERIAL_8250
+ ---help---
+ Say Y here to enable support for 16-bit PCMCIA serial devices,
+ including serial port cards, modems, and the modem functions of
+ multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
+ credit-card size devices often used with laptops.)
+
+ To compile this driver as a module, choose M here: the
+ module will be called serial_cs.
+
+ If unsure, say N.
+
+config SERIAL_8250_NR_UARTS
+ int "Maximum number of 8250/16550 serial ports"
+ depends on SERIAL_8250
+ default "4"
+ help
+ Set this to the number of serial ports you want the driver
+ to support. This includes any ports discovered via ACPI or
+ PCI enumeration and any ports that may be added at run-time
+ via hot-plug, or any ISA multi-port serial cards.
+
+config SERIAL_8250_RUNTIME_UARTS
+ int "Number of 8250/16550 serial ports to register at runtime"
+ depends on SERIAL_8250
+ range 0 SERIAL_8250_NR_UARTS
+ default "4"
+ help
+ Set this to the maximum number of serial ports you want
+ the kernel to register at boot time. This can be overridden
+ with the module parameter "nr_uarts", or boot-time parameter
+ 8250.nr_uarts
+
+config SERIAL_8250_EXTENDED
+ bool "Extended 8250/16550 serial driver options"
+ depends on SERIAL_8250
+ help
+ If you wish to use any non-standard features of the standard "dumb"
+ driver, say Y here. This includes HUB6 support, shared serial
+ interrupts, special multiport support, support for more than the
+ four COM 1/2/3/4 boards, etc.
+
+ Note that the answer to this question won't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about serial driver options. If unsure, say N.
+
+config SERIAL_8250_MANY_PORTS
+ bool "Support more than 4 legacy serial ports"
+ depends on SERIAL_8250_EXTENDED && !IA64
+ help
+ Say Y here if you have dumb serial boards other than the four
+ standard COM 1/2/3/4 ports. This may happen if you have an AST
+ FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
+ from <http://www.tldp.org/docs.html#howto>), or other custom
+ serial port hardware which acts similar to standard serial port
+ hardware. If you only use the standard COM 1/2/3/4 ports, you can
+ say N here to save some memory. You can also say Y if you have an
+ "intelligent" multiport card such as Cyclades, Digiboards, etc.
+
+#
+# Multi-port serial cards
+#
+
+config SERIAL_8250_FOURPORT
+ tristate "Support Fourport cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have an AST FourPort serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_fourport.
+
+config SERIAL_8250_ACCENT
+ tristate "Support Accent cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have an Accent Async serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_accent.
+
+config SERIAL_8250_BOCA
+ tristate "Support Boca cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have a Boca serial board. Please read the Boca
+ mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_boca.
+
+config SERIAL_8250_EXAR_ST16C554
+ tristate "Support Exar ST16C554/554D Quad UART"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
+ tinkering with your Envoy TU301, or have a machine with this UART,
+ say Y here.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_exar_st16c554.
+
+config SERIAL_8250_HUB6
+ tristate "Support Hub6 cards"
+ depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
+ help
+ Say Y here if you have a HUB6 serial board.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_hub6.
+
+#
+# Misc. options/drivers.
+#
+
+config SERIAL_8250_SHARE_IRQ
+ bool "Support for sharing serial interrupts"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Some serial boards have hardware support which allows multiple dumb
+ serial ports on the same board to share a single IRQ. To enable
+ support for this in the serial driver, say Y here.
+
+config SERIAL_8250_DETECT_IRQ
+ bool "Autodetect IRQ on standard ports (unsafe)"
+ depends on SERIAL_8250_EXTENDED
+ help
+ Say Y here if you want the kernel to try to guess which IRQ
+ to use for your serial port.
+
+ This is considered unsafe; it is far better to configure the IRQ in
+ a boot script using the setserial command.
+
+ If unsure, say N.
+
+config SERIAL_8250_RSA
+ bool "Support RSA serial ports"
+ depends on SERIAL_8250_EXTENDED
+ help
+ ::: To be written :::
+
+config SERIAL_8250_MCA
+ tristate "Support 8250-type ports on MCA buses"
+ depends on SERIAL_8250 != n && MCA
+ help
+ Say Y here if you have a MCA serial ports.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 8250_mca.
+
+config SERIAL_8250_ACORN
+ tristate "Acorn expansion card serial port support"
+ depends on ARCH_ACORN && SERIAL_8250
+ help
+ If you have an Atomwide Serial card or Serial Port card for an Acorn
+ system, say Y to this option. The driver can handle 1, 2, or 3 port
+ cards. If unsure, say N.
+
+config SERIAL_8250_RM9K
+ bool "Support for MIPS RM9xxx integrated serial port"
+ depends on SERIAL_8250 != n && SERIAL_RM9000
+ select SERIAL_8250_SHARE_IRQ
+ help
+ Selecting this option will add support for the integrated serial
+ port hardware found on MIPS RM9122 and similar processors.
+ If unsure, say N.
+
+config SERIAL_8250_FSL
+ bool
+ depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
+ default PPC
+
+config SERIAL_8250_DW
+ tristate "Support for Synopsys DesignWare 8250 quirks"
+ depends on SERIAL_8250 && OF
+ help
+ Selecting this option will enable handling of the extra features
+ present in the Synopsys DesignWare APB UART.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
new file mode 100644
index 0000000..867bba7
--- /dev/null
+++ b/drivers/tty/serial/8250/Makefile
@@ -0,0 +1,20 @@
+#
+# Makefile for the 8250 serial device drivers.
+#
+
+obj-$(CONFIG_SERIAL_8250) += 8250.o
+obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
+obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
+obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
+obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
+obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
+obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
+obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
+obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
+obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
+obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
+obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
+obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
+obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
+obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
+obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
diff --git a/drivers/tty/serial/m32r_sio.c b/drivers/tty/serial/8250/m32r_sio.c
similarity index 100%
rename from drivers/tty/serial/m32r_sio.c
rename to drivers/tty/serial/8250/m32r_sio.c
diff --git a/drivers/tty/serial/m32r_sio.h b/drivers/tty/serial/8250/m32r_sio.h
similarity index 100%
rename from drivers/tty/serial/m32r_sio.h
rename to drivers/tty/serial/8250/m32r_sio.h
diff --git a/drivers/tty/serial/m32r_sio_reg.h b/drivers/tty/serial/8250/m32r_sio_reg.h
similarity index 100%
rename from drivers/tty/serial/m32r_sio_reg.h
rename to drivers/tty/serial/8250/m32r_sio_reg.h
diff --git a/drivers/tty/serial/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c
similarity index 100%
rename from drivers/tty/serial/serial_cs.c
rename to drivers/tty/serial/8250/serial_cs.c
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index aca2386..2de9924 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -5,279 +5,7 @@
menu "Serial drivers"
depends on HAS_IOMEM
-#
-# The new 8250/16550 serial drivers
-config SERIAL_8250
- tristate "8250/16550 and compatible serial support"
- select SERIAL_CORE
- ---help---
- This selects whether you want to include the driver for the standard
- serial ports. The standard answer is Y. People who might say N
- here are those that are setting up dedicated Ethernet WWW/FTP
- servers, or users that have one of the various bus mice instead of a
- serial mouse and don't intend to use their machine's standard serial
- port for anything. (Note that the Cyclades and Stallion multi
- serial port drivers do not need this driver built in for them to
- work.)
-
- To compile this driver as a module, choose M here: the
- module will be called 8250.
- [WARNING: Do not compile this driver as a module if you are using
- non-standard serial ports, since the configuration information will
- be lost when the driver is unloaded. This limitation may be lifted
- in the future.]
-
- BTW1: If you have a mouseman serial mouse which is not recognized by
- the X window system, try running gpm first.
-
- BTW2: If you intend to use a software modem (also called Winmodem)
- under Linux, forget it. These modems are crippled and require
- proprietary drivers which are only available under Windows.
-
- Most people will say Y or M here, so that they can use serial mice,
- modems and similar devices connecting to the standard serial ports.
-
-config SERIAL_8250_CONSOLE
- bool "Console on 8250/16550 and compatible serial port"
- depends on SERIAL_8250=y
- select SERIAL_CORE_CONSOLE
- ---help---
- If you say Y here, it will be possible to use a serial port as the
- system console (the system console is the device which receives all
- kernel messages and warnings and which allows logins in single user
- mode). This could be useful if some terminal or printer is connected
- to that serial port.
-
- Even if you say Y here, the currently visible virtual console
- (/dev/tty0) will still be used as the system console by default, but
- you can alter that using a kernel command line option such as
- "console=ttyS1". (Try "man bootparam" or see the documentation of
- your boot loader (grub or lilo or loadlin) about how to pass options
- to the kernel at boot time.)
-
- If you don't have a VGA card installed and you say Y here, the
- kernel will automatically use the first serial line, /dev/ttyS0, as
- system console.
-
- You can set that using a kernel command line option such as
- "console=uart8250,io,0x3f8,9600n8"
- "console=uart8250,mmio,0xff5e0000,115200n8".
- and it will switch to normal serial console when the corresponding
- port is ready.
- "earlycon=uart8250,io,0x3f8,9600n8"
- "earlycon=uart8250,mmio,0xff5e0000,115200n8".
- it will not only setup early console.
-
- If unsure, say N.
-
-config FIX_EARLYCON_MEM
- bool
- depends on X86
- default y
-
-config SERIAL_8250_GSC
- tristate
- depends on SERIAL_8250 && GSC
- default SERIAL_8250
-
-config SERIAL_8250_PCI
- tristate "8250/16550 PCI device support" if EXPERT
- depends on SERIAL_8250 && PCI
- default SERIAL_8250
- help
- This builds standard PCI serial support. You may be able to
- disable this feature if you only need legacy serial support.
- Saves about 9K.
-
-config SERIAL_8250_PNP
- tristate "8250/16550 PNP device support" if EXPERT
- depends on SERIAL_8250 && PNP
- default SERIAL_8250
- help
- This builds standard PNP serial support. You may be able to
- disable this feature if you only need legacy serial support.
-
-config SERIAL_8250_FSL
- bool
- depends on SERIAL_8250_CONSOLE && PPC_UDBG_16550
- default PPC
-
-config SERIAL_8250_HP300
- tristate
- depends on SERIAL_8250 && HP300
- default SERIAL_8250
-
-config SERIAL_8250_CS
- tristate "8250/16550 PCMCIA device support"
- depends on PCMCIA && SERIAL_8250
- ---help---
- Say Y here to enable support for 16-bit PCMCIA serial devices,
- including serial port cards, modems, and the modem functions of
- multi-function Ethernet/modem cards. (PCMCIA- or PC-cards are
- credit-card size devices often used with laptops.)
-
- To compile this driver as a module, choose M here: the
- module will be called serial_cs.
-
- If unsure, say N.
-
-config SERIAL_8250_NR_UARTS
- int "Maximum number of 8250/16550 serial ports"
- depends on SERIAL_8250
- default "4"
- help
- Set this to the number of serial ports you want the driver
- to support. This includes any ports discovered via ACPI or
- PCI enumeration and any ports that may be added at run-time
- via hot-plug, or any ISA multi-port serial cards.
-
-config SERIAL_8250_RUNTIME_UARTS
- int "Number of 8250/16550 serial ports to register at runtime"
- depends on SERIAL_8250
- range 0 SERIAL_8250_NR_UARTS
- default "4"
- help
- Set this to the maximum number of serial ports you want
- the kernel to register at boot time. This can be overridden
- with the module parameter "nr_uarts", or boot-time parameter
- 8250.nr_uarts
-
-config SERIAL_8250_EXTENDED
- bool "Extended 8250/16550 serial driver options"
- depends on SERIAL_8250
- help
- If you wish to use any non-standard features of the standard "dumb"
- driver, say Y here. This includes HUB6 support, shared serial
- interrupts, special multiport support, support for more than the
- four COM 1/2/3/4 boards, etc.
-
- Note that the answer to this question won't directly affect the
- kernel: saying N will just cause the configurator to skip all
- the questions about serial driver options. If unsure, say N.
-
-config SERIAL_8250_MANY_PORTS
- bool "Support more than 4 legacy serial ports"
- depends on SERIAL_8250_EXTENDED && !IA64
- help
- Say Y here if you have dumb serial boards other than the four
- standard COM 1/2/3/4 ports. This may happen if you have an AST
- FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
- from <http://www.tldp.org/docs.html#howto>), or other custom
- serial port hardware which acts similar to standard serial port
- hardware. If you only use the standard COM 1/2/3/4 ports, you can
- say N here to save some memory. You can also say Y if you have an
- "intelligent" multiport card such as Cyclades, Digiboards, etc.
-
-#
-# Multi-port serial cards
-#
-
-config SERIAL_8250_FOURPORT
- tristate "Support Fourport cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an AST FourPort serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_fourport.
-
-config SERIAL_8250_ACCENT
- tristate "Support Accent cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have an Accent Async serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_accent.
-
-config SERIAL_8250_BOCA
- tristate "Support Boca cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a Boca serial board. Please read the Boca
- mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_boca.
-
-config SERIAL_8250_EXAR_ST16C554
- tristate "Support Exar ST16C554/554D Quad UART"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- The Uplogix Envoy TU301 uses this Exar Quad UART. If you are
- tinkering with your Envoy TU301, or have a machine with this UART,
- say Y here.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_exar_st16c554.
-
-config SERIAL_8250_HUB6
- tristate "Support Hub6 cards"
- depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
- help
- Say Y here if you have a HUB6 serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_hub6.
-
-config SERIAL_8250_SHARE_IRQ
- bool "Support for sharing serial interrupts"
- depends on SERIAL_8250_EXTENDED
- help
- Some serial boards have hardware support which allows multiple dumb
- serial ports on the same board to share a single IRQ. To enable
- support for this in the serial driver, say Y here.
-
-config SERIAL_8250_DETECT_IRQ
- bool "Autodetect IRQ on standard ports (unsafe)"
- depends on SERIAL_8250_EXTENDED
- help
- Say Y here if you want the kernel to try to guess which IRQ
- to use for your serial port.
-
- This is considered unsafe; it is far better to configure the IRQ in
- a boot script using the setserial command.
-
- If unsure, say N.
-
-config SERIAL_8250_RSA
- bool "Support RSA serial ports"
- depends on SERIAL_8250_EXTENDED
- help
- ::: To be written :::
-
-config SERIAL_8250_MCA
- tristate "Support 8250-type ports on MCA buses"
- depends on SERIAL_8250 != n && MCA
- help
- Say Y here if you have a MCA serial ports.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_mca.
-
-config SERIAL_8250_ACORN
- tristate "Acorn expansion card serial port support"
- depends on ARCH_ACORN && SERIAL_8250
- help
- If you have an Atomwide Serial card or Serial Port card for an Acorn
- system, say Y to this option. The driver can handle 1, 2, or 3 port
- cards. If unsure, say N.
-
-config SERIAL_8250_RM9K
- bool "Support for MIPS RM9xxx integrated serial port"
- depends on SERIAL_8250 != n && SERIAL_RM9000
- select SERIAL_8250_SHARE_IRQ
- help
- Selecting this option will add support for the integrated serial
- port hardware found on MIPS RM9122 and similar processors.
- If unsure, say N.
-
-config SERIAL_8250_DW
- tristate "Support for Synopsys DesignWare 8250 quirks"
- depends on SERIAL_8250 && OF
- help
- Selecting this option will enable handling of the extra features
- present in the Synopsys DesignWare APB UART.
+source "drivers/tty/serial/8250/Kconfig"
comment "Non-8250 serial port support"
@@ -536,15 +264,6 @@
help
MAX3107 chip support
-config SERIAL_MAX3107_AAVA
- tristate "MAX3107 AAVA platform support"
- depends on X86_MRST && SERIAL_MAX3107 && GPIOLIB
- select SERIAL_CORE
- help
- Support for the MAX3107 chip configuration found on the AAVA
- platform. Includes the extra initialisation and GPIO support
- neded for this device.
-
config SERIAL_DZ
bool "DECstation DZ serial driver"
depends on MACH_DECSTATION && 32BIT
diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile
index f5b01f2..fef32e1 100644
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -14,22 +14,9 @@
obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
-obj-$(CONFIG_SERIAL_8250) += 8250.o
-obj-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
-obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
-obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
-obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o
-obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += 8250_early.o
-obj-$(CONFIG_SERIAL_8250_FOURPORT) += 8250_fourport.o
-obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o
-obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o
-obj-$(CONFIG_SERIAL_8250_EXAR_ST16C554) += 8250_exar_st16c554.o
-obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
-obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o
-obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o
-obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o
+# Now bring in any enabled 8250/16450/16550 type drivers.
+obj-$(CONFIG_SERIAL_8250) += 8250/
+
obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
@@ -42,7 +29,6 @@
obj-$(CONFIG_SERIAL_SAMSUNG) += samsung.o
obj-$(CONFIG_SERIAL_MAX3100) += max3100.o
obj-$(CONFIG_SERIAL_MAX3107) += max3107.o
-obj-$(CONFIG_SERIAL_MAX3107_AAVA) += max3107-aava.o
obj-$(CONFIG_SERIAL_IP22_ZILOG) += ip22zilog.o
obj-$(CONFIG_SERIAL_MUX) += mux.o
obj-$(CONFIG_SERIAL_68328) += 68328serial.o
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 9ae0240..6800f5f 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -159,6 +159,7 @@
unsigned int fifosize; /* vendor-specific */
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
+ unsigned int old_cr; /* state during shutdown */
bool autorts;
char type[12];
bool interrupt_may_hang; /* vendor-specific */
@@ -1411,7 +1412,9 @@
while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
barrier();
- cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
+ /* restore RTS and DTR */
+ cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
+ cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
/* Clear pending error interrupts */
@@ -1469,6 +1472,7 @@
static void pl011_shutdown(struct uart_port *port)
{
struct uart_amba_port *uap = (struct uart_amba_port *)port;
+ unsigned int cr;
/*
* disable all interrupts
@@ -1488,9 +1492,16 @@
/*
* disable the port
+ * disable the port. It should not disable RTS and DTR.
+ * Also RTS and DTR state should be preserved to restore
+ * it during startup().
*/
uap->autorts = false;
- writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
+ cr = readw(uap->port.membase + UART011_CR);
+ uap->old_cr = cr;
+ cr &= UART011_CR_RTS | UART011_CR_DTR;
+ cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
+ writew(cr, uap->port.membase + UART011_CR);
/*
* disable break condition and fifos
@@ -1740,9 +1751,19 @@
{
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int status, old_cr, new_cr;
+ unsigned long flags;
+ int locked = 1;
clk_enable(uap->clk);
+ local_irq_save(flags);
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&uap->port.lock);
+ else
+ spin_lock(&uap->port.lock);
+
/*
* First save the CR then disable the interrupts
*/
@@ -1762,6 +1783,10 @@
} while (status & UART01x_FR_BUSY);
writew(old_cr, uap->port.membase + UART011_CR);
+ if (locked)
+ spin_unlock(&uap->port.lock);
+ local_irq_restore(flags);
+
clk_disable(uap->clk);
}
@@ -1905,6 +1930,7 @@
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
+ uap->old_cr = 0;
uap->fifosize = vendor->fifosize;
uap->interrupt_may_hang = vendor->interrupt_may_hang;
uap->port.dev = &dev->dev;
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 7c867a0..7545fe1 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -251,6 +251,7 @@
struct jsm_board *brd = pci_get_drvdata(pdev);
pci_restore_state(pdev);
+ pci_save_state(pdev);
jsm_uart_port_init(brd);
}
diff --git a/drivers/tty/serial/max3107-aava.c b/drivers/tty/serial/max3107-aava.c
deleted file mode 100644
index aae772a..0000000
--- a/drivers/tty/serial/max3107-aava.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * max3107.c - spi uart protocol driver for Maxim 3107
- * Based on max3100.c
- * by Christian Pellegrin <chripell@evolware.org>
- * and max3110.c
- * by Feng Tang <feng.tang@intel.com>
- *
- * Copyright (C) Aavamobile 2009
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/serial_core.h>
-#include <linux/serial.h>
-#include <linux/spi/spi.h>
-#include <linux/freezer.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/sfi.h>
-#include <linux/module.h>
-#include <asm/mrst.h>
-#include "max3107.h"
-
-/* GPIO direction to input function */
-static int max3107_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration register */
- buf[0] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO read failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to input */
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO write failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO direction to output function */
-static int max3107_gpio_direction_out(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO configuration and data registers */
- buf[0] = MAX3107_GPIOCFG_REG;
- buf[1] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev, "SPI transfer gpio failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Set GPIO to output */
- buf[0] |= (0x0001 << offset);
- /* Set value */
- if (value)
- buf[1] |= (0x0001 << offset);
- else
- buf[1] &= ~(0x0001 << offset);
-
- /* Write new GPIO configuration and data register values */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIOCFG_REG);
- buf[1] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO conf data w failed\n");
- return -EIO;
- }
- return 0;
-}
-
-/* GPIO value query function */
-static int max3107_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[1]; /* Buffer for SPI transfer */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return -EINVAL;
- }
-
- /* Read current GPIO data register */
- buf[0] = MAX3107_GPIODATA_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 2)) {
- dev_err(&s->spi->dev, "SPI transfer GPIO data r failed\n");
- return -EIO;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
-
- /* Return value */
- return buf[0] & (0x0001 << offset);
-}
-
-/* GPIO value set function */
-static void max3107_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct max3107_port *s = container_of(chip, struct max3107_port, chip);
- u16 buf[2]; /* Buffer for SPI transfers */
-
- if (offset >= MAX3107_GPIO_COUNT) {
- dev_err(&s->spi->dev, "Invalid GPIO\n");
- return;
- }
-
- /* Read current GPIO configuration registers*/
- buf[0] = MAX3107_GPIODATA_REG;
- buf[1] = MAX3107_GPIOCFG_REG;
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, (u8 *)buf, 4)) {
- dev_err(&s->spi->dev,
- "SPI transfer for GPIO data and config read failed\n");
- return;
- }
- buf[0] &= MAX3107_SPI_RX_DATA_MASK;
- buf[1] &= MAX3107_SPI_RX_DATA_MASK;
-
- if (!(buf[1] & (0x0001 << offset))) {
- /* Configured as input, can't set value */
- dev_warn(&s->spi->dev,
- "Trying to set value for input GPIO\n");
- return;
- }
-
- /* Set value */
- if (value)
- buf[0] |= (0x0001 << offset);
- else
- buf[0] &= ~(0x0001 << offset);
-
- /* Write new GPIO data register value */
- buf[0] |= (MAX3107_WRITE_BIT | MAX3107_GPIODATA_REG);
- /* Perform SPI transfer */
- if (max3107_rw(s, (u8 *)buf, NULL, 2))
- dev_err(&s->spi->dev, "SPI transfer GPIO data w failed\n");
-}
-
-/* GPIO chip data */
-static struct gpio_chip max3107_gpio_chip = {
- .owner = THIS_MODULE,
- .direction_input = max3107_gpio_direction_in,
- .direction_output = max3107_gpio_direction_out,
- .get = max3107_gpio_get,
- .set = max3107_gpio_set,
- .can_sleep = 1,
- .base = MAX3107_GPIO_BASE,
- .ngpio = MAX3107_GPIO_COUNT,
-};
-
-/**
- * max3107_aava_reset - reset on AAVA systems
- * @spi: The SPI device we are probing
- *
- * Reset the device ready for probing.
- */
-
-static int max3107_aava_reset(struct spi_device *spi)
-{
- /* Reset the chip */
- if (gpio_request(MAX3107_RESET_GPIO, "max3107")) {
- pr_err("Requesting RESET GPIO failed\n");
- return -EIO;
- }
- if (gpio_direction_output(MAX3107_RESET_GPIO, 0)) {
- pr_err("Setting RESET GPIO to 0 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- msleep(MAX3107_RESET_DELAY);
- if (gpio_direction_output(MAX3107_RESET_GPIO, 1)) {
- pr_err("Setting RESET GPIO to 1 failed\n");
- gpio_free(MAX3107_RESET_GPIO);
- return -EIO;
- }
- gpio_free(MAX3107_RESET_GPIO);
- msleep(MAX3107_WAKEUP_DELAY);
- return 0;
-}
-
-static int max3107_aava_configure(struct max3107_port *s)
-{
- int retval;
-
- /* Initialize GPIO chip data */
- s->chip = max3107_gpio_chip;
- s->chip.label = s->spi->modalias;
- s->chip.dev = &s->spi->dev;
-
- /* Add GPIO chip */
- retval = gpiochip_add(&s->chip);
- if (retval) {
- dev_err(&s->spi->dev, "Adding GPIO chip failed\n");
- return retval;
- }
-
- /* Temporary fix for EV2 boot problems, set modem reset to 0 */
- max3107_gpio_direction_out(&s->chip, 3, 0);
- return 0;
-}
-
-#if 0
-/* This will get enabled once we have the board stuff merged for this
- specific case */
-
-static const struct baud_table brg13_ext[] = {
- { 300, MAX3107_BRG13_B300 },
- { 600, MAX3107_BRG13_B600 },
- { 1200, MAX3107_BRG13_B1200 },
- { 2400, MAX3107_BRG13_B2400 },
- { 4800, MAX3107_BRG13_B4800 },
- { 9600, MAX3107_BRG13_B9600 },
- { 19200, MAX3107_BRG13_B19200 },
- { 57600, MAX3107_BRG13_B57600 },
- { 115200, MAX3107_BRG13_B115200 },
- { 230400, MAX3107_BRG13_B230400 },
- { 460800, MAX3107_BRG13_B460800 },
- { 921600, MAX3107_BRG13_B921600 },
- { 0, 0 }
-};
-
-static void max3107_aava_init(struct max3107_port *s)
-{
- /*override for AAVA SC specific*/
- if (mrst_platform_id() == MRST_PLATFORM_AAVA_SC) {
- if (get_koski_build_id() <= KOSKI_EV2)
- if (s->ext_clk) {
- s->brg_cfg = MAX3107_BRG13_B9600;
- s->baud_tbl = (struct baud_table *)brg13_ext;
- }
- }
-}
-#endif
-
-static int __devexit max3107_aava_remove(struct spi_device *spi)
-{
- struct max3107_port *s = dev_get_drvdata(&spi->dev);
-
- /* Remove GPIO chip */
- if (gpiochip_remove(&s->chip))
- dev_warn(&spi->dev, "Removing GPIO chip failed\n");
-
- /* Then do the default remove */
- return max3107_remove(spi);
-}
-
-/* Platform data */
-static struct max3107_plat aava_plat_data = {
- .loopback = 0,
- .ext_clk = 1,
-/* .init = max3107_aava_init, */
- .configure = max3107_aava_configure,
- .hw_suspend = max3107_hw_susp,
- .polled_mode = 0,
- .poll_time = 0,
-};
-
-
-static int __devinit max3107_probe_aava(struct spi_device *spi)
-{
- int err = max3107_aava_reset(spi);
- if (err < 0)
- return err;
- return max3107_probe(spi, &aava_plat_data);
-}
-
-/* Spi driver data */
-static struct spi_driver max3107_driver = {
- .driver = {
- .name = "aava-max3107",
- .owner = THIS_MODULE,
- },
- .probe = max3107_probe_aava,
- .remove = __devexit_p(max3107_aava_remove),
- .suspend = max3107_suspend,
- .resume = max3107_resume,
-};
-
-/* Driver init function */
-static int __init max3107_init(void)
-{
- return spi_register_driver(&max3107_driver);
-}
-
-/* Driver exit function */
-static void __exit max3107_exit(void)
-{
- spi_unregister_driver(&max3107_driver);
-}
-
-module_init(max3107_init);
-module_exit(max3107_exit);
-
-MODULE_DESCRIPTION("MAX3107 driver");
-MODULE_AUTHOR("Aavamobile");
-MODULE_ALIAS("spi:aava-max3107");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d192dcb..1c24269 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1160,7 +1160,7 @@
.cons = OMAP_CONSOLE,
};
-#ifdef CONFIG_SUSPEND
+#ifdef CONFIG_PM_SLEEP
static int serial_omap_suspend(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
@@ -1521,6 +1521,7 @@
}
}
+#ifdef CONFIG_PM_RUNTIME
static void serial_omap_restore_context(struct uart_omap_port *up)
{
if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
@@ -1550,7 +1551,6 @@
serial_out(up, UART_OMAP_MDR1, up->mdr1);
}
-#ifdef CONFIG_PM_RUNTIME
static int serial_omap_runtime_suspend(struct device *dev)
{
struct uart_omap_port *up = dev_get_drvdata(dev);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index c7bf31a..1305618 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2348,11 +2348,11 @@
*/
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
if (likely(!IS_ERR(tty_dev))) {
- device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
- } else
+ device_set_wakeup_capable(tty_dev, 1);
+ } else {
printk(KERN_ERR "Cannot register tty device on line %d\n",
uport->line);
+ }
/*
* Ensure UPF_DEAD is not set.
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index ef9dd62..bf6e238 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -227,7 +227,6 @@
int do_clocal = 0, retval;
unsigned long flags;
DEFINE_WAIT(wait);
- int cd;
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
@@ -284,11 +283,14 @@
retval = -ERESTARTSYS;
break;
}
- /* Probe the carrier. For devices with no carrier detect this
- will always return true */
- cd = tty_port_carrier_raised(port);
+ /*
+ * Probe the carrier. For devices with no carrier detect
+ * tty_port_carrier_raised will always return true.
+ * Never ask drivers if CLOCAL is set, this causes troubles
+ * on some hardware.
+ */
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || cd))
+ (do_clocal || tty_port_carrier_raised(port)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 5e096f4..65447c5 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1463,7 +1463,6 @@
if (!perm && op->op != KD_FONT_OP_GET)
return -EPERM;
op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
- op->flags |= KD_FONT_FLAG_OLD;
i = con_font_op(vc, op);
if (i)
return i;
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 1c50baf..d2b3cff 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -57,6 +57,8 @@
#define WDM_MAX 16
+/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
+#define WDM_DEFAULT_BUFSIZE 256
static DEFINE_MUTEX(wdm_mutex);
@@ -88,7 +90,8 @@
int count;
dma_addr_t shandle;
dma_addr_t ihandle;
- struct mutex lock;
+ struct mutex wlock;
+ struct mutex rlock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
@@ -323,7 +326,7 @@
}
/* concurrent writes and disconnect */
- r = mutex_lock_interruptible(&desc->lock);
+ r = mutex_lock_interruptible(&desc->wlock);
rv = -ERESTARTSYS;
if (r) {
kfree(buf);
@@ -386,7 +389,7 @@
out:
usb_autopm_put_interface(desc->intf);
outnp:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
outnl:
return rv < 0 ? rv : count;
}
@@ -399,7 +402,7 @@
struct wdm_device *desc = file->private_data;
- rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
+ rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
if (rv < 0)
return -ERESTARTSYS;
@@ -467,14 +470,16 @@
for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr];
+ spin_lock_irq(&desc->iuspin);
desc->length -= cntr;
+ spin_unlock_irq(&desc->iuspin);
/* in case we had outstanding data */
if (!desc->length)
clear_bit(WDM_READ, &desc->flags);
rv = cntr;
err:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->rlock);
return rv;
}
@@ -540,7 +545,8 @@
}
intf->needs_remote_wakeup = 1;
- mutex_lock(&desc->lock);
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
if (!desc->count++) {
desc->werr = 0;
desc->rerr = 0;
@@ -553,7 +559,7 @@
} else {
rv = 0;
}
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
@@ -565,9 +571,11 @@
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
- mutex_lock(&desc->lock);
+
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
desc->count--;
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -630,7 +638,7 @@
struct usb_cdc_dmm_desc *dmhd;
u8 *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen;
- u16 maxcom = 0;
+ u16 maxcom = WDM_DEFAULT_BUFSIZE;
if (!buffer)
goto out;
@@ -665,7 +673,8 @@
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
- mutex_init(&desc->lock);
+ mutex_init(&desc->rlock);
+ mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
@@ -716,7 +725,7 @@
goto err;
desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
- desc->bMaxPacketSize0,
+ desc->wMaxCommand,
GFP_KERNEL,
&desc->response->transfer_dma);
if (!desc->inbuf)
@@ -779,11 +788,13 @@
/* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
- mutex_lock(&desc->lock);
+ wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
- mutex_unlock(&desc->lock);
- wake_up_all(&desc->wait);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
if (!desc->count)
cleanup(desc);
mutex_unlock(&wdm_mutex);
@@ -798,8 +809,10 @@
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
/* if this is an autosuspend the caller does the locking */
- if (!PMSG_IS_AUTO(message))
- mutex_lock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ }
spin_lock_irq(&desc->iuspin);
if (PMSG_IS_AUTO(message) &&
@@ -815,8 +828,10 @@
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
}
- if (!PMSG_IS_AUTO(message))
- mutex_unlock(&desc->lock);
+ if (!PMSG_IS_AUTO(message)) {
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
+ }
return rv;
}
@@ -854,7 +869,8 @@
{
struct wdm_device *desc = usb_get_intfdata(intf);
- mutex_lock(&desc->lock);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
/*
@@ -876,7 +892,8 @@
int rv;
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
return 0;
}
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2f51de5..c8df1dd 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -126,7 +126,6 @@
struct dwc3_request *req)
{
struct dwc3 *dwc = dep->dwc;
- u32 type;
int ret = 0;
req->request.actual = 0;
@@ -149,20 +148,14 @@
direction = !!(dep->flags & DWC3_EP0_DIR_IN);
- if (dwc->ep0state == EP0_STATUS_PHASE) {
- type = dwc->three_stage_setup
- ? DWC3_TRBCTL_CONTROL_STATUS3
- : DWC3_TRBCTL_CONTROL_STATUS2;
- } else if (dwc->ep0state == EP0_DATA_PHASE) {
- type = DWC3_TRBCTL_CONTROL_DATA;
- } else {
- /* should never happen */
- WARN_ON(1);
+ if (dwc->ep0state != EP0_DATA_PHASE) {
+ dev_WARN(dwc->dev, "Unexpected pending request\n");
return 0;
}
ret = dwc3_ep0_start_trans(dwc, direction,
- req->request.dma, req->request.length, type);
+ req->request.dma, req->request.length,
+ DWC3_TRBCTL_CONTROL_DATA);
dep->flags &= ~(DWC3_EP_PENDING_REQUEST |
DWC3_EP0_DIR_IN);
} else if (dwc->delayed_status) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index a696bde..064b6e2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -101,7 +101,7 @@
if (req->request.num_mapped_sgs) {
req->request.dma = DMA_ADDR_INVALID;
dma_unmap_sg(dwc->dev, req->request.sg,
- req->request.num_sgs,
+ req->request.num_mapped_sgs,
req->direction ? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a95de6a..baaebf2 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -175,13 +175,12 @@
_ep->comp_desc = comp_desc;
if (g->speed == USB_SPEED_SUPER) {
switch (usb_endpoint_type(_ep->desc)) {
- case USB_ENDPOINT_XFER_BULK:
- case USB_ENDPOINT_XFER_INT:
- _ep->maxburst = comp_desc->bMaxBurst;
- break;
case USB_ENDPOINT_XFER_ISOC:
/* mult: bits 1:0 of bmAttributes */
_ep->mult = comp_desc->bmAttributes & 0x3;
+ case USB_ENDPOINT_XFER_BULK:
+ case USB_ENDPOINT_XFER_INT:
+ _ep->maxburst = comp_desc->bMaxBurst;
break;
default:
/* Do nothing for control endpoints */
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 753aa06..e0e6375 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -126,7 +126,7 @@
* descriptor and see if the EP matches it
*/
if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp) {
+ if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
num_req_streams = ep_comp->bmAttributes & 0x1f;
if (num_req_streams > ep->max_streams)
return 0;
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 6353eca..ee8ceec 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -3123,15 +3123,15 @@
struct fsg_module_parameters {
char *file[FSG_MAX_LUNS];
- int ro[FSG_MAX_LUNS];
- int removable[FSG_MAX_LUNS];
- int cdrom[FSG_MAX_LUNS];
- int nofua[FSG_MAX_LUNS];
+ bool ro[FSG_MAX_LUNS];
+ bool removable[FSG_MAX_LUNS];
+ bool cdrom[FSG_MAX_LUNS];
+ bool nofua[FSG_MAX_LUNS];
unsigned int file_count, ro_count, removable_count, cdrom_count;
unsigned int nofua_count;
unsigned int luns; /* nluns */
- int stall; /* can_stall */
+ bool stall; /* can_stall */
};
#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index d7ea6c0..b04712f 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1430,7 +1430,7 @@
int pipe = get_pipe_by_windex(wIndex);
struct fsl_ep *ep;
- if (wValue != 0 || wLength != 0 || pipe > udc->max_ep)
+ if (wValue != 0 || wLength != 0 || pipe >= udc->max_ep)
break;
ep = get_ep_by_pipe(udc, pipe);
@@ -1673,7 +1673,7 @@
if (!bit_pos)
return;
- for (i = 0; i < udc->max_ep * 2; i++) {
+ for (i = 0; i < udc->max_ep; i++) {
ep_num = i >> 1;
direction = i % 2;
diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c
index fa0fcc1..e2293c1 100644
--- a/drivers/usb/gadget/langwell_udc.c
+++ b/drivers/usb/gadget/langwell_udc.c
@@ -11,11 +11,6 @@
/* #undef DEBUG */
/* #undef VERBOSE_DEBUG */
-#if defined(CONFIG_USB_LANGWELL_OTG)
-#define OTG_TRANSCEIVER
-#endif
-
-
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
@@ -1522,8 +1517,7 @@
/* stop all USB activities */
-static void stop_activity(struct langwell_udc *dev,
- struct usb_gadget_driver *driver)
+static void stop_activity(struct langwell_udc *dev)
{
struct langwell_ep *ep;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
@@ -1535,9 +1529,9 @@
}
/* report disconnect; the driver is already quiesced */
- if (driver) {
+ if (dev->driver) {
spin_unlock(&dev->lock);
- driver->disconnect(&dev->gadget);
+ dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
}
@@ -1925,11 +1919,10 @@
/* stop all usb activities */
dev->gadget.speed = USB_SPEED_UNKNOWN;
- stop_activity(dev, driver);
- spin_unlock_irqrestore(&dev->lock, flags);
-
dev->gadget.dev.driver = NULL;
dev->driver = NULL;
+ stop_activity(dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
device_remove_file(&dev->pdev->dev, &dev_attr_function);
@@ -2315,13 +2308,9 @@
if (!gadget_is_otg(&dev->gadget))
break;
- else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE) {
+ else if (setup->bRequest == USB_DEVICE_B_HNP_ENABLE)
dev->gadget.b_hnp_enable = 1;
-#ifdef OTG_TRANSCEIVER
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 1;
-#endif
- } else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
+ else if (setup->bRequest == USB_DEVICE_A_HNP_SUPPORT)
dev->gadget.a_hnp_support = 1;
else if (setup->bRequest ==
USB_DEVICE_A_ALT_HNP_SUPPORT)
@@ -2733,7 +2722,7 @@
dev->bus_reset = 1;
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
dev->usb_state = USB_STATE_DEFAULT;
} else {
dev_vdbg(&dev->pdev->dev, "device controller reset\n");
@@ -2741,7 +2730,7 @@
langwell_udc_reset(dev);
/* reset all the queues, stop all USB activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
@@ -2752,12 +2741,6 @@
dev->usb_state = USB_STATE_ATTACHED;
}
-#ifdef OTG_TRANSCEIVER
- /* refer to USB OTG 6.6.2.3 b_hnp_en is cleared */
- if (!dev->lotg->otg.default_a)
- dev->lotg->hsm.b_hnp_enable = 0;
-#endif
-
dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
}
@@ -2770,29 +2753,6 @@
dev->resume_state = dev->usb_state;
dev->usb_state = USB_STATE_SUSPENDED;
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a) {
- if (dev->lotg->hsm.b_bus_suspend_vld == 1) {
- dev->lotg->hsm.b_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- dev->lotg->hsm.b_bus_suspend_vld++;
- } else {
- if (!dev->lotg->hsm.a_bus_suspend) {
- dev->lotg->hsm.a_bus_suspend = 1;
- /* notify transceiver the state changes */
- if (spin_trylock(&dev->lotg->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&dev->lotg->wq_lock);
- }
- }
- }
-#endif
-
/* report suspend to the driver */
if (dev->driver) {
if (dev->driver->suspend) {
@@ -2823,11 +2783,6 @@
if (dev->pdev->device != 0x0829)
langwell_phy_low_power(dev, 0);
-#ifdef OTG_TRANSCEIVER
- if (dev->lotg->otg.default_a == 0)
- dev->lotg->hsm.a_bus_suspend = 0;
-#endif
-
/* report resume to the driver */
if (dev->driver) {
if (dev->driver->resume) {
@@ -3020,7 +2975,6 @@
dev->done = &done;
-#ifndef OTG_TRANSCEIVER
/* free dTD dma_pool and dQH */
if (dev->dtd_pool)
dma_pool_destroy(dev->dtd_pool);
@@ -3032,7 +2986,6 @@
/* release SRAM caching */
if (dev->has_sram && dev->got_sram)
sram_deinit(dev);
-#endif
if (dev->status_req) {
kfree(dev->status_req->req.buf);
@@ -3045,7 +2998,6 @@
if (dev->got_irq)
free_irq(pdev->irq, dev);
-#ifndef OTG_TRANSCEIVER
if (dev->cap_regs)
iounmap(dev->cap_regs);
@@ -3055,13 +3007,6 @@
if (dev->enabled)
pci_disable_device(pdev);
-#else
- if (dev->transceiver) {
- otg_put_transceiver(dev->transceiver);
- dev->transceiver = NULL;
- dev->lotg = NULL;
- }
-#endif
dev->cap_regs = NULL;
@@ -3072,9 +3017,7 @@
device_remove_file(&pdev->dev, &dev_attr_langwell_udc);
device_remove_file(&pdev->dev, &dev_attr_remote_wakeup);
-#ifndef OTG_TRANSCEIVER
pci_set_drvdata(pdev, NULL);
-#endif
/* free dev, wait for the release() finished */
wait_for_completion(&done);
@@ -3089,9 +3032,7 @@
const struct pci_device_id *id)
{
struct langwell_udc *dev;
-#ifndef OTG_TRANSCEIVER
unsigned long resource, len;
-#endif
void __iomem *base = NULL;
size_t size;
int retval;
@@ -3109,16 +3050,6 @@
dev->pdev = pdev;
dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
-#ifdef OTG_TRANSCEIVER
- /* PCI device is already enabled by otg_transceiver driver */
- dev->enabled = 1;
-
- /* mem region and register base */
- dev->region = 1;
- dev->transceiver = otg_get_transceiver();
- dev->lotg = otg_to_langwell(dev->transceiver);
- base = dev->lotg->regs;
-#else
pci_set_drvdata(pdev, dev);
/* now all the pci goodies ... */
@@ -3139,7 +3070,6 @@
dev->region = 1;
base = ioremap_nocache(resource, len);
-#endif
if (base == NULL) {
dev_err(&dev->pdev->dev, "can't map memory\n");
retval = -EFAULT;
@@ -3163,7 +3093,6 @@
dev->got_sram = 0;
dev_vdbg(&dev->pdev->dev, "dev->has_sram: %d\n", dev->has_sram);
-#ifndef OTG_TRANSCEIVER
/* enable SRAM caching if detected */
if (dev->has_sram && !dev->got_sram)
sram_init(dev);
@@ -3182,7 +3111,6 @@
goto error;
}
dev->got_irq = 1;
-#endif
/* set stopped bit */
dev->stopped = 1;
@@ -3257,10 +3185,8 @@
dev->remote_wakeup = 0;
dev->dev_status = 1 << USB_DEVICE_SELF_POWERED;
-#ifndef OTG_TRANSCEIVER
/* reset device controller */
langwell_udc_reset(dev);
-#endif
/* initialize gadget structure */
dev->gadget.ops = &langwell_ops; /* usb_gadget_ops */
@@ -3268,9 +3194,6 @@
INIT_LIST_HEAD(&dev->gadget.ep_list); /* ep_list */
dev->gadget.speed = USB_SPEED_UNKNOWN; /* speed */
dev->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
-#ifdef OTG_TRANSCEIVER
- dev->gadget.is_otg = 1; /* support otg mode */
-#endif
/* the "gadget" abstracts/virtualizes the controller */
dev_set_name(&dev->gadget.dev, "gadget");
@@ -3282,10 +3205,8 @@
/* controller endpoints reinit */
eps_reinit(dev);
-#ifndef OTG_TRANSCEIVER
/* reset ep0 dQH and endptctrl */
ep0_reset(dev);
-#endif
/* create dTD dma_pool resource */
dev->dtd_pool = dma_pool_create("langwell_dtd",
@@ -3367,7 +3288,7 @@
spin_lock_irq(&dev->lock);
/* stop all usb activities */
- stop_activity(dev, dev->driver);
+ stop_activity(dev);
spin_unlock_irq(&dev->lock);
/* free dTD dma_pool and dQH */
@@ -3525,22 +3446,14 @@
static int __init init(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_register_peripheral(&langwell_pci_driver);
-#else
return pci_register_driver(&langwell_pci_driver);
-#endif
}
module_init(init);
static void __exit cleanup(void)
{
-#ifdef OTG_TRANSCEIVER
- return langwell_unregister_peripheral(&langwell_pci_driver);
-#else
pci_unregister_driver(&langwell_pci_driver);
-#endif
}
module_exit(cleanup);
diff --git a/drivers/usb/gadget/langwell_udc.h b/drivers/usb/gadget/langwell_udc.h
index ef79e24..d6e78ac 100644
--- a/drivers/usb/gadget/langwell_udc.h
+++ b/drivers/usb/gadget/langwell_udc.h
@@ -8,7 +8,6 @@
*/
#include <linux/usb/langwell_udc.h>
-#include <linux/usb/langwell_otg.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index c7f291a..85ea14e 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -598,16 +598,16 @@
| USB_5GBPS_OPERATION),
.bFunctionalitySupport = USB_LOW_SPEED_OPERATION,
.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT,
- .bU2DevExitLat = USB_DEFAULT_U2_DEV_EXIT_LAT,
+ .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT),
};
static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = {
.bLength = USB_DT_BOS_SIZE,
.bDescriptorType = USB_DT_BOS,
- .wTotalLength = USB_DT_BOS_SIZE
+ .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE
+ USB_DT_USB_EXT_CAP_SIZE
- + USB_DT_USB_SS_CAP_SIZE,
+ + USB_DT_USB_SS_CAP_SIZE),
.bNumDeviceCaps = 2,
};
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index e90344a..b556a72 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -125,7 +125,7 @@
*/
if (pdata->init && pdata->init(pdev)) {
retval = -ENODEV;
- goto err3;
+ goto err4;
}
/* Enable USB controller, 83xx or 8536 */
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index f4b627d..01bb7241d 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -276,6 +276,9 @@
/* Serial Bus Release Number is at PCI 0x60 offset */
pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
+ if (pdev->vendor == PCI_VENDOR_ID_STMICRO
+ && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST)
+ ehci->sbrn = 0x20; /* ConneXT has no sbrn register */
/* Keep this around for a while just in case some EHCI
* implementation uses legacy PCI PM support. This test
@@ -526,6 +529,9 @@
/* handle any USB 2.0 EHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0),
.driver_data = (unsigned long) &ehci_pci_hc_driver,
+ }, {
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST),
+ .driver_data = (unsigned long) &ehci_pci_hc_driver,
},
{ /* end: all zeroes */ }
};
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 5df0b0e..77afabc 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -139,8 +139,23 @@
}
iclk = clk_get(&pdev->dev, "ohci_clk");
+ if (IS_ERR(iclk)) {
+ dev_err(&pdev->dev, "failed to get ohci_clk\n");
+ retval = PTR_ERR(iclk);
+ goto err3;
+ }
fclk = clk_get(&pdev->dev, "uhpck");
+ if (IS_ERR(fclk)) {
+ dev_err(&pdev->dev, "failed to get uhpck\n");
+ retval = PTR_ERR(fclk);
+ goto err4;
+ }
hclk = clk_get(&pdev->dev, "hclk");
+ if (IS_ERR(hclk)) {
+ dev_err(&pdev->dev, "failed to get hclk\n");
+ retval = PTR_ERR(hclk);
+ goto err5;
+ }
at91_start_hc(pdev);
ohci_hcd_init(hcd_to_ohci(hcd));
@@ -153,9 +168,12 @@
at91_stop_hc(pdev);
clk_put(hclk);
+ err5:
clk_put(fclk);
+ err4:
clk_put(iclk);
+ err3:
iounmap(hcd->regs);
err2:
@@ -226,7 +244,8 @@
if (!gpio_is_valid(pdata->vbus_pin[port]))
return;
- gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
+ gpio_set_value(pdata->vbus_pin[port],
+ !pdata->vbus_pin_active_low[port] ^ enable);
}
static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
@@ -237,7 +256,8 @@
if (!gpio_is_valid(pdata->vbus_pin[port]))
return -EINVAL;
- return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
+ return gpio_get_value(pdata->vbus_pin[port]) ^
+ !pdata->vbus_pin_active_low[port];
}
/*
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 5179fcd..e4bcb62 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -82,6 +82,14 @@
ohci_dbg(ohci,format, ## arg ); \
} while (0);
+/* Version for use where "next" is the address of a local variable */
+#define ohci_dbg_nosw(ohci, next, size, format, arg...) \
+ do { \
+ unsigned s_len; \
+ s_len = scnprintf(*next, *size, format, ## arg); \
+ *size -= s_len; *next += s_len; \
+ } while (0);
+
static void ohci_dump_intr_mask (
struct ohci_hcd *ohci,
@@ -653,7 +661,7 @@
/* dump driver info, then registers in spec order */
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"bus %s, device %s\n"
"%s\n"
"%s\n",
@@ -672,7 +680,7 @@
/* hcca */
if (ohci->hcca)
- ohci_dbg_sw (ohci, &next, &size,
+ ohci_dbg_nosw(ohci, &next, &size,
"hcca frame 0x%04x\n", ohci_frame_no(ohci));
/* other registers mostly affect frame timings */
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6109810..1843bb6 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -397,6 +397,10 @@
/* handle any USB OHCI controller */
PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0),
.driver_data = (unsigned long) &ohci_pci_hc_driver,
+ }, {
+ /* The device in the ConneXT I/O hub has no class reg */
+ PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_OHCI),
+ .driver_data = (unsigned long) &ohci_pci_hc_driver,
}, { /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, pci_ids);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b90e138..b62037b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1204,6 +1204,7 @@
*
* Returns a zero-based port number, which is suitable for indexing into each of
* the split roothubs' port arrays and bus state arrays.
+ * Add one to it in order to call xhci_find_slot_id_by_port.
*/
static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
struct xhci_hcd *xhci, u32 port_id)
@@ -1324,7 +1325,7 @@
xhci_set_link_state(xhci, port_array, faked_port_index,
XDEV_U0);
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- faked_port_index);
+ faked_port_index + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n");
goto cleanup;
@@ -3323,7 +3324,8 @@
/* Check TD length */
if (running_total != td_len) {
xhci_err(xhci, "ISOC TD length unmatch\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto cleanup;
}
}
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index d9b6a03..da97dce 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -37,9 +37,6 @@
static int emi26_load_firmware (struct usb_device *dev);
static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi26_disconnect(struct usb_interface *intf);
-static int __init emi26_init (void);
-static void __exit emi26_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi26_writememory (struct usb_device *dev, int address,
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 9f39062..4e0f167 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -46,9 +46,6 @@
static int emi62_load_firmware (struct usb_device *dev);
static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *id);
static void emi62_disconnect(struct usb_interface *intf);
-static int __init emi62_init (void);
-static void __exit emi62_exit (void);
-
/* thanks to drivers/usb/serial/keyspan_pda.c code */
static int emi62_writememory(struct usb_device *dev, int address,
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
index 107bf13..b2d82b9 100644
--- a/drivers/usb/misc/usbsevseg.c
+++ b/drivers/usb/misc/usbsevseg.c
@@ -24,7 +24,7 @@
#define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1227
-#define MAXLEN 6
+#define MAXLEN 8
/* table of devices that work with this driver */
static const struct usb_device_id id_table[] = {
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index f9a3f62..7c569f5 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -33,9 +33,6 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
-#include <mach/hardware.h>
-#include <mach/memory.h>
-#include <asm/gpio.h>
#include <mach/cputype.h>
#include <asm/mach-types.h>
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 56cf024..3d11cf64 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -981,6 +981,9 @@
unsigned long flags;
pm_runtime_get_sync(musb->controller);
+
+ musb_gadget_cleanup(musb);
+
spin_lock_irqsave(&musb->lock, flags);
musb_platform_disable(musb);
musb_generic_disable(musb);
@@ -1827,8 +1830,6 @@
sysfs_remove_group(&musb->controller->kobj, &musb_attr_group);
#endif
- musb_gadget_cleanup(musb);
-
if (musb->nIrq >= 0) {
if (musb->irq_wake)
disable_irq_wake(musb->nIrq);
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index c27bbbf..df719ea 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -222,7 +222,6 @@
musb_writel(musb->mregs, OTG_FORCESTDBY, l);
}
-/* blocking notifier support */
static int musb_otg_notifications(struct notifier_block *nb,
unsigned long event, void *unused)
{
@@ -231,7 +230,7 @@
musb->xceiv_event = event;
schedule_work(&musb->otg_notifier_work);
- return 0;
+ return NOTIFY_OK;
}
static void musb_otg_notifier_work(struct work_struct *data_notifier_work)
@@ -386,6 +385,7 @@
static int omap2430_musb_exit(struct musb *musb)
{
del_timer_sync(&musb_idle_timer);
+ cancel_work_sync(&musb->otg_notifier_work);
omap2430_low_level_exit(musb);
otg_put_transceiver(musb->xceiv);
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 2a25955..76d6293 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -86,20 +86,6 @@
built-in with usb ip or which are autonomous and doesn't require any
phy programming such as ISP1x04 etc.
-config USB_LANGWELL_OTG
- tristate "Intel Langwell USB OTG dual-role support"
- depends on USB && PCI && INTEL_SCU_IPC
- select USB_OTG
- select USB_OTG_UTILS
- help
- Say Y here if you want to build Intel Langwell USB OTG
- transciever driver in kernel. This driver implements role
- switch between EHCI host driver and Langwell USB OTG
- client driver.
-
- To compile this driver as a module, choose M here: the
- module will be called langwell_otg.
-
config USB_MSM_OTG
tristate "OTG support for Qualcomm on-chip USB controller"
depends on (USB || USB_GADGET) && ARCH_MSM
@@ -124,7 +110,7 @@
config FSL_USB2_OTG
bool "Freescale USB OTG Transceiver Driver"
- depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2
+ depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
@@ -132,7 +118,7 @@
config USB_MV_OTG
tristate "Marvell USB OTG support"
- depends on USB_MV_UDC
+ depends on USB_MV_UDC && USB_SUSPEND
select USB_OTG
select USB_OTG_UTILS
help
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
index b2c5a95..41aa509 100644
--- a/drivers/usb/otg/Makefile
+++ b/drivers/usb/otg/Makefile
@@ -13,7 +13,6 @@
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o
obj-$(CONFIG_TWL6030_USB) += twl6030-usb.o
-obj-$(CONFIG_USB_LANGWELL_OTG) += langwell_otg.o
obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o
obj-$(CONFIG_USB_ULPI) += ulpi.o
obj-$(CONFIG_USB_ULPI_VIEWPORT) += ulpi_viewport.o
diff --git a/drivers/usb/otg/langwell_otg.c b/drivers/usb/otg/langwell_otg.c
deleted file mode 100644
index f08f784..0000000
--- a/drivers/usb/otg/langwell_otg.c
+++ /dev/null
@@ -1,2347 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/* This driver helps to switch Langwell OTG controller function between host
- * and peripheral. It works with EHCI driver and Langwell client controller
- * driver together.
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/moduleparam.h>
-#include <linux/usb/ch9.h>
-#include <linux/usb/gadget.h>
-#include <linux/usb.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/hcd.h>
-#include <linux/notifier.h>
-#include <linux/delay.h>
-#include <asm/intel_scu_ipc.h>
-
-#include <linux/usb/langwell_otg.h>
-
-#define DRIVER_DESC "Intel Langwell USB OTG transceiver driver"
-#define DRIVER_VERSION "July 10, 2010"
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Henry Yuan <hang.yuan@intel.com>, Hao Wu <hao.wu@intel.com>");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL");
-
-static const char driver_name[] = "langwell_otg";
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id);
-static void langwell_otg_remove(struct pci_dev *pdev);
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message);
-static int langwell_otg_resume(struct pci_dev *pdev);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host);
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget);
-static int langwell_otg_start_srp(struct otg_transceiver *otg);
-
-static const struct pci_device_id pci_ids[] = {{
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
- .vendor = 0x8086,
- .device = 0x0811,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
-}, { /* end: all zeroes */ }
-};
-
-static struct pci_driver otg_pci_driver = {
- .name = (char *) driver_name,
- .id_table = pci_ids,
-
- .probe = langwell_otg_probe,
- .remove = langwell_otg_remove,
-
- .suspend = langwell_otg_suspend,
- .resume = langwell_otg_resume,
-};
-
-/* HSM timers */
-static inline struct langwell_otg_timer *otg_timer_initializer
-(void (*function)(unsigned long), unsigned long expires, unsigned long data)
-{
- struct langwell_otg_timer *timer;
- timer = kmalloc(sizeof(struct langwell_otg_timer), GFP_KERNEL);
- if (timer == NULL)
- return timer;
-
- timer->function = function;
- timer->expires = expires;
- timer->data = data;
- return timer;
-}
-
-static struct langwell_otg_timer *a_wait_vrise_tmr, *a_aidl_bdis_tmr,
- *b_se0_srp_tmr, *b_srp_init_tmr;
-
-static struct list_head active_timers;
-
-static struct langwell_otg *the_transceiver;
-
-/* host/client notify transceiver when event affects HNP state */
-void langwell_update_transceiver(void)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "transceiver is updated\n");
-
- if (!lnw->qwork)
- return ;
-
- queue_work(lnw->qwork, &lnw->work);
-}
-EXPORT_SYMBOL(langwell_update_transceiver);
-
-static int langwell_otg_set_host(struct otg_transceiver *otg,
- struct usb_bus *host)
-{
- otg->host = host;
-
- return 0;
-}
-
-static int langwell_otg_set_peripheral(struct otg_transceiver *otg,
- struct usb_gadget *gadget)
-{
- otg->gadget = gadget;
-
- return 0;
-}
-
-static int langwell_otg_set_power(struct otg_transceiver *otg,
- unsigned mA)
-{
- return 0;
-}
-
-/* A-device drives vbus, controlled through IPC commands */
-static int langwell_otg_set_vbus(struct otg_transceiver *otg, bool enabled)
-{
- struct langwell_otg *lnw = the_transceiver;
- u8 sub_id;
-
- dev_dbg(lnw->dev, "%s <--- %s\n", __func__, enabled ? "on" : "off");
-
- if (enabled)
- sub_id = 0x8; /* Turn on the VBus */
- else
- sub_id = 0x9; /* Turn off the VBus */
-
- if (intel_scu_ipc_simple_command(0xef, sub_id)) {
- dev_dbg(lnw->dev, "Failed to set Vbus via IPC commands\n");
- return -EBUSY;
- }
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- return 0;
-}
-
-/* charge vbus or discharge vbus through a resistor to ground */
-static void langwell_otg_chrg_vbus(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- val = readl(lnw->iotg.base + CI_OTGSC);
-
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VC,
- lnw->iotg.base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_VD,
- lnw->iotg.base + CI_OTGSC);
-}
-
-/* Start SRP */
-static int langwell_otg_start_srp(struct otg_transceiver *otg)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- val = readl(iotg->base + CI_OTGSC);
-
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HADP,
- iotg->base + CI_OTGSC);
-
- /* Check if the data plus is finished or not */
- msleep(8);
- val = readl(iotg->base + CI_OTGSC);
- if (val & (OTGSC_HADP | OTGSC_DP))
- dev_dbg(lnw->dev, "DataLine SRP Error\n");
-
- /* Disable interrupt - b_sess_vld */
- val = readl(iotg->base + CI_OTGSC);
- val &= (~(OTGSC_BSVIE | OTGSC_BSEIE));
- writel(val, iotg->base + CI_OTGSC);
-
- /* Start VBus SRP, drive vbus to generate VBus pulse */
- iotg->otg.set_vbus(&iotg->otg, true);
- msleep(15);
- iotg->otg.set_vbus(&iotg->otg, false);
-
- /* Enable interrupt - b_sess_vld*/
- val = readl(iotg->base + CI_OTGSC);
- dev_dbg(lnw->dev, "after VBUS pulse otgsc = %x\n", val);
-
- val |= (OTGSC_BSVIE | OTGSC_BSEIE);
- writel(val, iotg->base + CI_OTGSC);
-
- /* If Vbus is valid, then update the hsm */
- if (val & OTGSC_BSV) {
- dev_dbg(lnw->dev, "no b_sess_vld interrupt\n");
-
- lnw->iotg.hsm.b_sess_vld = 1;
- langwell_update_transceiver();
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return 0;
-}
-
-/* stop SOF via bus_suspend */
-static void langwell_otg_loc_sof(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct usb_hcd *hcd;
- int err;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "suspend" : "resume");
-
- hcd = bus_to_hcd(lnw->iotg.otg.host);
- if (on)
- err = hcd->driver->bus_resume(hcd);
- else
- err = hcd->driver->bus_suspend(hcd);
-
- if (err)
- dev_dbg(lnw->dev, "Fail to resume/suspend USB bus - %d\n", err);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_otgsc(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 otgsc, usbcfg;
-
- dev_dbg(lnw->dev, "check sync OTGSC and USBCFG registers\n");
-
- otgsc = readl(lnw->iotg.base + CI_OTGSC);
- usbcfg = readl(lnw->usbcfg);
-
- dev_dbg(lnw->dev, "OTGSC = %08x, USBCFG = %08x\n",
- otgsc, usbcfg);
- dev_dbg(lnw->dev, "OTGSC_AVV = %d\n", !!(otgsc & OTGSC_AVV));
- dev_dbg(lnw->dev, "USBCFG.VBUSVAL = %d\n",
- !!(usbcfg & USBCFG_VBUSVAL));
- dev_dbg(lnw->dev, "OTGSC_ASV = %d\n", !!(otgsc & OTGSC_ASV));
- dev_dbg(lnw->dev, "USBCFG.AVALID = %d\n",
- !!(usbcfg & USBCFG_AVALID));
- dev_dbg(lnw->dev, "OTGSC_BSV = %d\n", !!(otgsc & OTGSC_BSV));
- dev_dbg(lnw->dev, "USBCFG.BVALID = %d\n",
- !!(usbcfg & USBCFG_BVALID));
- dev_dbg(lnw->dev, "OTGSC_BSE = %d\n", !!(otgsc & OTGSC_BSE));
- dev_dbg(lnw->dev, "USBCFG.SESEND = %d\n",
- !!(usbcfg & USBCFG_SESEND));
-
- /* Check USBCFG VBusValid/AValid/BValid/SessEnd */
- if (!!(otgsc & OTGSC_AVV) ^ !!(usbcfg & USBCFG_VBUSVAL)) {
- dev_dbg(lnw->dev, "OTGSC.AVV != USBCFG.VBUSVAL\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_ASV) ^ !!(usbcfg & USBCFG_AVALID)) {
- dev_dbg(lnw->dev, "OTGSC.ASV != USBCFG.AVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSV) ^ !!(usbcfg & USBCFG_BVALID)) {
- dev_dbg(lnw->dev, "OTGSC.BSV != USBCFG.BVALID\n");
- goto err;
- }
- if (!!(otgsc & OTGSC_BSE) ^ !!(usbcfg & USBCFG_SESEND)) {
- dev_dbg(lnw->dev, "OTGSC.BSE != USBCFG.SESSEN\n");
- goto err;
- }
-
- dev_dbg(lnw->dev, "OTGSC and USBCFG are synced\n");
-
- return 0;
-
-err:
- dev_warn(lnw->dev, "OTGSC isn't equal to USBCFG\n");
- return -EPIPE;
-}
-
-
-static void langwell_otg_phy_low_power(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u8 val, phcd;
- int retval;
-
- dev_dbg(lnw->dev, "%s ---> %s mode\n",
- __func__, on ? "Low power" : "Normal");
-
- phcd = 0x40;
-
- val = readb(iotg->base + CI_HOSTPC1 + 2);
-
- if (on) {
- /* Due to hardware issue, after set PHCD, sync will failed
- * between USBCFG and OTGSC, so before set PHCD, check if
- * sync is in process now. If the answer is "yes", then do
- * not touch PHCD bit */
- retval = langwell_otg_check_otgsc();
- if (retval) {
- dev_dbg(lnw->dev, "Skip PHCD programming..\n");
- return ;
- }
-
- writeb(val | phcd, iotg->base + CI_HOSTPC1 + 2);
- } else
- writeb(val & ~phcd, iotg->base + CI_HOSTPC1 + 2);
-
- dev_dbg(lnw->dev, "%s <--- done\n", __func__);
-}
-
-/* After drv vbus, add 5 ms delay to set PHCD */
-static void langwell_otg_phy_low_power_wait(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- dev_dbg(lnw->dev, "add 5ms delay before programing PHCD\n");
-
- mdelay(5);
- langwell_otg_phy_low_power(on);
-}
-
-/* Enable/Disable OTG interrupt */
-static void langwell_otg_intr(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
-
- /* OTGSC_INT_MASK doesn't contains 1msInt */
- if (on) {
- val = val | (OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- } else {
- val = val & ~(OTGSC_INT_MASK);
- writel(val, iotg->base + CI_OTGSC);
- }
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HAAR: Hardware Assist Auto-Reset */
-static void langwell_otg_HAAR(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HAAR,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HAAR,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-/* set HABA: Hardware Assist B-Disconnect to A-Connect */
-static void langwell_otg_HABA(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val;
-
- dev_dbg(lnw->dev, "%s ---> %s\n", __func__, on ? "on" : "off");
-
- val = readl(iotg->base + CI_OTGSC);
- if (on)
- writel((val & ~OTGSC_INTSTS_MASK) | OTGSC_HABA,
- iotg->base + CI_OTGSC);
- else
- writel((val & ~OTGSC_INTSTS_MASK) & ~OTGSC_HABA,
- iotg->base + CI_OTGSC);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
-}
-
-static int langwell_otg_check_se0_srp(int on)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = TB_SE0_SRP * 10;
- u32 val;
-
- dev_dbg(lnw->dev, "%s --->\n", __func__);
-
- do {
- udelay(100);
- if (!delay_time--)
- break;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- val &= PORTSC_LS;
- } while (!val);
-
- dev_dbg(lnw->dev, "%s <---\n", __func__);
- return val;
-}
-
-/* The timeout callback function to set time out bit */
-static void set_tmout(unsigned long indicator)
-{
- *(int *)indicator = 1;
-}
-
-void langwell_otg_nsf_msg(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- switch (indicator) {
- case 2:
- case 4:
- case 6:
- case 7:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not responding\n", indicator);
- break;
- case 3:
- dev_warn(lnw->dev,
- "OTG:NSF-%lu - deivce not supported\n", indicator);
- break;
- default:
- dev_warn(lnw->dev, "Do not have this kind of NSF\n");
- break;
- }
-}
-
-/* Initialize timers */
-static int langwell_otg_init_timers(struct otg_hsm *hsm)
-{
- /* HSM used timers */
- a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
- (unsigned long)&hsm->a_wait_vrise_tmout);
- if (a_wait_vrise_tmr == NULL)
- return -ENOMEM;
- a_aidl_bdis_tmr = otg_timer_initializer(&set_tmout, TA_AIDL_BDIS,
- (unsigned long)&hsm->a_aidl_bdis_tmout);
- if (a_aidl_bdis_tmr == NULL)
- return -ENOMEM;
- b_se0_srp_tmr = otg_timer_initializer(&set_tmout, TB_SE0_SRP,
- (unsigned long)&hsm->b_se0_srp);
- if (b_se0_srp_tmr == NULL)
- return -ENOMEM;
- b_srp_init_tmr = otg_timer_initializer(&set_tmout, TB_SRP_INIT,
- (unsigned long)&hsm->b_srp_init_tmout);
- if (b_srp_init_tmr == NULL)
- return -ENOMEM;
-
- return 0;
-}
-
-/* Free timers */
-static void langwell_otg_free_timers(void)
-{
- kfree(a_wait_vrise_tmr);
- kfree(a_aidl_bdis_tmr);
- kfree(b_se0_srp_tmr);
- kfree(b_srp_init_tmr);
-}
-
-/* The timeout callback function to set time out bit */
-static void langwell_otg_timer_fn(unsigned long indicator)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- *(int *)indicator = 1;
-
- dev_dbg(lnw->dev, "kernel timer - timeout\n");
-
- langwell_update_transceiver();
-}
-
-/* kernel timer used instead of HW based interrupt */
-static void langwell_otg_add_ktimer(enum langwell_otg_timer_type timers)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- unsigned long j = jiffies;
- unsigned long data, time;
-
- switch (timers) {
- case TA_WAIT_VRISE_TMR:
- iotg->hsm.a_wait_vrise_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_vrise_tmout;
- time = TA_WAIT_VRISE;
- break;
- case TA_WAIT_BCON_TMR:
- iotg->hsm.a_wait_bcon_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_wait_bcon_tmout;
- time = TA_WAIT_BCON;
- break;
- case TA_AIDL_BDIS_TMR:
- iotg->hsm.a_aidl_bdis_tmout = 0;
- data = (unsigned long)&iotg->hsm.a_aidl_bdis_tmout;
- time = TA_AIDL_BDIS;
- break;
- case TB_ASE0_BRST_TMR:
- iotg->hsm.b_ase0_brst_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_ase0_brst_tmout;
- time = TB_ASE0_BRST;
- break;
- case TB_SRP_INIT_TMR:
- iotg->hsm.b_srp_init_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_init_tmout;
- time = TB_SRP_INIT;
- break;
- case TB_SRP_FAIL_TMR:
- iotg->hsm.b_srp_fail_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_srp_fail_tmout;
- time = TB_SRP_FAIL;
- break;
- case TB_BUS_SUSPEND_TMR:
- iotg->hsm.b_bus_suspend_tmout = 0;
- data = (unsigned long)&iotg->hsm.b_bus_suspend_tmout;
- time = TB_BUS_SUSPEND;
- break;
- default:
- dev_dbg(lnw->dev, "unknown timer, cannot enable it\n");
- return;
- }
-
- lnw->hsm_timer.data = data;
- lnw->hsm_timer.function = langwell_otg_timer_fn;
- lnw->hsm_timer.expires = j + time * HZ / 1000; /* milliseconds */
-
- add_timer(&lnw->hsm_timer);
-
- dev_dbg(lnw->dev, "add timer successfully\n");
-}
-
-/* Add timer to timer list */
-static void langwell_otg_add_timer(void *gtimer)
-{
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer;
- struct intel_mid_otg_xceiv *iotg = &the_transceiver->iotg;
- u32 val32;
-
- /* Check if the timer is already in the active list,
- * if so update timer count
- */
- list_for_each_entry(tmp_timer, &active_timers, list)
- if (tmp_timer == timer) {
- timer->count = timer->expires;
- return;
- }
- timer->count = timer->expires;
-
- if (list_empty(&active_timers)) {
- val32 = readl(iotg->base + CI_OTGSC);
- writel(val32 | OTGSC_1MSE, iotg->base + CI_OTGSC);
- }
-
- list_add_tail(&timer->list, &active_timers);
-}
-
-/* Remove timer from the timer list; clear timeout status */
-static void langwell_otg_del_timer(void *gtimer)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *timer = (struct langwell_otg_timer *)gtimer;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- u32 val32;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list)
- if (tmp_timer == timer)
- list_del(&timer->list);
-
- if (list_empty(&active_timers)) {
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- writel(val32 & ~OTGSC_1MSE, lnw->iotg.base + CI_OTGSC);
- }
-}
-
-/* Reduce timer count by 1, and find timeout conditions.*/
-static int langwell_otg_tick_timer(u32 *int_sts)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct langwell_otg_timer *tmp_timer, *del_tmp;
- int expired = 0;
-
- list_for_each_entry_safe(tmp_timer, del_tmp, &active_timers, list) {
- tmp_timer->count--;
- /* check if timer expires */
- if (!tmp_timer->count) {
- list_del(&tmp_timer->list);
- tmp_timer->function(tmp_timer->data);
- expired = 1;
- }
- }
-
- if (list_empty(&active_timers)) {
- dev_dbg(lnw->dev, "tick timer: disable 1ms int\n");
- *int_sts = *int_sts & ~OTGSC_1MSE;
- }
- return expired;
-}
-
-static void reset_otg(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- int delay_time = 1000;
- u32 val;
-
- dev_dbg(lnw->dev, "reseting OTG controller ...\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- writel(val | USBCMD_RST, lnw->iotg.base + CI_USBCMD);
- do {
- udelay(100);
- if (!delay_time--)
- dev_dbg(lnw->dev, "reset timeout\n");
- val = readl(lnw->iotg.base + CI_USBCMD);
- val &= USBCMD_RST;
- } while (val != 0);
- dev_dbg(lnw->dev, "reset done.\n");
-}
-
-static void set_host_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_HOST;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void set_client_mode(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- u32 val;
-
- reset_otg();
- val = readl(lnw->iotg.base + CI_USBMODE);
- val = (val & (~USBMODE_CM)) | USBMODE_DEVICE;
- writel(val, lnw->iotg.base + CI_USBMODE);
-}
-
-static void init_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC after reset */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC init value = 0x%x\n", __func__, val32);
-
- /* set init state */
- if (val32 & OTGSC_ID) {
- iotg->hsm.id = 1;
- iotg->otg.default_a = 0;
- set_client_mode();
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else {
- iotg->hsm.id = 0;
- iotg->otg.default_a = 1;
- set_host_mode();
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
-
- /* set session indicator */
- if (val32 & OTGSC_BSE)
- iotg->hsm.b_sess_end = 1;
- if (val32 & OTGSC_BSV)
- iotg->hsm.b_sess_vld = 1;
- if (val32 & OTGSC_ASV)
- iotg->hsm.a_sess_vld = 1;
- if (val32 & OTGSC_AVV)
- iotg->hsm.a_vbus_vld = 1;
-
- /* defautly power the bus */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_bus_drop = 0;
- /* defautly don't request bus as B device */
- iotg->hsm.b_bus_req = 0;
- /* no system error */
- iotg->hsm.a_clr_err = 0;
-
- langwell_otg_phy_low_power_wait(1);
-}
-
-static void update_hsm(void)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 val32;
-
- /* read OTGSC */
- val32 = readl(lnw->iotg.base + CI_OTGSC);
- dev_dbg(lnw->dev, "%s: OTGSC value = 0x%x\n", __func__, val32);
-
- iotg->hsm.id = !!(val32 & OTGSC_ID);
- iotg->hsm.b_sess_end = !!(val32 & OTGSC_BSE);
- iotg->hsm.b_sess_vld = !!(val32 & OTGSC_BSV);
- iotg->hsm.a_sess_vld = !!(val32 & OTGSC_ASV);
- iotg->hsm.a_vbus_vld = !!(val32 & OTGSC_AVV);
-}
-
-static irqreturn_t otg_dummy_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = the_transceiver;
- void __iomem *reg_base = _dev;
- u32 val;
- u32 int_mask = 0;
-
- val = readl(reg_base + CI_USBMODE);
- if ((val & USBMODE_CM) != USBMODE_DEVICE)
- return IRQ_NONE;
-
- val = readl(reg_base + CI_USBSTS);
- int_mask = val & INTR_DUMMY_MASK;
-
- if (int_mask == 0)
- return IRQ_NONE;
-
- /* clear hsm.b_conn here since host driver can't detect it
- * otg_dummy_irq called means B-disconnect happened.
- */
- if (lnw->iotg.hsm.b_conn) {
- lnw->iotg.hsm.b_conn = 0;
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- }
-
- /* Clear interrupts */
- writel(int_mask, reg_base + CI_USBSTS);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t otg_irq(int irq, void *_dev)
-{
- struct langwell_otg *lnw = _dev;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- u32 int_sts, int_en;
- u32 int_mask = 0;
- int flag = 0;
-
- int_sts = readl(lnw->iotg.base + CI_OTGSC);
- int_en = (int_sts & OTGSC_INTEN_MASK) >> 8;
- int_mask = int_sts & int_en;
- if (int_mask == 0)
- return IRQ_NONE;
-
- if (int_mask & OTGSC_IDIS) {
- dev_dbg(lnw->dev, "%s: id change int\n", __func__);
- iotg->hsm.id = (int_sts & OTGSC_ID) ? 1 : 0;
- dev_dbg(lnw->dev, "id = %d\n", iotg->hsm.id);
- flag = 1;
- }
- if (int_mask & OTGSC_DPIS) {
- dev_dbg(lnw->dev, "%s: data pulse int\n", __func__);
- iotg->hsm.a_srp_det = (int_sts & OTGSC_DPS) ? 1 : 0;
- dev_dbg(lnw->dev, "data pulse = %d\n", iotg->hsm.a_srp_det);
- flag = 1;
- }
- if (int_mask & OTGSC_BSEIS) {
- dev_dbg(lnw->dev, "%s: b session end int\n", __func__);
- iotg->hsm.b_sess_end = (int_sts & OTGSC_BSE) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_end = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_BSVIS) {
- dev_dbg(lnw->dev, "%s: b session valid int\n", __func__);
- iotg->hsm.b_sess_vld = (int_sts & OTGSC_BSV) ? 1 : 0;
- dev_dbg(lnw->dev, "b_sess_vld = %d\n", iotg->hsm.b_sess_end);
- flag = 1;
- }
- if (int_mask & OTGSC_ASVIS) {
- dev_dbg(lnw->dev, "%s: a session valid int\n", __func__);
- iotg->hsm.a_sess_vld = (int_sts & OTGSC_ASV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_sess_vld = %d\n", iotg->hsm.a_sess_vld);
- flag = 1;
- }
- if (int_mask & OTGSC_AVVIS) {
- dev_dbg(lnw->dev, "%s: a vbus valid int\n", __func__);
- iotg->hsm.a_vbus_vld = (int_sts & OTGSC_AVV) ? 1 : 0;
- dev_dbg(lnw->dev, "a_vbus_vld = %d\n", iotg->hsm.a_vbus_vld);
- flag = 1;
- }
-
- if (int_mask & OTGSC_1MSS) {
- /* need to schedule otg_work if any timer is expired */
- if (langwell_otg_tick_timer(&int_sts))
- flag = 1;
- }
-
- writel((int_sts & ~OTGSC_INTSTS_MASK) | int_mask,
- lnw->iotg.base + CI_OTGSC);
- if (flag)
- langwell_update_transceiver();
-
- return IRQ_HANDLED;
-}
-
-static int langwell_otg_iotg_notify(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = data;
- int flag = 0;
-
- if (iotg == NULL)
- return NOTIFY_BAD;
-
- if (lnw == NULL)
- return NOTIFY_BAD;
-
- switch (action) {
- case MID_OTG_NOTIFY_CONNECT:
- dev_dbg(lnw->dev, "Lnw OTG Notify Connect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 1;
- else
- iotg->hsm.a_conn = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_DISCONN:
- dev_dbg(lnw->dev, "Lnw OTG Notify Disconnect Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_conn = 0;
- else
- iotg->hsm.a_conn = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus suspend Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.a_suspend_req = 1;
- else
- iotg->hsm.b_bus_req = 0;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Host Bus resume Event\n");
- if (iotg->otg.default_a == 1)
- iotg->hsm.b_bus_resume = 1;
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CSUSPEND:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus suspend Event\n");
- if (iotg->otg.default_a == 1) {
- if (iotg->hsm.b_bus_suspend_vld == 2) {
- iotg->hsm.b_bus_suspend = 1;
- iotg->hsm.b_bus_suspend_vld = 0;
- flag = 1;
- } else {
- iotg->hsm.b_bus_suspend_vld++;
- flag = 0;
- }
- } else {
- if (iotg->hsm.a_bus_suspend == 0) {
- iotg->hsm.a_bus_suspend = 1;
- flag = 1;
- }
- }
- break;
- case MID_OTG_NOTIFY_CRESUME:
- dev_dbg(lnw->dev, "Lnw OTG Notify Client Bus resume Event\n");
- if (iotg->otg.default_a == 0)
- iotg->hsm.a_bus_suspend = 0;
- flag = 0;
- break;
- case MID_OTG_NOTIFY_HOSTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_HOSTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Host Driver remove\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTADD:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver Add\n");
- flag = 1;
- break;
- case MID_OTG_NOTIFY_CLIENTREMOVE:
- dev_dbg(lnw->dev, "Lnw OTG Nofity Client Driver remove\n");
- flag = 1;
- break;
- default:
- dev_dbg(lnw->dev, "Lnw OTG Nofity unknown notify message\n");
- return NOTIFY_DONE;
- }
-
- if (flag)
- langwell_update_transceiver();
-
- return NOTIFY_OK;
-}
-
-static void langwell_otg_work(struct work_struct *work)
-{
- struct langwell_otg *lnw;
- struct intel_mid_otg_xceiv *iotg;
- int retval;
- struct pci_dev *pdev;
-
- lnw = container_of(work, struct langwell_otg, work);
- iotg = &lnw->iotg;
- pdev = to_pci_dev(lnw->dev);
-
- dev_dbg(lnw->dev, "%s: old state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-
- switch (iotg->otg.state) {
- case OTG_STATE_UNDEFINED:
- case OTG_STATE_B_IDLE:
- if (!iotg->hsm.id) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_del_timer(b_srp_init_tmr);
- del_timer_sync(&lnw->hsm_timer);
- iotg->hsm.b_sess_end = 0;
- iotg->hsm.a_bus_suspend = 0;
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
-
- } else if (iotg->hsm.b_srp_init_tmout) {
- iotg->hsm.b_srp_init_tmout = 0;
- dev_warn(lnw->dev, "SRP init timeout\n");
- } else if (iotg->hsm.b_srp_fail_tmout) {
- iotg->hsm.b_srp_fail_tmout = 0;
- iotg->hsm.b_bus_req = 0;
-
- /* No silence failure */
- langwell_otg_nsf_msg(6);
- } else if (iotg->hsm.b_bus_req && iotg->hsm.b_sess_end) {
- del_timer_sync(&lnw->hsm_timer);
- /* workaround for b_se0_srp detection */
- retval = langwell_otg_check_se0_srp(0);
- if (retval) {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "LS isn't SE0, try later\n");
- } else {
- /* clear the PHCD before start srp */
- langwell_otg_phy_low_power(0);
-
- /* Start SRP */
- langwell_otg_add_timer(b_srp_init_tmr);
- iotg->otg.start_srp(&iotg->otg);
- langwell_otg_del_timer(b_srp_init_tmr);
- langwell_otg_add_ktimer(TB_SRP_FAIL_TMR);
-
- /* reset PHY low power mode here */
- langwell_otg_phy_low_power_wait(1);
- }
- }
- break;
- case OTG_STATE_B_SRP_INIT:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_chrg_vbus(0);
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.b_sess_vld) {
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.start_peripheral) {
- lnw->iotg.start_peripheral(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- } else
- dev_dbg(lnw->dev, "client driver not loaded\n");
- }
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.b_bus_req && iotg->otg.gadget &&
- iotg->otg.gadget->b_hnp_enable &&
- iotg->hsm.a_bus_suspend) {
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- langwell_otg_HAAR(1);
- iotg->hsm.a_conn = 0;
-
- if (lnw->iotg.start_host) {
- lnw->iotg.start_host(&lnw->iotg);
- iotg->otg.state = OTG_STATE_B_WAIT_ACON;
- } else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
-
- iotg->hsm.a_bus_resume = 0;
- langwell_otg_add_ktimer(TB_ASE0_BRST_TMR);
- }
- break;
-
- case OTG_STATE_B_WAIT_ACON:
- if (!iotg->hsm.id) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- langwell_otg_HAAR(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_conn) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- iotg->otg.state = OTG_STATE_B_HOST;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_resume ||
- iotg->hsm.b_ase0_brst_tmout) {
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
- langwell_otg_nsf_msg(7);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_B_HOST:
- if (!iotg->hsm.id) {
- iotg->otg.default_a = 1;
- iotg->hsm.a_srp_det = 0;
-
- langwell_otg_chrg_vbus(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.b_sess_vld) {
- iotg->hsm.b_hnp_enable = 0;
- iotg->hsm.b_bus_req = 0;
-
- langwell_otg_chrg_vbus(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if ((!iotg->hsm.b_bus_req) ||
- (!iotg->hsm.a_conn)) {
- iotg->hsm.b_bus_req = 0;
- langwell_otg_loc_sof(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.a_bus_suspend = 0;
-
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- iotg->otg.state = OTG_STATE_B_PERIPHERAL;
- }
- break;
-
- case OTG_STATE_A_IDLE:
- iotg->otg.default_a = 1;
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- iotg->hsm.vbus_srp_up = 0;
-
- langwell_otg_chrg_vbus(0);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop &&
- (iotg->hsm.a_srp_det || iotg->hsm.a_bus_req)) {
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
-
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_bus_drop && iotg->hsm.a_sess_vld) {
- iotg->hsm.vbus_srp_up = 1;
- } else if (!iotg->hsm.a_sess_vld && iotg->hsm.vbus_srp_up) {
- msleep(10);
- langwell_otg_phy_low_power(0);
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_srp_det = 1;
- iotg->hsm.vbus_srp_up = 0;
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_sess_vld &&
- !iotg->hsm.vbus_srp_up) {
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VRISE:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_bus_req = 0;
- iotg->otg.default_a = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- } else if (iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.b_conn = 0;
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev, "host driver not loaded.\n");
- break;
- }
-
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.a_wait_vrise_tmout) {
- iotg->hsm.b_conn = 0;
- if (iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else {
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- break;
- }
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else {
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- }
- break;
- case OTG_STATE_A_WAIT_BCON:
- if (iotg->hsm.id) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->hsm.a_wait_bcon_tmout &&
- !iotg->hsm.a_bus_req)) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_conn) {
- /* delete hsm timer for a_wait_bcon_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- iotg->hsm.a_suspend_req = 0;
- iotg->otg.state = OTG_STATE_A_HOST;
- if (iotg->hsm.a_srp_det && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- /* SRP capable peripheral-only device */
- iotg->hsm.a_bus_req = 1;
- iotg->hsm.a_srp_det = 0;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- /* It is not safe enough to do a fast
- * transition from A_WAIT_BCON to
- * A_SUSPEND */
- msleep(10000);
- if (iotg->hsm.a_bus_req)
- break;
-
- if (request_irq(pdev->irq,
- otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d fail\n",
- pdev->irq);
- }
-
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
-
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.a_bus_req && iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- }
- }
- break;
- case OTG_STATE_A_HOST:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_drop ||
- (iotg->otg.host &&
- !iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req)) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.a_vbus_vld) {
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->otg.host &&
- iotg->otg.host->b_hnp_enable &&
- !iotg->hsm.a_bus_req) {
- /* Set HABA to enable hardware assistance to signal
- * A-connect after receiver B-disconnect. Hardware
- * will then set client mode and enable URE, SLE and
- * PCE after the assistance. otg_dummy_irq is used to
- * clean these ints when client driver is not resumed.
- */
- if (request_irq(pdev->irq, otg_dummy_irq, IRQF_SHARED,
- driver_name, iotg->base) != 0) {
- dev_dbg(lnw->dev,
- "request interrupt %d failed\n",
- pdev->irq);
- }
-
- /* set HABA */
- langwell_otg_HABA(1);
- iotg->hsm.b_bus_resume = 0;
- iotg->hsm.a_aidl_bdis_tmout = 0;
- langwell_otg_loc_sof(0);
- /* clear PHCD to enable HW timer */
- langwell_otg_phy_low_power(0);
- langwell_otg_add_timer(a_aidl_bdis_tmr);
- iotg->otg.state = OTG_STATE_A_SUSPEND;
- } else if (!iotg->hsm.b_conn || !iotg->hsm.a_bus_req) {
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_SUSPEND:
- if (iotg->hsm.id) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req ||
- iotg->hsm.b_bus_resume) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- iotg->hsm.a_suspend_req = 0;
- langwell_otg_loc_sof(1);
- iotg->otg.state = OTG_STATE_A_HOST;
- } else if (iotg->hsm.a_aidl_bdis_tmout ||
- iotg->hsm.a_bus_drop) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (!iotg->hsm.b_conn && iotg->otg.host &&
- iotg->otg.host->b_hnp_enable) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- iotg->hsm.b_bus_suspend = 0;
- iotg->hsm.b_bus_suspend_vld = 0;
-
- /* msleep(200); */
- if (lnw->iotg.start_peripheral)
- lnw->iotg.start_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver not loaded.\n");
-
- langwell_otg_add_ktimer(TB_BUS_SUSPEND_TMR);
- iotg->otg.state = OTG_STATE_A_PERIPHERAL;
- break;
- } else if (!iotg->hsm.a_vbus_vld) {
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- free_irq(pdev->irq, iotg->base);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- }
- break;
- case OTG_STATE_A_PERIPHERAL:
- if (iotg->hsm.id) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
- iotg->otg.default_a = 0;
- iotg->hsm.b_bus_req = 0;
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- set_client_mode();
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (!iotg->hsm.a_vbus_vld) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- langwell_otg_phy_low_power_wait(1);
- iotg->otg.state = OTG_STATE_A_VBUS_ERR;
- } else if (iotg->hsm.a_bus_drop) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_WAIT_VFALL;
- } else if (iotg->hsm.b_bus_suspend) {
- /* delete hsm timer for b_bus_suspend_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- } else if (iotg->hsm.b_bus_suspend_tmout) {
- u32 val;
- val = readl(lnw->iotg.base + CI_PORTSC1);
- if (!(val & PORTSC_SUSP))
- break;
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "client driver has been removed.\n");
-
- if (lnw->iotg.start_host)
- lnw->iotg.start_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev,
- "host driver not loaded.\n");
- langwell_otg_add_ktimer(TA_WAIT_BCON_TMR);
- iotg->otg.state = OTG_STATE_A_WAIT_BCON;
- }
- break;
- case OTG_STATE_A_VBUS_ERR:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_clr_err) {
- iotg->hsm.a_clr_err = 0;
- iotg->hsm.a_srp_det = 0;
- reset_otg();
- init_hsm();
- if (iotg->otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
- } else {
- /* FW will clear PHCD bit when any VBus
- * event detected. Reset PHCD to 1 again */
- langwell_otg_phy_low_power(1);
- }
- break;
- case OTG_STATE_A_WAIT_VFALL:
- if (iotg->hsm.id) {
- iotg->otg.default_a = 0;
- set_client_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_B_IDLE;
- langwell_update_transceiver();
- } else if (iotg->hsm.a_bus_req) {
-
- /* Turn on VBus */
- iotg->otg.set_vbus(&iotg->otg, true);
- iotg->hsm.a_wait_vrise_tmout = 0;
- langwell_otg_add_timer(a_wait_vrise_tmr);
- iotg->otg.state = OTG_STATE_A_WAIT_VRISE;
- } else if (!iotg->hsm.a_sess_vld) {
- iotg->hsm.a_srp_det = 0;
- set_host_mode();
- langwell_otg_phy_low_power(1);
- iotg->otg.state = OTG_STATE_A_IDLE;
- }
- break;
- default:
- ;
- }
-
- dev_dbg(lnw->dev, "%s: new state = %s\n", __func__,
- otg_state_string(iotg->otg.state));
-}
-
-static ssize_t
-show_registers(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size,
- "\n"
- "USBCMD = 0x%08x\n"
- "USBSTS = 0x%08x\n"
- "USBINTR = 0x%08x\n"
- "ASYNCLISTADDR = 0x%08x\n"
- "PORTSC1 = 0x%08x\n"
- "HOSTPC1 = 0x%08x\n"
- "OTGSC = 0x%08x\n"
- "USBMODE = 0x%08x\n",
- readl(lnw->iotg.base + 0x30),
- readl(lnw->iotg.base + 0x34),
- readl(lnw->iotg.base + 0x38),
- readl(lnw->iotg.base + 0x48),
- readl(lnw->iotg.base + 0x74),
- readl(lnw->iotg.base + 0xb4),
- readl(lnw->iotg.base + 0xf4),
- readl(lnw->iotg.base + 0xf8)
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL);
-
-static ssize_t
-show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- if (iotg->otg.host)
- iotg->hsm.a_set_b_hnp_en = iotg->otg.host->b_hnp_enable;
-
- if (iotg->otg.gadget)
- iotg->hsm.b_hnp_enable = iotg->otg.gadget->b_hnp_enable;
-
- t = scnprintf(next, size,
- "\n"
- "current state = %s\n"
- "a_bus_resume = \t%d\n"
- "a_bus_suspend = \t%d\n"
- "a_conn = \t%d\n"
- "a_sess_vld = \t%d\n"
- "a_srp_det = \t%d\n"
- "a_vbus_vld = \t%d\n"
- "b_bus_resume = \t%d\n"
- "b_bus_suspend = \t%d\n"
- "b_conn = \t%d\n"
- "b_se0_srp = \t%d\n"
- "b_sess_end = \t%d\n"
- "b_sess_vld = \t%d\n"
- "id = \t%d\n"
- "a_set_b_hnp_en = \t%d\n"
- "b_srp_done = \t%d\n"
- "b_hnp_enable = \t%d\n"
- "a_wait_vrise_tmout = \t%d\n"
- "a_wait_bcon_tmout = \t%d\n"
- "a_aidl_bdis_tmout = \t%d\n"
- "b_ase0_brst_tmout = \t%d\n"
- "a_bus_drop = \t%d\n"
- "a_bus_req = \t%d\n"
- "a_clr_err = \t%d\n"
- "a_suspend_req = \t%d\n"
- "b_bus_req = \t%d\n"
- "b_bus_suspend_tmout = \t%d\n"
- "b_bus_suspend_vld = \t%d\n",
- otg_state_string(iotg->otg.state),
- iotg->hsm.a_bus_resume,
- iotg->hsm.a_bus_suspend,
- iotg->hsm.a_conn,
- iotg->hsm.a_sess_vld,
- iotg->hsm.a_srp_det,
- iotg->hsm.a_vbus_vld,
- iotg->hsm.b_bus_resume,
- iotg->hsm.b_bus_suspend,
- iotg->hsm.b_conn,
- iotg->hsm.b_se0_srp,
- iotg->hsm.b_sess_end,
- iotg->hsm.b_sess_vld,
- iotg->hsm.id,
- iotg->hsm.a_set_b_hnp_en,
- iotg->hsm.b_srp_done,
- iotg->hsm.b_hnp_enable,
- iotg->hsm.a_wait_vrise_tmout,
- iotg->hsm.a_wait_bcon_tmout,
- iotg->hsm.a_aidl_bdis_tmout,
- iotg->hsm.b_ase0_brst_tmout,
- iotg->hsm.a_bus_drop,
- iotg->hsm.a_bus_req,
- iotg->hsm.a_clr_err,
- iotg->hsm.a_suspend_req,
- iotg->hsm.b_bus_req,
- iotg->hsm.b_bus_suspend_tmout,
- iotg->hsm.b_bus_suspend_vld
- );
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
-
-static ssize_t
-get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_req = 0\n");
- } else if (buf[0] == '1') {
- /* If a_bus_drop is TRUE, a_bus_req can't be set */
- if (iotg->hsm.a_bus_drop)
- return -1;
- iotg->hsm.a_bus_req = 1;
- dev_dbg(lnw->dev, "User request: a_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
-
-static ssize_t
-get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.a_bus_drop);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_a_bus_drop(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.a_bus_drop = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.a_bus_drop = 1;
- iotg->hsm.a_bus_req = 0;
- dev_dbg(lnw->dev, "User request: a_bus_drop = 1\n");
- dev_dbg(lnw->dev, "User request: and a_bus_req = 0\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop, set_a_bus_drop);
-
-static ssize_t
-get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct langwell_otg *lnw = the_transceiver;
- char *next;
- unsigned size, t;
-
- next = buf;
- size = PAGE_SIZE;
-
- t = scnprintf(next, size, "%d", lnw->iotg.hsm.b_bus_req);
- size -= t;
- next += t;
-
- return PAGE_SIZE - size;
-}
-
-static ssize_t
-set_b_bus_req(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (iotg->otg.default_a)
- return -1;
-
- if (count > 2)
- return -1;
-
- if (buf[0] == '0') {
- iotg->hsm.b_bus_req = 0;
- dev_dbg(lnw->dev, "User request: b_bus_req = 0\n");
- } else if (buf[0] == '1') {
- iotg->hsm.b_bus_req = 1;
- dev_dbg(lnw->dev, "User request: b_bus_req = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
-
-static ssize_t
-set_a_clr_err(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
-
- if (!iotg->otg.default_a)
- return -1;
- if (count > 2)
- return -1;
-
- if (buf[0] == '1') {
- iotg->hsm.a_clr_err = 1;
- dev_dbg(lnw->dev, "User request: a_clr_err = 1\n");
- }
- if (spin_trylock(&lnw->wq_lock)) {
- langwell_update_transceiver();
- spin_unlock(&lnw->wq_lock);
- }
- return count;
-}
-static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
-
-static struct attribute *inputs_attrs[] = {
- &dev_attr_a_bus_req.attr,
- &dev_attr_a_bus_drop.attr,
- &dev_attr_b_bus_req.attr,
- &dev_attr_a_clr_err.attr,
- NULL,
-};
-
-static struct attribute_group debug_dev_attr_group = {
- .name = "inputs",
- .attrs = inputs_attrs,
-};
-
-static int langwell_otg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- unsigned long resource, len;
- void __iomem *base = NULL;
- int retval;
- u32 val32;
- struct langwell_otg *lnw;
- char qname[] = "langwell_otg_queue";
-
- retval = 0;
- dev_dbg(&pdev->dev, "\notg controller is detected.\n");
- if (pci_enable_device(pdev) < 0) {
- retval = -ENODEV;
- goto done;
- }
-
- lnw = kzalloc(sizeof *lnw, GFP_KERNEL);
- if (lnw == NULL) {
- retval = -ENOMEM;
- goto done;
- }
- the_transceiver = lnw;
-
- /* control register: BAR 0 */
- resource = pci_resource_start(pdev, 0);
- len = pci_resource_len(pdev, 0);
- if (!request_mem_region(resource, len, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->region = 1;
-
- base = ioremap_nocache(resource, len);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->iotg.base = base;
-
- if (!request_mem_region(USBCFG_ADDR, USBCFG_LEN, driver_name)) {
- retval = -EBUSY;
- goto err;
- }
- lnw->cfg_region = 1;
-
- /* For the SCCB.USBCFG register */
- base = ioremap_nocache(USBCFG_ADDR, USBCFG_LEN);
- if (base == NULL) {
- retval = -EFAULT;
- goto err;
- }
- lnw->usbcfg = base;
-
- if (!pdev->irq) {
- dev_dbg(&pdev->dev, "No IRQ.\n");
- retval = -ENODEV;
- goto err;
- }
-
- lnw->qwork = create_singlethread_workqueue(qname);
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create workqueue %s\n", qname);
- retval = -ENOMEM;
- goto err;
- }
- INIT_WORK(&lnw->work, langwell_otg_work);
-
- /* OTG common part */
- lnw->dev = &pdev->dev;
- lnw->iotg.otg.dev = lnw->dev;
- lnw->iotg.otg.label = driver_name;
- lnw->iotg.otg.set_host = langwell_otg_set_host;
- lnw->iotg.otg.set_peripheral = langwell_otg_set_peripheral;
- lnw->iotg.otg.set_power = langwell_otg_set_power;
- lnw->iotg.otg.set_vbus = langwell_otg_set_vbus;
- lnw->iotg.otg.start_srp = langwell_otg_start_srp;
- lnw->iotg.otg.state = OTG_STATE_UNDEFINED;
-
- if (otg_set_transceiver(&lnw->iotg.otg)) {
- dev_dbg(lnw->dev, "can't set transceiver\n");
- retval = -EBUSY;
- goto err;
- }
-
- reset_otg();
- init_hsm();
-
- spin_lock_init(&lnw->lock);
- spin_lock_init(&lnw->wq_lock);
- INIT_LIST_HEAD(&active_timers);
- retval = langwell_otg_init_timers(&lnw->iotg.hsm);
- if (retval) {
- dev_dbg(&pdev->dev, "Failed to init timers\n");
- goto err;
- }
-
- init_timer(&lnw->hsm_timer);
- ATOMIC_INIT_NOTIFIER_HEAD(&lnw->iotg.iotg_notifier);
-
- lnw->iotg_notifier.notifier_call = langwell_otg_iotg_notify;
-
- retval = intel_mid_otg_register_notifier(&lnw->iotg,
- &lnw->iotg_notifier);
- if (retval) {
- dev_dbg(lnw->dev, "Failed to register notifier\n");
- goto err;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(lnw->dev, "request interrupt %d failed\n", pdev->irq);
- retval = -EBUSY;
- goto err;
- }
-
- /* enable OTGSC int */
- val32 = OTGSC_DPIE | OTGSC_BSEIE | OTGSC_BSVIE |
- OTGSC_ASVIE | OTGSC_AVVIE | OTGSC_IDIE | OTGSC_IDPU;
- writel(val32, lnw->iotg.base + CI_OTGSC);
-
- retval = device_create_file(&pdev->dev, &dev_attr_registers);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = device_create_file(&pdev->dev, &dev_attr_hsm);
- if (retval < 0) {
- dev_dbg(lnw->dev, "Can't hsm sysfs attribute: %d\n", retval);
- goto err;
- }
-
- retval = sysfs_create_group(&pdev->dev.kobj, &debug_dev_attr_group);
- if (retval < 0) {
- dev_dbg(lnw->dev,
- "Can't register sysfs attr group: %d\n", retval);
- goto err;
- }
-
- if (lnw->iotg.otg.state == OTG_STATE_A_IDLE)
- langwell_update_transceiver();
-
- return 0;
-
-err:
- if (the_transceiver)
- langwell_otg_remove(pdev);
-done:
- return retval;
-}
-
-static void langwell_otg_remove(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
-
- if (lnw->qwork) {
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- }
- intel_mid_otg_unregister_notifier(&lnw->iotg, &lnw->iotg_notifier);
- langwell_otg_free_timers();
-
- /* disable OTGSC interrupt as OTGSC doesn't change in reset */
- writel(0, lnw->iotg.base + CI_OTGSC);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
- if (lnw->usbcfg)
- iounmap(lnw->usbcfg);
- if (lnw->cfg_region)
- release_mem_region(USBCFG_ADDR, USBCFG_LEN);
- if (lnw->iotg.base)
- iounmap(lnw->iotg.base);
- if (lnw->region)
- release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
-
- otg_set_transceiver(NULL);
- pci_disable_device(pdev);
- sysfs_remove_group(&pdev->dev.kobj, &debug_dev_attr_group);
- device_remove_file(&pdev->dev, &dev_attr_hsm);
- device_remove_file(&pdev->dev, &dev_attr_registers);
- kfree(lnw);
- lnw = NULL;
-}
-
-static void transceiver_suspend(struct pci_dev *pdev)
-{
- pci_save_state(pdev);
- pci_set_power_state(pdev, PCI_D3hot);
- langwell_otg_phy_low_power(1);
-}
-
-static int langwell_otg_suspend(struct pci_dev *pdev, pm_message_t message)
-{
- struct langwell_otg *lnw = the_transceiver;
- struct intel_mid_otg_xceiv *iotg = &lnw->iotg;
- int ret = 0;
-
- /* Disbale OTG interrupts */
- langwell_otg_intr(0);
-
- if (pdev->irq)
- free_irq(pdev->irq, lnw);
-
- /* Prevent more otg_work */
- flush_workqueue(lnw->qwork);
- destroy_workqueue(lnw->qwork);
- lnw->qwork = NULL;
-
- /* start actions */
- switch (iotg->otg.state) {
- case OTG_STATE_A_WAIT_VFALL:
- iotg->otg.state = OTG_STATE_A_IDLE;
- case OTG_STATE_A_IDLE:
- case OTG_STATE_B_IDLE:
- case OTG_STATE_A_VBUS_ERR:
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_VRISE:
- langwell_otg_del_timer(a_wait_vrise_tmr);
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_WAIT_BCON:
- del_timer_sync(&lnw->hsm_timer);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
-
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
-
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_SUSPEND:
- langwell_otg_del_timer(a_aidl_bdis_tmr);
- langwell_otg_HABA(0);
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(lnw->dev, "host driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_A_PERIPHERAL:
- del_timer_sync(&lnw->hsm_timer);
-
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->hsm.a_srp_det = 0;
-
- /* Turn off VBus */
- iotg->otg.set_vbus(&iotg->otg, false);
- iotg->otg.state = OTG_STATE_A_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_HOST:
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_PERIPHERAL:
- if (lnw->iotg.stop_peripheral)
- lnw->iotg.stop_peripheral(&lnw->iotg);
- else
- dev_dbg(&pdev->dev,
- "client driver has been removed.\n");
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- case OTG_STATE_B_WAIT_ACON:
- /* delete hsm timer for b_ase0_brst_tmr */
- del_timer_sync(&lnw->hsm_timer);
-
- langwell_otg_HAAR(0);
-
- if (lnw->iotg.stop_host)
- lnw->iotg.stop_host(&lnw->iotg);
- else
- dev_dbg(&pdev->dev, "host driver has been removed.\n");
- iotg->hsm.b_bus_req = 0;
- iotg->otg.state = OTG_STATE_B_IDLE;
- transceiver_suspend(pdev);
- break;
- default:
- dev_dbg(lnw->dev, "error state before suspend\n");
- break;
- }
-
- return ret;
-}
-
-static void transceiver_resume(struct pci_dev *pdev)
-{
- pci_restore_state(pdev);
- pci_set_power_state(pdev, PCI_D0);
-}
-
-static int langwell_otg_resume(struct pci_dev *pdev)
-{
- struct langwell_otg *lnw = the_transceiver;
- int ret = 0;
-
- transceiver_resume(pdev);
-
- lnw->qwork = create_singlethread_workqueue("langwell_otg_queue");
- if (!lnw->qwork) {
- dev_dbg(&pdev->dev, "cannot create langwell otg workqueuen");
- ret = -ENOMEM;
- goto error;
- }
-
- if (request_irq(pdev->irq, otg_irq, IRQF_SHARED,
- driver_name, lnw) != 0) {
- dev_dbg(&pdev->dev, "request interrupt %d failed\n", pdev->irq);
- ret = -EBUSY;
- goto error;
- }
-
- /* enable OTG interrupts */
- langwell_otg_intr(1);
-
- update_hsm();
-
- langwell_update_transceiver();
-
- return ret;
-error:
- langwell_otg_intr(0);
- transceiver_suspend(pdev);
- return ret;
-}
-
-static int __init langwell_otg_init(void)
-{
- return pci_register_driver(&otg_pci_driver);
-}
-module_init(langwell_otg_init);
-
-static void __exit langwell_otg_cleanup(void)
-{
- pci_unregister_driver(&otg_pci_driver);
-}
-module_exit(langwell_otg_cleanup);
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index db0d4fc..b5fbe14 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -202,6 +202,7 @@
static void mv_otg_start_host(struct mv_otg *mvotg, int on)
{
+#ifdef CONFIG_USB
struct otg_transceiver *otg = &mvotg->otg;
struct usb_hcd *hcd;
@@ -216,6 +217,7 @@
usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
else
usb_remove_hcd(hcd);
+#endif /* CONFIG_USB */
}
static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 528691d5f..7542aa9 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -425,7 +425,7 @@
struct usbhs_pipe *pipe;
int recip = ctrl->bRequestType & USB_RECIP_MASK;
int nth = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
- int ret;
+ int ret = 0;
int (*func)(struct usbhs_priv *priv, struct usbhsg_uep *uep,
struct usb_ctrlrequest *ctrl);
char *msg;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index fba1147..8dbf51a 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -39,6 +39,8 @@
struct usb_serial_port *port);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp210x_tiocmget(struct tty_struct *);
@@ -138,6 +140,7 @@
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
@@ -201,6 +204,8 @@
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
@@ -360,8 +365,8 @@
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
- if (baud <= 56) baud = 0;
- else if (baud <= 300) baud = 300;
+ if (baud <= 300)
+ baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
@@ -389,10 +394,10 @@
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
- else if (baud <= 1053257) baud = 921600;
- else if (baud <= 1474560) baud = 1228800;
- else if (baud <= 2457600) baud = 1843200;
- else baud = 3686400;
+ else if (baud < 1000000)
+ baud = 921600;
+ else if (baud > 2000000)
+ baud = 2000000;
return baud;
}
@@ -409,13 +414,14 @@
return result;
}
- result = usb_serial_generic_open(tty, port);
- if (result)
- return result;
-
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- return 0;
+
+ /* The baud rate must be initialised on cp2104 */
+ if (tty)
+ cp210x_change_speed(tty, port, NULL);
+
+ return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
@@ -467,10 +473,7 @@
dbg("%s - port %d", __func__, port->number);
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
@@ -579,11 +582,64 @@
*cflagp = cflag;
}
+/*
+ * CP2101 supports the following baud rates:
+ *
+ * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ * 576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ * div = round(freq / (2 x prescale x request))
+ * actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ u32 baud;
+
+ baud = tty->termios->c_ospeed;
+
+ /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+ * or to an arbitrary rate in [1M,2M].
+ *
+ * NOTE: B0 is not implemented.
+ */
+ baud = cp210x_quantise_baudrate(baud);
+
+ dbg("%s - setting baud rate to %u", __func__, baud);
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+ sizeof(baud))) {
+ dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+ if (old_termios)
+ baud = old_termios->c_ospeed;
+ else
+ baud = 9600;
+ }
+
+ tty_encode_baud_rate(tty, baud, baud);
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ unsigned int bits;
unsigned int modem_ctl[4];
dbg("%s - port %d", __func__, port->number);
@@ -593,20 +649,9 @@
cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
- /* If the baud rate is to be updated*/
- if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
- dbg("%s - Setting baud rate to %d baud", __func__,
- baud);
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
- dbg("Baud rate requested not supported by device");
- baud = tty_termios_baud_rate(old_termios);
- }
- }
- /* Report back the resulting baud rate */
- tty_encode_baud_rate(tty, baud, baud);
+ if (tty->termios->c_ospeed != old_termios->c_ospeed)
+ cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 01b6404..ad654f8 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -797,6 +797,7 @@
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
@@ -805,6 +806,8 @@
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@@ -841,6 +844,7 @@
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -1333,8 +1337,7 @@
goto check_and_exit;
}
- if ((new_serial.baud_base != priv->baud_base) &&
- (new_serial.baud_base < 9600)) {
+ if (new_serial.baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
@@ -1824,6 +1827,7 @@
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;
@@ -1842,8 +1846,10 @@
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (tty)
- ftdi_set_termios(tty, port, tty->termios);
+ if (tty) {
+ memset(&dummy, 0, sizeof(dummy));
+ ftdi_set_termios(tty, port, &dummy);
+ }
/* Start reading from the device */
result = usb_serial_generic_open(tty, port);
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index df1d7da..f994503 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -39,6 +39,13 @@
/* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID 0xa6d0
+
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
/* US Interface Navigator (http://www.usinterface.com/) */
@@ -525,6 +532,12 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
+ * Hornby Elite
+ */
+#define HORNBY_VID 0x04D8
+#define HORNBY_ELITE_PID 0x000A
+
+/*
* RATOC REX-USB60F
*/
#define RATOC_VENDOR_ID 0x0584
@@ -1168,3 +1181,9 @@
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106 0x8A28
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 65bf06a..5818bfc 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2657,15 +2657,7 @@
static void edge_disconnect(struct usb_serial *serial)
{
- int i;
- struct edgeport_port *edge_port;
-
dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- edge_remove_sysfs_attrs(edge_port->port);
- }
}
static void edge_release(struct usb_serial *serial)
@@ -2744,6 +2736,7 @@
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -2775,6 +2768,7 @@
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index 5d3beee..a92a3ef 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -38,7 +38,7 @@
#include <linux/ioctl.h>
#include "kobil_sct.h"
-static int debug;
+static bool debug;
/* Version Information */
#define DRIVER_VERSION "21/05/2004"
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 420d985..ea126a4 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -480,6 +480,10 @@
#define ZD_VENDOR_ID 0x0685
#define ZD_PRODUCT_7000 0x7000
+/* LG products */
+#define LG_VENDOR_ID 0x1004
+#define LG_PRODUCT_L02C 0x618f
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
@@ -1183,6 +1187,7 @@
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
{ USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 30b73e6..a348198 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -36,6 +36,7 @@
#define UTSTARCOM_PRODUCT_UM175_V1 0x3712
#define UTSTARCOM_PRODUCT_UM175_V2 0x3714
#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715
+#define PANTECH_PRODUCT_UML190_VZW 0x3716
#define PANTECH_PRODUCT_UML290_VZW 0x3718
/* CMOTECH devices */
@@ -67,7 +68,11 @@
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 1f62723..d32f720 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -789,7 +789,7 @@
rts51x_set_stat(chip, RTS51X_STAT_SS);
/* ignore mass storage interface's children */
pm_suspend_ignore_children(&us->pusb_intf->dev, true);
- usb_autopm_put_interface(us->pusb_intf);
+ usb_autopm_put_interface_async(us->pusb_intf);
US_DEBUGP("%s: RTS51X_STAT_SS 01,"
"intf->pm_usage_cnt:%d, power.usage:%d\n",
__func__,
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 8efeae2..b4a7167 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -27,8 +27,6 @@
#define USB_SKEL_VENDOR_ID 0xfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
-static DEFINE_MUTEX(skel_mutex);
-
/* table of devices that work with this driver */
static const struct usb_device_id skel_table[] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
@@ -101,25 +99,18 @@
goto exit;
}
- mutex_lock(&skel_mutex);
dev = usb_get_intfdata(interface);
if (!dev) {
- mutex_unlock(&skel_mutex);
retval = -ENODEV;
goto exit;
}
/* increment our usage count for the device */
kref_get(&dev->kref);
- mutex_unlock(&skel_mutex);
/* lock the device to allow correctly handling errors
* in resumption */
mutex_lock(&dev->io_mutex);
- if (!dev->interface) {
- retval = -ENODEV;
- goto out_err;
- }
retval = usb_autopm_get_interface(interface);
if (retval)
@@ -127,11 +118,7 @@
/* save our object in the file's private structure */
file->private_data = dev;
-
-out_err:
mutex_unlock(&dev->io_mutex);
- if (retval)
- kref_put(&dev->kref, skel_delete);
exit:
return retval;
@@ -611,6 +598,7 @@
int minor = interface->minor;
dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
/* give back our minor */
usb_deregister_dev(interface, &skel_class);
@@ -622,12 +610,8 @@
usb_kill_anchored_urbs(&dev->submitted);
- mutex_lock(&skel_mutex);
- usb_set_intfdata(interface, NULL);
-
/* decrement our usage count */
kref_put(&dev->kref, skel_delete);
- mutex_unlock(&skel_mutex);
dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor);
}
diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig
index 0ead882..f29fdd7 100644
--- a/drivers/usb/wusbcore/Kconfig
+++ b/drivers/usb/wusbcore/Kconfig
@@ -6,7 +6,7 @@
depends on EXPERIMENTAL
depends on USB
depends on PCI
- select UWB
+ depends on UWB
select CRYPTO
select CRYPTO_BLKCIPHER
select CRYPTO_CBC
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c
index 43207cc..fe01add 100644
--- a/drivers/video/macfb.c
+++ b/drivers/video/macfb.c
@@ -592,12 +592,12 @@
if (!fb_info.screen_base)
return -ENODEV;
- printk("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
- macfb_fix.smem_start, fb_info.screen_base,
- macfb_fix.smem_len / 1024);
- printk("macfb: mode is %dx%dx%d, linelength=%d\n",
- macfb_defined.xres, macfb_defined.yres,
- macfb_defined.bits_per_pixel, macfb_fix.line_length);
+ pr_info("macfb: framebuffer at 0x%08lx, mapped to 0x%p, size %dk\n",
+ macfb_fix.smem_start, fb_info.screen_base,
+ macfb_fix.smem_len / 1024);
+ pr_info("macfb: mode is %dx%dx%d, linelength=%d\n",
+ macfb_defined.xres, macfb_defined.yres,
+ macfb_defined.bits_per_pixel, macfb_fix.line_length);
/* Fill in the available video resolution */
macfb_defined.xres_virtual = macfb_defined.xres;
@@ -613,14 +613,10 @@
switch (macfb_defined.bits_per_pixel) {
case 1:
- /*
- * XXX: I think this will catch any program that tries
- * to do FBIO_PUTCMAP when the visual is monochrome.
- */
macfb_defined.red.length = macfb_defined.bits_per_pixel;
macfb_defined.green.length = macfb_defined.bits_per_pixel;
macfb_defined.blue.length = macfb_defined.bits_per_pixel;
- video_cmap_len = 0;
+ video_cmap_len = 2;
macfb_fix.visual = FB_VISUAL_MONO01;
break;
case 2:
@@ -660,11 +656,10 @@
macfb_fix.visual = FB_VISUAL_TRUECOLOR;
break;
default:
- video_cmap_len = 0;
- macfb_fix.visual = FB_VISUAL_MONO01;
- printk("macfb: unknown or unsupported bit depth: %d\n",
+ pr_err("macfb: unknown or unsupported bit depth: %d\n",
macfb_defined.bits_per_pixel);
- break;
+ err = -EINVAL;
+ goto fail_unmap;
}
/*
@@ -734,8 +729,8 @@
case MAC_MODEL_Q950:
strcpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -744,8 +739,8 @@
case MAC_MODEL_LCII:
strcpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -758,8 +753,8 @@
case MAC_MODEL_P600:
strcpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -773,10 +768,10 @@
case MAC_MODEL_P520:
case MAC_MODEL_P550:
case MAC_MODEL_P460:
- macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Sonora");
+ macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -786,10 +781,10 @@
*/
case MAC_MODEL_IICI:
case MAC_MODEL_IISI:
- macfb_setpalette = rbv_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "RBV");
+ macfb_setpalette = rbv_setpalette;
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
@@ -797,10 +792,10 @@
*/
case MAC_MODEL_Q840:
case MAC_MODEL_C660:
- macfb_setpalette = civic_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "Civic");
+ macfb_setpalette = civic_setpalette;
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
@@ -809,26 +804,26 @@
* We think this may be like the LC II
*/
case MAC_MODEL_LC:
+ strcpy(macfb_fix.id, "LC");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "LC");
break;
/*
* We think this may be like the LC II
*/
case MAC_MODEL_CCL:
+ strcpy(macfb_fix.id, "Color Classic");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
}
- strcpy(macfb_fix.id, "Color Classic");
break;
/*
@@ -893,10 +888,10 @@
case MAC_MODEL_PB270C:
case MAC_MODEL_PB280:
case MAC_MODEL_PB280C:
- macfb_setpalette = csc_setpalette;
- macfb_defined.activate = FB_ACTIVATE_NOW;
strcpy(macfb_fix.id, "CSC");
+ macfb_setpalette = csc_setpalette;
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
+ macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
@@ -918,8 +913,9 @@
if (err)
goto fail_dealloc;
- printk("fb%d: %s frame buffer device\n",
- fb_info.node, fb_info.fix.id);
+ pr_info("fb%d: %s frame buffer device\n",
+ fb_info.node, fb_info.fix.id);
+
return 0;
fail_dealloc:
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 79e1b29..5aa43c3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -35,7 +35,7 @@
#define virtio_rmb(vq) \
do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
#define virtio_wmb(vq) \
- do { if ((vq)->weak_barriers) smp_rmb(); else rmb(); } while(0)
+ do { if ((vq)->weak_barriers) smp_wmb(); else wmb(); } while(0)
#else
/* We must force memory ordering even if guest is UP since host could be
* running on another CPU, but SMP barriers are defined to barrier() in that
@@ -308,9 +308,9 @@
bool needs_kick;
START_USE(vq);
- /* Descriptors and available array need to be set before we expose the
- * new available array entries. */
- virtio_wmb(vq);
+ /* We need to expose available array entries before checking avail
+ * event. */
+ virtio_mb(vq);
old = vq->vring.avail->idx - vq->num_added;
new = vq->vring.avail->idx;
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 1b0e3dd..63d7b58 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -300,11 +300,7 @@
if (!mem)
return -EINVAL;
- if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
- "dw_wdt"))
- return -ENOMEM;
-
- dw_wdt.regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ dw_wdt.regs = devm_request_and_ioremap(&pdev->dev, mem);
if (!dw_wdt.regs)
return -ENOMEM;
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 99796c5..bdf401b 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -36,6 +36,7 @@
* document number TBD : Patsburg (PBG)
* document number TBD : DH89xxCC
* document number TBD : Panther Point
+ * document number TBD : Lynx Point
*/
/*
@@ -126,6 +127,7 @@
TCO_PBG, /* Patsburg */
TCO_DH89XXCC, /* DH89xxCC */
TCO_PPT, /* Panther Point */
+ TCO_LPT, /* Lynx Point */
};
static struct {
@@ -189,6 +191,7 @@
{"Patsburg", 2},
{"DH89xxCC", 2},
{"Panther Point", 2},
+ {"Lynx Point", 2},
{NULL, 0}
};
@@ -331,6 +334,38 @@
{ PCI_VDEVICE(INTEL, 0x1e5d), TCO_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5e), TCO_PPT},
{ PCI_VDEVICE(INTEL, 0x1e5f), TCO_PPT},
+ { PCI_VDEVICE(INTEL, 0x8c40), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c41), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c42), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c43), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c44), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c45), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c46), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c47), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c48), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c49), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4a), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4b), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4c), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4d), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4e), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c4f), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c50), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c51), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c52), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c53), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c54), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c55), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c56), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c57), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c58), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c59), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5a), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5b), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5c), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5d), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5e), TCO_LPT},
+ { PCI_VDEVICE(INTEL, 0x8c5f), TCO_LPT},
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index b8ef2c6..c44c333 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -247,7 +247,6 @@
static int __init imx2_wdt_probe(struct platform_device *pdev)
{
int ret;
- int res_size;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -256,15 +255,7 @@
return -ENODEV;
}
- res_size = resource_size(res);
- if (!devm_request_mem_region(&pdev->dev, res->start, res_size,
- res->name)) {
- dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
- res_size, res->start);
- return -ENOMEM;
- }
-
- imx2_wdt.base = devm_ioremap_nocache(&pdev->dev, res->start, res_size);
+ imx2_wdt.base = devm_request_and_ioremap(&pdev->dev, res);
if (!imx2_wdt.base) {
dev_err(&pdev->dev, "ioremap failed\n");
return -ENOMEM;
diff --git a/drivers/watchdog/nuc900_wdt.c b/drivers/watchdog/nuc900_wdt.c
index 50359ba..529085b 100644
--- a/drivers/watchdog/nuc900_wdt.c
+++ b/drivers/watchdog/nuc900_wdt.c
@@ -72,7 +72,7 @@
};
static unsigned long nuc900wdt_busy;
-struct nuc900_wdt *nuc900_wdt;
+static struct nuc900_wdt *nuc900_wdt;
static inline void nuc900_wdt_keepalive(void)
{
@@ -287,7 +287,8 @@
setup_timer(&nuc900_wdt->timer, nuc900_wdt_timer_ping, 0);
- if (misc_register(&nuc900wdt_miscdev)) {
+ ret = misc_register(&nuc900wdt_miscdev);
+ if (ret) {
dev_err(&pdev->dev, "err register miscdev on minor=%d (%d)\n",
WATCHDOG_MINOR, ret);
goto err_clk;
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index 4b33e3f..d19ff51 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -339,6 +339,7 @@
return 0;
err_misc:
+ pm_runtime_disable(wdev->dev);
platform_set_drvdata(pdev, NULL);
iounmap(wdev->base);
@@ -371,6 +372,7 @@
struct omap_wdt_dev *wdev = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pm_runtime_disable(wdev->dev);
if (!res)
return -ENOENT;
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
index bd143c9..8e210aa 100644
--- a/drivers/watchdog/pnx4008_wdt.c
+++ b/drivers/watchdog/pnx4008_wdt.c
@@ -226,7 +226,7 @@
static int pnx4008_wdt_release(struct inode *inode, struct file *file)
{
if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status))
- printk(KERN_WARNING "WATCHDOG: Device closed unexpectdly\n");
+ printk(KERN_WARNING "WATCHDOG: Device closed unexpectedly\n");
wdt_disable();
clk_disable(wdt_clk);
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
index 4c2a4e8..e37d811 100644
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ b/drivers/watchdog/stmp3xxx_wdt.c
@@ -174,7 +174,7 @@
if (!nowayout) {
if (!test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
wdt_ping();
- pr_debug("%s: Device closed unexpectdly\n", __func__);
+ pr_debug("%s: Device closed unexpectedly\n", __func__);
ret = -EINVAL;
} else {
wdt_disable();
diff --git a/drivers/watchdog/via_wdt.c b/drivers/watchdog/via_wdt.c
index 026b4bb..8f07dd4 100644
--- a/drivers/watchdog/via_wdt.c
+++ b/drivers/watchdog/via_wdt.c
@@ -124,8 +124,6 @@
static int wdt_set_timeout(struct watchdog_device *wdd,
unsigned int new_timeout)
{
- if (new_timeout < 1 || new_timeout > WDT_TIMEOUT_MAX)
- return -EINVAL;
writel(new_timeout, wdt_mem + VIA_WDT_COUNT);
timeout = new_timeout;
return 0;
@@ -150,6 +148,8 @@
static struct watchdog_device wdt_dev = {
.info = &wdt_info,
.ops = &wdt_ops,
+ .min_timeout = 1,
+ .max_timeout = WDT_TIMEOUT_MAX,
};
static int __devinit wdt_probe(struct pci_dev *pdev,
@@ -233,7 +233,7 @@
pci_disable_device(pdev);
}
-DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
+static DEFINE_PCI_DEVICE_TABLE(wdt_pci_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800) },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c
index 42e940c..c3c3188 100644
--- a/drivers/watchdog/wafer5823wdt.c
+++ b/drivers/watchdog/wafer5823wdt.c
@@ -152,12 +152,12 @@
return -EFAULT;
if (options & WDIOS_DISABLECARD) {
- wafwdt_start();
+ wafwdt_stop();
retval = 0;
}
if (options & WDIOS_ENABLECARD) {
- wafwdt_stop();
+ wafwdt_start();
retval = 0;
}
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index 909c786..5d7113c 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -212,10 +212,10 @@
/* Setting both simultaneously means at least one must fail */
if (options == WDIOS_DISABLECARD)
- ret = wm8350_wdt_start(wm8350);
+ ret = wm8350_wdt_stop(wm8350);
if (options == WDIOS_ENABLECARD)
- ret = wm8350_wdt_stop(wm8350);
+ ret = wm8350_wdt_start(wm8350);
break;
}
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 1cd94da..b4d4eac 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -948,9 +948,12 @@
int rc;
struct gnttab_set_version gsv;
- gsv.version = 2;
+ if (xen_hvm_domain())
+ gsv.version = 1;
+ else
+ gsv.version = 2;
rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
- if (rc == 0) {
+ if (rc == 0 && gsv.version == 2) {
grant_table_version = 2;
gnttab_interface = &gnttab_v2_ops;
} else if (grant_table_version == 2) {
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index b9a8432..633c701 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -297,7 +297,7 @@
struct btrfs_delayed_extent_op *extent_op = head->extent_op;
struct rb_node *n = &head->node.rb_node;
int sgn;
- int ret;
+ int ret = 0;
if (extent_op && extent_op->update_key)
btrfs_disk_key_to_cpu(info_key, &extent_op->key);
@@ -392,7 +392,7 @@
struct btrfs_key *info_key, int *info_level,
struct list_head *prefs)
{
- int ret;
+ int ret = 0;
int slot;
struct extent_buffer *leaf;
struct btrfs_key key;
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index ad0b3ba..b669a7d 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -1662,7 +1662,7 @@
block = btrfsic_block_hashtable_lookup(bdev, dev_bytenr,
&state->block_hashtable);
if (NULL != block) {
- u64 bytenr;
+ u64 bytenr = 0;
struct list_head *elem_ref_to;
struct list_head *tmp_ref_to;
@@ -2777,9 +2777,10 @@
printk(KERN_INFO
"submit_bh(rw=0x%x, blocknr=%lu (bytenr %llu),"
" size=%lu, data=%p, bdev=%p)\n",
- rw, bh->b_blocknr,
- (unsigned long long)dev_bytenr, bh->b_size,
- bh->b_data, bh->b_bdev);
+ rw, (unsigned long)bh->b_blocknr,
+ (unsigned long long)dev_bytenr,
+ (unsigned long)bh->b_size, bh->b_data,
+ bh->b_bdev);
btrfsic_process_written_block(dev_state, dev_bytenr,
bh->b_data, bh->b_size, NULL,
NULL, bh, rw);
@@ -2844,7 +2845,7 @@
printk(KERN_INFO
"submit_bio(rw=0x%x, bi_vcnt=%u,"
" bi_sector=%lu (bytenr %llu), bi_bdev=%p)\n",
- rw, bio->bi_vcnt, bio->bi_sector,
+ rw, bio->bi_vcnt, (unsigned long)bio->bi_sector,
(unsigned long long)dev_bytenr,
bio->bi_bdev);
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 7aa9cd3..811d9f9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -962,6 +962,13 @@
tree = &BTRFS_I(page->mapping->host)->io_tree;
map = &BTRFS_I(page->mapping->host)->extent_tree;
+ /*
+ * We need to mask out eg. __GFP_HIGHMEM and __GFP_DMA32 as we're doing
+ * slab allocation from alloc_extent_state down the callchain where
+ * it'd hit a BUG_ON as those flags are not allowed.
+ */
+ gfp_flags &= ~GFP_SLAB_BUG_MASK;
+
ret = try_release_extent_state(map, tree, page, gfp_flags);
if (!ret)
return 0;
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 700879e..283af7a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -34,23 +34,24 @@
#include "locking.h"
#include "free-space-cache.h"
-/* control flags for do_chunk_alloc's force field
+/*
+ * control flags for do_chunk_alloc's force field
* CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
* if we really need one.
*
- * CHUNK_ALLOC_FORCE means it must try to allocate one
- *
* CHUNK_ALLOC_LIMITED means to only try and allocate one
* if we have very few chunks already allocated. This is
* used as part of the clustering code to help make sure
* we have a good pool of storage to cluster in, without
* filling the FS with empty chunks
*
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
+ *
*/
enum {
CHUNK_ALLOC_NO_FORCE = 0,
- CHUNK_ALLOC_FORCE = 1,
- CHUNK_ALLOC_LIMITED = 2,
+ CHUNK_ALLOC_LIMITED = 1,
+ CHUNK_ALLOC_FORCE = 2,
};
/*
@@ -3414,7 +3415,7 @@
again:
spin_lock(&space_info->lock);
- if (space_info->force_alloc)
+ if (force < space_info->force_alloc)
force = space_info->force_alloc;
if (space_info->full) {
spin_unlock(&space_info->lock);
@@ -5794,6 +5795,7 @@
u64 search_end, struct btrfs_key *ins,
u64 data)
{
+ bool final_tried = false;
int ret;
u64 search_start = 0;
@@ -5813,22 +5815,25 @@
search_start, search_end, hint_byte,
ins, data);
- if (ret == -ENOSPC && num_bytes > min_alloc_size) {
- num_bytes = num_bytes >> 1;
- num_bytes = num_bytes & ~(root->sectorsize - 1);
- num_bytes = max(num_bytes, min_alloc_size);
- do_chunk_alloc(trans, root->fs_info->extent_root,
- num_bytes, data, CHUNK_ALLOC_FORCE);
- goto again;
- }
- if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
- struct btrfs_space_info *sinfo;
+ if (ret == -ENOSPC) {
+ if (!final_tried) {
+ num_bytes = num_bytes >> 1;
+ num_bytes = num_bytes & ~(root->sectorsize - 1);
+ num_bytes = max(num_bytes, min_alloc_size);
+ do_chunk_alloc(trans, root->fs_info->extent_root,
+ num_bytes, data, CHUNK_ALLOC_FORCE);
+ if (num_bytes == min_alloc_size)
+ final_tried = true;
+ goto again;
+ } else if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
+ struct btrfs_space_info *sinfo;
- sinfo = __find_space_info(root->fs_info, data);
- printk(KERN_ERR "btrfs allocation failed flags %llu, "
- "wanted %llu\n", (unsigned long long)data,
- (unsigned long long)num_bytes);
- dump_space_info(sinfo, num_bytes, 1);
+ sinfo = __find_space_info(root->fs_info, data);
+ printk(KERN_ERR "btrfs allocation failed flags %llu, "
+ "wanted %llu\n", (unsigned long long)data,
+ (unsigned long long)num_bytes);
+ dump_space_info(sinfo, num_bytes, 1);
+ }
}
trace_btrfs_reserved_extent_alloc(root, ins->objectid, ins->offset);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 9d09a4f..fcf77e1 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -3909,6 +3909,8 @@
while (start <= end) {
index = start >> PAGE_CACHE_SHIFT;
page = find_get_page(tree->mapping, index);
+ if (!page)
+ return 1;
uptodate = PageUptodate(page);
page_cache_release(page);
if (!uptodate) {
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index d20ff87..c2f2059 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -2242,7 +2242,7 @@
if (entry->bitmap) {
ret = btrfs_alloc_from_bitmap(block_group,
cluster, entry, bytes,
- min_start);
+ cluster->window_start);
if (ret == 0) {
node = rb_next(&entry->offset_index);
if (!node)
@@ -2251,6 +2251,7 @@
offset_index);
continue;
}
+ cluster->window_start += bytes;
} else {
ret = entry->offset;
@@ -2475,7 +2476,7 @@
}
list_for_each_entry(entry, bitmaps, list) {
- if (entry->bytes < min_bytes)
+ if (entry->bytes < bytes)
continue;
ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
bytes, cont1_bytes, min_bytes);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 0da19a0..32214fe 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6401,18 +6401,23 @@
unsigned long zero_start;
loff_t size;
int ret;
+ int reserved = 0;
u64 page_start;
u64 page_end;
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
- if (!ret)
+ if (!ret) {
ret = btrfs_update_time(vma->vm_file);
+ reserved = 1;
+ }
if (ret) {
if (ret == -ENOMEM)
ret = VM_FAULT_OOM;
else /* -ENOSPC, -EIO, etc */
ret = VM_FAULT_SIGBUS;
- goto out;
+ if (reserved)
+ goto out;
+ goto out_noreserve;
}
ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
@@ -6495,6 +6500,7 @@
unlock_page(page);
out:
btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
+out_noreserve:
return ret;
}
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index ab62001..03bb62a 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1065,7 +1065,7 @@
i = range->start >> PAGE_CACHE_SHIFT;
}
if (!max_to_defrag)
- max_to_defrag = last_index;
+ max_to_defrag = last_index + 1;
/*
* make writeback starts from i, so the defrag range can be
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index cb877e0..966cc74 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -1957,7 +1957,8 @@
finish_wait(&root->log_commit_wait[index], &wait);
mutex_lock(&root->log_mutex);
- } while (root->log_transid < transid + 2 &&
+ } while (root->fs_info->last_trans_log_full_commit !=
+ trans->transid && root->log_transid < transid + 2 &&
atomic_read(&root->log_commit[index]));
return 0;
}
@@ -1966,7 +1967,8 @@
struct btrfs_root *root)
{
DEFINE_WAIT(wait);
- while (atomic_read(&root->log_writers)) {
+ while (root->fs_info->last_trans_log_full_commit !=
+ trans->transid && atomic_read(&root->log_writers)) {
prepare_to_wait(&root->log_writer_wait,
&wait, TASK_UNINTERRUPTIBLE);
mutex_unlock(&root->log_mutex);
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index b60fc8bf..620daad 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -641,10 +641,10 @@
unsigned long ttl;
u32 gen;
- spin_lock(&cap->session->s_cap_lock);
+ spin_lock(&cap->session->s_gen_ttl_lock);
gen = cap->session->s_cap_gen;
ttl = cap->session->s_cap_ttl;
- spin_unlock(&cap->session->s_cap_lock);
+ spin_unlock(&cap->session->s_gen_ttl_lock);
if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) {
dout("__cap_is_valid %p cap %p issued %s "
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 618246b..3e8094b 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -975,10 +975,10 @@
di = ceph_dentry(dentry);
if (di->lease_session) {
s = di->lease_session;
- spin_lock(&s->s_cap_lock);
+ spin_lock(&s->s_gen_ttl_lock);
gen = s->s_cap_gen;
ttl = s->s_cap_ttl;
- spin_unlock(&s->s_cap_lock);
+ spin_unlock(&s->s_gen_ttl_lock);
if (di->lease_gen == gen &&
time_before(jiffies, dentry->d_time) &&
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 23ab6a3..866e8d7 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -262,6 +262,7 @@
/* trace */
ceph_decode_32_safe(&p, end, len, bad);
if (len > 0) {
+ ceph_decode_need(&p, end, len, bad);
err = parse_reply_info_trace(&p, p+len, info, features);
if (err < 0)
goto out_bad;
@@ -270,6 +271,7 @@
/* extra */
ceph_decode_32_safe(&p, end, len, bad);
if (len > 0) {
+ ceph_decode_need(&p, end, len, bad);
err = parse_reply_info_extra(&p, p+len, info, features);
if (err < 0)
goto out_bad;
@@ -398,9 +400,11 @@
s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS;
s->s_con.peer_name.num = cpu_to_le64(mds);
- spin_lock_init(&s->s_cap_lock);
+ spin_lock_init(&s->s_gen_ttl_lock);
s->s_cap_gen = 0;
s->s_cap_ttl = 0;
+
+ spin_lock_init(&s->s_cap_lock);
s->s_renew_requested = 0;
s->s_renew_seq = 0;
INIT_LIST_HEAD(&s->s_caps);
@@ -2326,10 +2330,10 @@
case CEPH_SESSION_STALE:
pr_info("mds%d caps went stale, renewing\n",
session->s_mds);
- spin_lock(&session->s_cap_lock);
+ spin_lock(&session->s_gen_ttl_lock);
session->s_cap_gen++;
session->s_cap_ttl = 0;
- spin_unlock(&session->s_cap_lock);
+ spin_unlock(&session->s_gen_ttl_lock);
send_renew_caps(mdsc, session);
break;
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index a50ca0e..8c7c04e 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -117,10 +117,13 @@
void *s_authorizer_buf, *s_authorizer_reply_buf;
size_t s_authorizer_buf_len, s_authorizer_reply_buf_len;
- /* protected by s_cap_lock */
- spinlock_t s_cap_lock;
+ /* protected by s_gen_ttl_lock */
+ spinlock_t s_gen_ttl_lock;
u32 s_cap_gen; /* inc each time we get mds stale msg */
unsigned long s_cap_ttl; /* when session caps expire */
+
+ /* protected by s_cap_lock */
+ spinlock_t s_cap_lock;
struct list_head s_caps; /* all caps issued by this session */
int s_nr_caps, s_trim_caps;
int s_num_cap_releases;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 857214a..a76f697 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -111,8 +111,10 @@
}
static struct ceph_vxattr_cb ceph_file_vxattrs[] = {
+ { true, "ceph.file.layout", ceph_vxattrcb_layout},
+ /* The following extended attribute name is deprecated */
{ true, "ceph.layout", ceph_vxattrcb_layout},
- { NULL, NULL }
+ { true, NULL, NULL }
};
static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode)
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 2a83425..63ab245 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -417,17 +417,6 @@
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "encryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
page, (extent_offset
* crypt_stat->extent_size),
@@ -440,14 +429,6 @@
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "encryption:\n");
- ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
- }
out:
return rc;
}
@@ -543,17 +524,6 @@
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "decryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(enc_extent_page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
(extent_offset
* crypt_stat->extent_size),
@@ -567,16 +537,6 @@
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "decryption:\n");
- ecryptfs_dump_hex((char *)(page_address(page)
- + (extent_offset
- * crypt_stat->extent_size)), 8);
- }
out:
return rc;
}
@@ -1590,8 +1550,8 @@
*/
int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
{
- int rc = 0;
- char *page_virt = NULL;
+ int rc;
+ char *page_virt;
struct inode *ecryptfs_inode = ecryptfs_dentry->d_inode;
struct ecryptfs_crypt_stat *crypt_stat =
&ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
@@ -1616,11 +1576,13 @@
ecryptfs_dentry,
ECRYPTFS_VALIDATE_HEADER_SIZE);
if (rc) {
+ /* metadata is not in the file header, so try xattrs */
memset(page_virt, 0, PAGE_CACHE_SIZE);
rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file header region or xattr region\n");
+ "file header region or xattr region, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
goto out;
}
@@ -1629,7 +1591,8 @@
ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file xattr region either\n");
+ "file xattr region either, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
if (crypt_stat->mount_crypt_stat->flags
@@ -1640,7 +1603,8 @@
"crypto metadata only in the extended attribute "
"region, but eCryptfs was mounted without "
"xattr support enabled. eCryptfs will not treat "
- "this like an encrypted file.\n");
+ "this like an encrypted file, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
}
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h
index a9f29b1..a2362df 100644
--- a/fs/ecryptfs/ecryptfs_kernel.h
+++ b/fs/ecryptfs/ecryptfs_kernel.h
@@ -151,6 +151,11 @@
* dentry name */
#define ECRYPTFS_TAG_73_PACKET_TYPE 0x49 /* FEK-encrypted filename as
* metadata */
+#define ECRYPTFS_MIN_PKT_LEN_SIZE 1 /* Min size to specify packet length */
+#define ECRYPTFS_MAX_PKT_LEN_SIZE 2 /* Pass at least this many bytes to
+ * ecryptfs_parse_packet_length() and
+ * ecryptfs_write_packet_length()
+ */
/* Constraint: ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES >=
* ECRYPTFS_MAX_IV_BYTES */
#define ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES 16
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 19a8ca4..19892d7 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -822,18 +822,6 @@
size_t num_zeros = (PAGE_CACHE_SIZE
- (ia->ia_size & ~PAGE_CACHE_MASK));
-
- /*
- * XXX(truncate) this should really happen at the begginning
- * of ->setattr. But the code is too messy to that as part
- * of a larger patch. ecryptfs is also totally missing out
- * on the inode_change_ok check at the beginning of
- * ->setattr while would include this.
- */
- rc = inode_newsize_ok(inode, ia->ia_size);
- if (rc)
- goto out;
-
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
truncate_setsize(inode, ia->ia_size);
lower_ia->ia_size = ia->ia_size;
@@ -883,6 +871,28 @@
return rc;
}
+static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
+{
+ struct ecryptfs_crypt_stat *crypt_stat;
+ loff_t lower_oldsize, lower_newsize;
+
+ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ lower_oldsize = upper_size_to_lower_size(crypt_stat,
+ i_size_read(inode));
+ lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
+ if (lower_newsize > lower_oldsize) {
+ /*
+ * The eCryptfs inode and the new *lower* size are mixed here
+ * because we may not have the lower i_mutex held and/or it may
+ * not be appropriate to call inode_newsize_ok() with inodes
+ * from other filesystems.
+ */
+ return inode_newsize_ok(inode, lower_newsize);
+ }
+
+ return 0;
+}
+
/**
* ecryptfs_truncate
* @dentry: The ecryptfs layer dentry
@@ -899,6 +909,10 @@
struct iattr lower_ia = { .ia_valid = 0 };
int rc;
+ rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
+ if (rc)
+ return rc;
+
rc = truncate_upper(dentry, &ia, &lower_ia);
if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
@@ -978,6 +992,16 @@
}
}
mutex_unlock(&crypt_stat->cs_mutex);
+
+ rc = inode_change_ok(inode, ia);
+ if (rc)
+ goto out;
+ if (ia->ia_valid & ATTR_SIZE) {
+ rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
+ if (rc)
+ goto out;
+ }
+
if (S_ISREG(inode->i_mode)) {
rc = filemap_write_and_wait(inode->i_mapping);
if (rc)
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
index ac1ad48..8e3b943 100644
--- a/fs/ecryptfs/keystore.c
+++ b/fs/ecryptfs/keystore.c
@@ -109,7 +109,7 @@
(*size) += ((unsigned char)(data[1]) + 192);
(*length_size) = 2;
} else if (data[0] == 255) {
- /* Five-byte length; we're not supposed to see this */
+ /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
ecryptfs_printk(KERN_ERR, "Five-byte packet length not "
"supported\n");
rc = -EINVAL;
@@ -126,7 +126,7 @@
/**
* ecryptfs_write_packet_length
* @dest: The byte array target into which to write the length. Must
- * have at least 5 bytes allocated.
+ * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated.
* @size: The length to write.
* @packet_size_length: The number of bytes used to encode the packet
* length is written to this address.
@@ -146,6 +146,7 @@
dest[1] = ((size - 192) % 256);
(*packet_size_length) = 2;
} else {
+ /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
rc = -EINVAL;
ecryptfs_printk(KERN_WARNING,
"Unsupported packet size: [%zd]\n", size);
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 940a82e..349209d 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -218,6 +218,29 @@
return rc;
}
+/*
+ * miscdevfs packet format:
+ * Octet 0: Type
+ * Octets 1-4: network byte order msg_ctx->counter
+ * Octets 5-N0: Size of struct ecryptfs_message to follow
+ * Octets N0-N1: struct ecryptfs_message (including data)
+ *
+ * Octets 5-N1 not written if the packet type does not include a message
+ */
+#define PKT_TYPE_SIZE 1
+#define PKT_CTR_SIZE 4
+#define MIN_NON_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+#define MIN_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ + ECRYPTFS_MIN_PKT_LEN_SIZE)
+/* 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES comes from tag 65 packet format */
+#define MAX_MSG_PKT_SIZE (PKT_TYPE_SIZE + PKT_CTR_SIZE \
+ + ECRYPTFS_MAX_PKT_LEN_SIZE \
+ + sizeof(struct ecryptfs_message) \
+ + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)
+#define PKT_TYPE_OFFSET 0
+#define PKT_CTR_OFFSET PKT_TYPE_SIZE
+#define PKT_LEN_OFFSET (PKT_TYPE_SIZE + PKT_CTR_SIZE)
+
/**
* ecryptfs_miscdev_read - format and send message from queue
* @file: fs/ecryptfs/euid miscdevfs handle (ignored)
@@ -237,7 +260,7 @@
struct ecryptfs_daemon *daemon;
struct ecryptfs_msg_ctx *msg_ctx;
size_t packet_length_size;
- char packet_length[3];
+ char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
size_t i;
size_t total_length;
uid_t euid = current_euid();
@@ -305,15 +328,8 @@
packet_length_size = 0;
msg_ctx->msg_size = 0;
}
- /* miscdevfs packet format:
- * Octet 0: Type
- * Octets 1-4: network byte order msg_ctx->counter
- * Octets 5-N0: Size of struct ecryptfs_message to follow
- * Octets N0-N1: struct ecryptfs_message (including data)
- *
- * Octets 5-N1 not written if the packet type does not
- * include a message */
- total_length = (1 + 4 + packet_length_size + msg_ctx->msg_size);
+ total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
+ + msg_ctx->msg_size);
if (count < total_length) {
rc = 0;
printk(KERN_WARNING "%s: Only given user buffer of "
@@ -324,9 +340,10 @@
rc = -EFAULT;
if (put_user(msg_ctx->type, buf))
goto out_unlock_msg_ctx;
- if (put_user(cpu_to_be32(msg_ctx->counter), (__be32 __user *)(buf + 1)))
+ if (put_user(cpu_to_be32(msg_ctx->counter),
+ (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
goto out_unlock_msg_ctx;
- i = 5;
+ i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
if (msg_ctx->msg) {
if (copy_to_user(&buf[i], packet_length, packet_length_size))
goto out_unlock_msg_ctx;
@@ -391,12 +408,6 @@
* @count: Amount of data in @buf
* @ppos: Pointer to offset in file (ignored)
*
- * miscdevfs packet format:
- * Octet 0: Type
- * Octets 1-4: network byte order msg_ctx->counter (0's for non-response)
- * Octets 5-N0: Size of struct ecryptfs_message to follow
- * Octets N0-N1: struct ecryptfs_message (including data)
- *
* Returns the number of bytes read from @buf
*/
static ssize_t
@@ -405,60 +416,78 @@
{
__be32 counter_nbo;
u32 seq;
- size_t packet_size, packet_size_length, i;
- ssize_t sz = 0;
+ size_t packet_size, packet_size_length;
char *data;
uid_t euid = current_euid();
- int rc;
+ unsigned char packet_size_peek[ECRYPTFS_MAX_PKT_LEN_SIZE];
+ ssize_t rc;
- if (count == 0)
- goto out;
+ if (count == 0) {
+ return 0;
+ } else if (count == MIN_NON_MSG_PKT_SIZE) {
+ /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
+ goto memdup;
+ } else if (count < MIN_MSG_PKT_SIZE || count > MAX_MSG_PKT_SIZE) {
+ printk(KERN_WARNING "%s: Acceptable packet size range is "
+ "[%d-%lu], but amount of data written is [%zu].",
+ __func__, MIN_MSG_PKT_SIZE, MAX_MSG_PKT_SIZE, count);
+ return -EINVAL;
+ }
+ if (copy_from_user(packet_size_peek, &buf[PKT_LEN_OFFSET],
+ sizeof(packet_size_peek))) {
+ printk(KERN_WARNING "%s: Error while inspecting packet size\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
+ &packet_size_length);
+ if (rc) {
+ printk(KERN_WARNING "%s: Error parsing packet length; "
+ "rc = [%zd]\n", __func__, rc);
+ return rc;
+ }
+
+ if ((PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_size_length + packet_size)
+ != count) {
+ printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
+ packet_size);
+ return -EINVAL;
+ }
+
+memdup:
data = memdup_user(buf, count);
if (IS_ERR(data)) {
printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
__func__, PTR_ERR(data));
- goto out;
+ return PTR_ERR(data);
}
- sz = count;
- i = 0;
- switch (data[i++]) {
+ switch (data[PKT_TYPE_OFFSET]) {
case ECRYPTFS_MSG_RESPONSE:
- if (count < (1 + 4 + 1 + sizeof(struct ecryptfs_message))) {
+ if (count < (MIN_MSG_PKT_SIZE
+ + sizeof(struct ecryptfs_message))) {
printk(KERN_WARNING "%s: Minimum acceptable packet "
"size is [%zd], but amount of data written is "
"only [%zd]. Discarding response packet.\n",
__func__,
- (1 + 4 + 1 + sizeof(struct ecryptfs_message)),
- count);
+ (MIN_MSG_PKT_SIZE
+ + sizeof(struct ecryptfs_message)), count);
+ rc = -EINVAL;
goto out_free;
}
- memcpy(&counter_nbo, &data[i], 4);
+ memcpy(&counter_nbo, &data[PKT_CTR_OFFSET], PKT_CTR_SIZE);
seq = be32_to_cpu(counter_nbo);
- i += 4;
- rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
- &packet_size_length);
+ rc = ecryptfs_miscdev_response(
+ &data[PKT_LEN_OFFSET + packet_size_length],
+ packet_size, euid, current_user_ns(),
+ task_pid(current), seq);
if (rc) {
- printk(KERN_WARNING "%s: Error parsing packet length; "
- "rc = [%d]\n", __func__, rc);
- goto out_free;
- }
- i += packet_size_length;
- if ((1 + 4 + packet_size_length + packet_size) != count) {
- printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
- " + packet_size([%zd]))([%zd]) != "
- "count([%zd]). Invalid packet format.\n",
- __func__, packet_size_length, packet_size,
- (1 + packet_size_length + packet_size), count);
- goto out_free;
- }
- rc = ecryptfs_miscdev_response(&data[i], packet_size,
- euid, current_user_ns(),
- task_pid(current), seq);
- if (rc)
printk(KERN_WARNING "%s: Failed to deliver miscdev "
- "response to requesting operation; rc = [%d]\n",
+ "response to requesting operation; rc = [%zd]\n",
__func__, rc);
+ goto out_free;
+ }
break;
case ECRYPTFS_MSG_HELO:
case ECRYPTFS_MSG_QUIT:
@@ -467,12 +496,13 @@
ecryptfs_printk(KERN_WARNING, "Dropping miscdev "
"message of unrecognized type [%d]\n",
data[0]);
- break;
+ rc = -EINVAL;
+ goto out_free;
}
+ rc = count;
out_free:
kfree(data);
-out:
- return sz;
+ return rc;
}
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
index 6a44148..10ec695 100644
--- a/fs/ecryptfs/mmap.c
+++ b/fs/ecryptfs/mmap.c
@@ -57,6 +57,10 @@
* @page: Page that is locked before this call is made
*
* Returns zero on success; non-zero otherwise
+ *
+ * This is where we encrypt the data and pass the encrypted data to
+ * the lower filesystem. In OpenPGP-compatible mode, we operate on
+ * entire underlying packets.
*/
static int ecryptfs_writepage(struct page *page, struct writeback_control *wbc)
{
@@ -481,10 +485,6 @@
* @copied: The amount of data copied
* @page: The eCryptfs page
* @fsdata: The fsdata (unused)
- *
- * This is where we encrypt the data and pass the encrypted data to
- * the lower filesystem. In OpenPGP-compatible mode, we operate on
- * entire underlying packets.
*/
static int ecryptfs_write_end(struct file *file,
struct address_space *mapping,
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 3745f7c..5c0106f 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -130,13 +130,18 @@
pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
- size_t total_remaining_bytes = ((offset + size) - pos);
+ loff_t total_remaining_bytes = ((offset + size) - pos);
+
+ if (fatal_signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes;
if (pos < offset) {
/* remaining zeros to write, up to destination offset */
- size_t total_remaining_zeros = (offset - pos);
+ loff_t total_remaining_zeros = (offset - pos);
if (num_bytes > total_remaining_zeros)
num_bytes = total_remaining_zeros;
@@ -193,15 +198,19 @@
}
pos += num_bytes;
}
- if ((offset + size) > ecryptfs_file_size) {
- i_size_write(ecryptfs_inode, (offset + size));
+ if (pos > ecryptfs_file_size) {
+ i_size_write(ecryptfs_inode, pos);
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
- rc = ecryptfs_write_inode_size_to_metadata(
+ int rc2;
+
+ rc2 = ecryptfs_write_inode_size_to_metadata(
ecryptfs_inode);
- if (rc) {
+ if (rc2) {
printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; "
- "rc = [%d]\n", rc);
+ "rc = [%d]\n", rc2);
+ if (!rc)
+ rc = rc2;
goto out;
}
}
@@ -273,76 +282,3 @@
flush_dcache_page(page_for_ecryptfs);
return rc;
}
-
-#if 0
-/**
- * ecryptfs_read
- * @data: The virtual address into which to write the data read (and
- * possibly decrypted) from the lower file
- * @offset: The offset in the decrypted view of the file from which to
- * read into @data
- * @size: The number of bytes to read into @data
- * @ecryptfs_file: The eCryptfs file from which to read
- *
- * Read an arbitrary amount of data from an arbitrary location in the
- * eCryptfs page cache. This is done on an extent-by-extent basis;
- * individual extents are decrypted and read from the lower page
- * cache (via VFS reads). This function takes care of all the
- * address translation to locations in the lower filesystem.
- *
- * Returns zero on success; non-zero otherwise
- */
-int ecryptfs_read(char *data, loff_t offset, size_t size,
- struct file *ecryptfs_file)
-{
- struct inode *ecryptfs_inode = ecryptfs_file->f_dentry->d_inode;
- struct page *ecryptfs_page;
- char *ecryptfs_page_virt;
- loff_t ecryptfs_file_size = i_size_read(ecryptfs_inode);
- loff_t data_offset = 0;
- loff_t pos;
- int rc = 0;
-
- if ((offset + size) > ecryptfs_file_size) {
- rc = -EINVAL;
- printk(KERN_ERR "%s: Attempt to read data past the end of the "
- "file; offset = [%lld]; size = [%td]; "
- "ecryptfs_file_size = [%lld]\n",
- __func__, offset, size, ecryptfs_file_size);
- goto out;
- }
- pos = offset;
- while (pos < (offset + size)) {
- pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
- size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
- size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
- size_t total_remaining_bytes = ((offset + size) - pos);
-
- if (num_bytes > total_remaining_bytes)
- num_bytes = total_remaining_bytes;
- ecryptfs_page = ecryptfs_get_locked_page(ecryptfs_inode,
- ecryptfs_page_idx);
- if (IS_ERR(ecryptfs_page)) {
- rc = PTR_ERR(ecryptfs_page);
- printk(KERN_ERR "%s: Error getting page at "
- "index [%ld] from eCryptfs inode "
- "mapping; rc = [%d]\n", __func__,
- ecryptfs_page_idx, rc);
- goto out;
- }
- ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0);
- memcpy((data + data_offset),
- ((char *)ecryptfs_page_virt + start_offset_in_page),
- num_bytes);
- kunmap_atomic(ecryptfs_page_virt, KM_USER0);
- flush_dcache_page(ecryptfs_page);
- SetPageUptodate(ecryptfs_page);
- unlock_page(ecryptfs_page);
- page_cache_release(ecryptfs_page);
- pos += num_bytes;
- data_offset += num_bytes;
- }
-out:
- return rc;
-}
-#endif /* 0 */
diff --git a/fs/exec.c b/fs/exec.c
index aeb135c..92ce83a 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1071,6 +1071,21 @@
perf_event_comm(tsk);
}
+static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len)
+{
+ int i, ch;
+
+ /* Copies the binary name from after last slash */
+ for (i = 0; (ch = *(fn++)) != '\0';) {
+ if (ch == '/')
+ i = 0; /* overwrite what we wrote */
+ else
+ if (i < len - 1)
+ tcomm[i++] = ch;
+ }
+ tcomm[i] = '\0';
+}
+
int flush_old_exec(struct linux_binprm * bprm)
{
int retval;
@@ -1085,6 +1100,7 @@
set_mm_exe_file(bprm->mm, bprm->file);
+ filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm));
/*
* Release all of the old mmap stuff
*/
@@ -1116,10 +1132,6 @@
void setup_new_exec(struct linux_binprm * bprm)
{
- int i, ch;
- const char *name;
- char tcomm[sizeof(current->comm)];
-
arch_pick_mmap_layout(current->mm);
/* This is the point of no return */
@@ -1130,18 +1142,7 @@
else
set_dumpable(current->mm, suid_dumpable);
- name = bprm->filename;
-
- /* Copies the binary name from after last slash */
- for (i=0; (ch = *(name++)) != '\0';) {
- if (ch == '/')
- i = 0; /* overwrite what we wrote */
- else
- if (i < (sizeof(tcomm) - 1))
- tcomm[i++] = ch;
- }
- tcomm[i] = '\0';
- set_task_comm(current, tcomm);
+ set_task_comm(current, bprm->tcomm);
/* Set the new mm task size. We have to do that late because it may
* depend on TIF_32BIT which is only updated in flush_thread() on
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index a01cdad..eafb8d3 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -335,7 +335,7 @@
void *ebuf;
uint32_t ofs;
size_t retlen;
- int ret = -EIO;
+ int ret;
unsigned long *wordebuf;
ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen,
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
index e97404d..9c50144 100644
--- a/fs/logfs/dev_mtd.c
+++ b/fs/logfs/dev_mtd.c
@@ -152,9 +152,6 @@
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = 0;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs += mtd->erasesize;
@@ -172,9 +169,6 @@
filler_t *filler = logfs_mtd_readpage;
struct mtd_info *mtd = super->s_mtd;
- if (!mtd_can_have_bb(mtd))
- return NULL;
-
*ofs = mtd->size - mtd->erasesize;
while (mtd_block_isbad(mtd, *ofs)) {
*ofs -= mtd->erasesize;
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
index 501043e..3de7a32 100644
--- a/fs/logfs/dir.c
+++ b/fs/logfs/dir.c
@@ -71,7 +71,7 @@
static int write_inode(struct inode *inode)
{
- return __logfs_write_inode(inode, WF_LOCK);
+ return __logfs_write_inode(inode, NULL, WF_LOCK);
}
static s64 dir_seek_data(struct inode *inode, s64 pos)
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
index b548c87..3886cde 100644
--- a/fs/logfs/file.c
+++ b/fs/logfs/file.c
@@ -230,7 +230,9 @@
return ret;
mutex_lock(&inode->i_mutex);
+ logfs_get_wblocks(sb, NULL, WF_LOCK);
logfs_write_anchor(sb);
+ logfs_put_wblocks(sb, NULL, WF_LOCK);
mutex_unlock(&inode->i_mutex);
return 0;
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
index caa4419..d4efb06 100644
--- a/fs/logfs/gc.c
+++ b/fs/logfs/gc.c
@@ -367,7 +367,7 @@
int i, max_dist;
struct gc_candidate *cand = NULL, *this;
- max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+ max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS - 1);
for (i = max_dist; i >= 0; i--) {
this = first_in_list(&super->s_low_list[i]);
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
index 388df1a..a422f42 100644
--- a/fs/logfs/inode.c
+++ b/fs/logfs/inode.c
@@ -286,7 +286,7 @@
if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
return 0;
- ret = __logfs_write_inode(inode, flags);
+ ret = __logfs_write_inode(inode, NULL, flags);
LOGFS_BUG_ON(ret, inode->i_sb);
return ret;
}
@@ -363,7 +363,9 @@
static int logfs_sync_fs(struct super_block *sb, int wait)
{
+ logfs_get_wblocks(sb, NULL, WF_LOCK);
logfs_write_anchor(sb);
+ logfs_put_wblocks(sb, NULL, WF_LOCK);
return 0;
}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
index 9da2970..1e1c369 100644
--- a/fs/logfs/journal.c
+++ b/fs/logfs/journal.c
@@ -612,7 +612,6 @@
if (len == 0)
return logfs_write_header(super, header, 0, type);
- BUG_ON(len > sb->s_blocksize);
compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
if (compr_len < 0 || type == JE_ANCHOR) {
memcpy(data, buf, len);
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
index 9263738..5f09376 100644
--- a/fs/logfs/logfs.h
+++ b/fs/logfs/logfs.h
@@ -528,7 +528,7 @@
void logfs_set_blocks(struct inode *inode, u64 no);
/* these logically belong into inode.c but actually reside in readwrite.c */
int logfs_read_inode(struct inode *inode);
-int __logfs_write_inode(struct inode *inode, long flags);
+int __logfs_write_inode(struct inode *inode, struct page *, long flags);
void logfs_evict_inode(struct inode *inode);
/* journal.c */
@@ -577,6 +577,8 @@
__be64 *array, int page_is_empty);
int logfs_exist_block(struct inode *inode, u64 bix);
int get_page_reserve(struct inode *inode, struct page *page);
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock);
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock);
extern struct logfs_block_ops indirect_block_ops;
/* segment.c */
@@ -594,6 +596,7 @@
void logfs_sync_area(struct logfs_area *area);
void logfs_sync_segments(struct super_block *sb);
void freeseg(struct super_block *sb, u32 segno);
+void free_areas(struct super_block *sb);
/* area handling */
int logfs_init_areas(struct super_block *sb);
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
index 2ac4217..4153e65 100644
--- a/fs/logfs/readwrite.c
+++ b/fs/logfs/readwrite.c
@@ -244,8 +244,7 @@
* is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
* in addition to PG_locked.
*/
-static void logfs_get_wblocks(struct super_block *sb, struct page *page,
- int lock)
+void logfs_get_wblocks(struct super_block *sb, struct page *page, int lock)
{
struct logfs_super *super = logfs_super(sb);
@@ -260,8 +259,7 @@
}
}
-static void logfs_put_wblocks(struct super_block *sb, struct page *page,
- int lock)
+void logfs_put_wblocks(struct super_block *sb, struct page *page, int lock)
{
struct logfs_super *super = logfs_super(sb);
@@ -424,7 +422,7 @@
if (inode->i_ino == LOGFS_INO_MASTER)
logfs_write_anchor(inode->i_sb);
else {
- ret = __logfs_write_inode(inode, 0);
+ ret = __logfs_write_inode(inode, NULL, 0);
/* see indirect_write_block comment */
BUG_ON(ret);
}
@@ -560,8 +558,13 @@
static void indirect_free_block(struct super_block *sb,
struct logfs_block *block)
{
- ClearPagePrivate(block->page);
- block->page->private = 0;
+ struct page *page = block->page;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
__free_block(sb, block);
}
@@ -650,8 +653,11 @@
logfs_unpack_index(page->index, &bix, &level);
block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
block->page = page;
+
SetPagePrivate(page);
- page->private = (unsigned long)block;
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+
block->ops = &indirect_block_ops;
}
@@ -1570,11 +1576,15 @@
static int __logfs_delete(struct inode *inode, struct page *page)
{
long flags = WF_DELETE;
+ int err;
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
if (page->index < I0_BLOCKS)
return logfs_write_direct(inode, page, flags);
+ err = grow_inode(inode, page->index, 0);
+ if (err)
+ return err;
return logfs_write_rec(inode, page, page->index, 0, flags);
}
@@ -1623,7 +1633,7 @@
if (inode->i_ino == LOGFS_INO_MASTER)
logfs_write_anchor(inode->i_sb);
else {
- err = __logfs_write_inode(inode, flags);
+ err = __logfs_write_inode(inode, page, flags);
}
}
}
@@ -1873,7 +1883,7 @@
logfs_get_wblocks(sb, NULL, 1);
err = __logfs_truncate(inode, size);
if (!err)
- err = __logfs_write_inode(inode, 0);
+ err = __logfs_write_inode(inode, NULL, 0);
logfs_put_wblocks(sb, NULL, 1);
}
@@ -1901,8 +1911,11 @@
li->li_block = block;
block->page = NULL;
- page->private = 0;
- ClearPagePrivate(page);
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
}
static void move_inode_to_page(struct page *page, struct inode *inode)
@@ -1918,8 +1931,12 @@
BUG_ON(PagePrivate(page));
block->ops = &indirect_block_ops;
block->page = page;
- page->private = (unsigned long)block;
- SetPagePrivate(page);
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+ }
block->inode = NULL;
li->li_block = NULL;
@@ -2106,14 +2123,14 @@
ec_level);
}
-int __logfs_write_inode(struct inode *inode, long flags)
+int __logfs_write_inode(struct inode *inode, struct page *page, long flags)
{
struct super_block *sb = inode->i_sb;
int ret;
- logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+ logfs_get_wblocks(sb, page, flags & WF_LOCK);
ret = do_write_inode(inode);
- logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+ logfs_put_wblocks(sb, page, flags & WF_LOCK);
return ret;
}
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
index 9d51873..ab798ed 100644
--- a/fs/logfs/segment.c
+++ b/fs/logfs/segment.c
@@ -86,7 +86,11 @@
BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memcpy(page_address(page) + offset, buf, copylen);
- SetPagePrivate(page);
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
buf += copylen;
@@ -110,7 +114,10 @@
page = get_mapping_page(sb, index, 0);
BUG_ON(!page); /* FIXME: reserve a pool */
memset(page_address(page) + offset, 0xff, len);
- SetPagePrivate(page);
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
}
}
@@ -130,7 +137,10 @@
BUG_ON(!page); /* FIXME: reserve a pool */
SetPageUptodate(page);
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
- SetPagePrivate(page);
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ }
page_cache_release(page);
index++;
no_indizes--;
@@ -485,8 +495,12 @@
mempool_free(item, super->s_alias_pool);
}
block->page = page;
- SetPagePrivate(page);
- page->private = (unsigned long)block;
+
+ if (!PagePrivate(page)) {
+ SetPagePrivate(page);
+ page_cache_get(page);
+ set_page_private(page, (unsigned long) block);
+ }
block->ops = &indirect_block_ops;
initialize_block_counters(page, block, data, 0);
}
@@ -536,8 +550,12 @@
list_add(&item->list, &block->item_list);
}
block->page = NULL;
- ClearPagePrivate(page);
- page->private = 0;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ set_page_private(page, 0);
+ }
block->ops = &btree_block_ops;
err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
block);
@@ -702,7 +720,10 @@
page = find_get_page(mapping, ofs >> PAGE_SHIFT);
if (!page)
continue;
- ClearPagePrivate(page);
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ }
page_cache_release(page);
}
}
@@ -841,6 +862,16 @@
kfree(area);
}
+void free_areas(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ for_each_area(i)
+ free_area(super->s_area[i]);
+ free_area(super->s_journal_area);
+}
+
static struct logfs_area *alloc_area(struct super_block *sb)
{
struct logfs_area *area;
@@ -923,10 +954,6 @@
void logfs_cleanup_areas(struct super_block *sb)
{
struct logfs_super *super = logfs_super(sb);
- int i;
btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
- for_each_area(i)
- free_area(super->s_area[i]);
- free_area(super->s_journal_area);
}
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
index e795c234..c9ee7f5 100644
--- a/fs/logfs/super.c
+++ b/fs/logfs/super.c
@@ -486,14 +486,15 @@
/* Alias entries slow down mount, so evict as many as possible */
sync_filesystem(sb);
logfs_write_anchor(sb);
+ free_areas(sb);
/*
* From this point on alias entries are simply dropped - and any
* writes to the object store are considered bugs.
*/
- super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
log_super("LogFS: Now in shutdown\n");
generic_shutdown_super(sb);
+ super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 9cde9edf..d4548dd 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -198,26 +198,6 @@
return result;
}
-static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
-{
- struct mm_struct *mm;
- int err;
-
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
- if (err)
- return ERR_PTR(err);
-
- mm = get_task_mm(task);
- if (mm && mm != current->mm &&
- !ptrace_may_access(task, mode)) {
- mmput(mm);
- mm = ERR_PTR(-EACCES);
- }
- mutex_unlock(&task->signal->cred_guard_mutex);
-
- return mm;
-}
-
struct mm_struct *mm_for_maps(struct task_struct *task)
{
return mm_access(task, PTRACE_MODE_READ);
@@ -711,6 +691,13 @@
if (IS_ERR(mm))
return PTR_ERR(mm);
+ if (mm) {
+ /* ensure this mm_struct can't be freed */
+ atomic_inc(&mm->mm_count);
+ /* but do not pin its memory */
+ mmput(mm);
+ }
+
/* OK to pass negative loff_t, we can catch out-of-range */
file->f_mode |= FMODE_UNSIGNED_OFFSET;
file->private_data = mm;
@@ -718,57 +705,13 @@
return 0;
}
-static ssize_t mem_read(struct file * file, char __user * buf,
- size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos, int write)
{
- int ret;
- char *page;
- unsigned long src = *ppos;
struct mm_struct *mm = file->private_data;
-
- if (!mm)
- return 0;
-
- page = (char *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- return -ENOMEM;
-
- ret = 0;
-
- while (count > 0) {
- int this_len, retval;
-
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- retval = access_remote_vm(mm, src, page, this_len, 0);
- if (!retval) {
- if (!ret)
- ret = -EIO;
- break;
- }
-
- if (copy_to_user(buf, page, retval)) {
- ret = -EFAULT;
- break;
- }
-
- ret += retval;
- src += retval;
- buf += retval;
- count -= retval;
- }
- *ppos = src;
-
- free_page((unsigned long) page);
- return ret;
-}
-
-static ssize_t mem_write(struct file * file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- int copied;
+ unsigned long addr = *ppos;
+ ssize_t copied;
char *page;
- unsigned long dst = *ppos;
- struct mm_struct *mm = file->private_data;
if (!mm)
return 0;
@@ -778,31 +721,54 @@
return -ENOMEM;
copied = 0;
- while (count > 0) {
- int this_len, retval;
+ if (!atomic_inc_not_zero(&mm->mm_users))
+ goto free;
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- if (copy_from_user(page, buf, this_len)) {
+ while (count > 0) {
+ int this_len = min_t(int, count, PAGE_SIZE);
+
+ if (write && copy_from_user(page, buf, this_len)) {
copied = -EFAULT;
break;
}
- retval = access_remote_vm(mm, dst, page, this_len, 1);
- if (!retval) {
+
+ this_len = access_remote_vm(mm, addr, page, this_len, write);
+ if (!this_len) {
if (!copied)
copied = -EIO;
break;
}
- copied += retval;
- buf += retval;
- dst += retval;
- count -= retval;
- }
- *ppos = dst;
+ if (!write && copy_to_user(buf, page, this_len)) {
+ copied = -EFAULT;
+ break;
+ }
+
+ buf += this_len;
+ addr += this_len;
+ copied += this_len;
+ count -= this_len;
+ }
+ *ppos = addr;
+
+ mmput(mm);
+free:
free_page((unsigned long) page);
return copied;
}
+static ssize_t mem_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, buf, count, ppos, 0);
+}
+
+static ssize_t mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
+
loff_t mem_lseek(struct file *file, loff_t offset, int orig)
{
switch (orig) {
@@ -822,8 +788,8 @@
static int mem_release(struct inode *inode, struct file *file)
{
struct mm_struct *mm = file->private_data;
-
- mmput(mm);
+ if (mm)
+ mmdrop(mm);
return 0;
}
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 62f4fb3..00012e3 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -493,6 +493,12 @@
const void *ns = NULL;
int err;
+ if (!dir_sd) {
+ WARN(1, KERN_ERR "sysfs: kobject %s without dirent\n",
+ kobject_name(kobj));
+ return -ENOENT;
+ }
+
err = 0;
if (!sysfs_ns_type(dir_sd))
goto out;
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 4a802b4..85eb816 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -318,8 +318,11 @@
struct sysfs_addrm_cxt acxt;
struct sysfs_dirent *sd;
- if (!dir_sd)
+ if (!dir_sd) {
+ WARN(1, KERN_WARNING "sysfs: can not remove '%s', no directory\n",
+ name);
return -ENOENT;
+ }
sysfs_addrm_start(&acxt, dir_sd);
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 0cf52da..ebdb888 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -131,7 +131,8 @@
__func__, (unsigned long long) ip->i_ino,
(long long) pathlen);
ASSERT(0);
- return XFS_ERROR(EFSCORRUPTED);
+ error = XFS_ERROR(EFSCORRUPTED);
+ goto out;
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 76caa67..92f0981 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1328,6 +1328,7 @@
struct drm_file *file_priv);
extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
/* Cache management (drm_cache.c) */
void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index fd88a39..0092102 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -18,7 +18,7 @@
#define BINPRM_BUF_SIZE 128
#ifdef __KERNEL__
-#include <linux/list.h>
+#include <linux/sched.h>
#define CORENAME_MAX_SIZE 128
@@ -58,6 +58,7 @@
unsigned interp_flags;
unsigned interp_data;
unsigned long loader, exec;
+ char tcomm[TASK_COMM_LEN];
};
#define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 0ab54e1..d09af4b 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -39,6 +39,7 @@
extern int freeze_processes(void);
extern int freeze_kernel_threads(void);
extern void thaw_processes(void);
+extern void thaw_kernel_threads(void);
static inline bool try_to_freeze(void)
{
@@ -174,6 +175,7 @@
static inline int freeze_processes(void) { return -ENOSYS; }
static inline int freeze_kernel_threads(void) { return -ENOSYS; }
static inline void thaw_processes(void) {}
+static inline void thaw_kernel_threads(void) {}
static inline bool try_to_freeze(void) { return false; }
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index b5ca4b2..004ff33 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -1,6 +1,8 @@
#ifndef _GPIO_KEYS_H
#define _GPIO_KEYS_H
+struct device;
+
struct gpio_keys_button {
/* Configuration parameters */
unsigned int code; /* input event code (KEY_*, SW_*) */
diff --git a/include/linux/lp8727.h b/include/linux/lp8727.h
old mode 100755
new mode 100644
diff --git a/include/linux/mfd/mcp.h b/include/linux/mfd/mcp.h
index 1515e64..f88c1cc 100644
--- a/include/linux/mfd/mcp.h
+++ b/include/linux/mfd/mcp.h
@@ -10,7 +10,6 @@
#ifndef MCP_H
#define MCP_H
-#include <linux/mod_devicetable.h>
#include <mach/dma.h>
struct mcp_ops;
@@ -27,7 +26,7 @@
dma_device_t dma_telco_rd;
dma_device_t dma_telco_wr;
struct device attached_device;
- const char *codec;
+ int gpio_base;
};
struct mcp_ops {
@@ -45,11 +44,10 @@
unsigned int mcp_reg_read(struct mcp *, unsigned int);
void mcp_enable(struct mcp *);
void mcp_disable(struct mcp *);
-const struct mcp_device_id *mcp_get_device_id(const struct mcp *mcp);
#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
struct mcp *mcp_host_alloc(struct device *, size_t);
-int mcp_host_register(struct mcp *, void *);
+int mcp_host_register(struct mcp *);
void mcp_host_unregister(struct mcp *);
struct mcp_driver {
@@ -58,7 +56,6 @@
void (*remove)(struct mcp *);
int (*suspend)(struct mcp *, pm_message_t);
int (*resume)(struct mcp *);
- const struct mcp_device_id *id_table;
};
int mcp_driver_register(struct mcp_driver *);
@@ -67,6 +64,9 @@
#define mcp_get_drvdata(mcp) dev_get_drvdata(&(mcp)->attached_device)
#define mcp_set_drvdata(mcp,d) dev_set_drvdata(&(mcp)->attached_device, d)
-#define mcp_priv(mcp) ((void *)((mcp)+1))
+static inline void *mcp_priv(struct mcp *mcp)
+{
+ return mcp + 1;
+}
#endif
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
index bc19e5f..4321f04 100644
--- a/include/linux/mfd/ucb1x00.h
+++ b/include/linux/mfd/ucb1x00.h
@@ -104,9 +104,6 @@
#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
#define UCB_MODE_AUD_OFF_CAN (1 << 13)
-struct ucb1x00_plat_data {
- int gpio_base;
-};
struct ucb1x00_irq {
void *devid;
@@ -119,7 +116,7 @@
unsigned int irq;
struct semaphore adc_sem;
spinlock_t io_lock;
- const struct mcp_device_id *id;
+ u16 id;
u16 io_dir;
u16 io_out;
u16 adc_cr;
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index b29e7f6..83ac071 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -436,17 +436,6 @@
__attribute__((aligned(sizeof(kernel_ulong_t))));
};
-/* mcp */
-
-#define MCP_NAME_SIZE 20
-#define MCP_MODULE_PREFIX "mcp:"
-
-struct mcp_device_id {
- char name[MCP_NAME_SIZE];
- kernel_ulong_t driver_data /* Data private to the driver */
- __attribute__((aligned(sizeof(kernel_ulong_t))));
-};
-
/* dmi */
enum dmi_field {
DMI_NONE,
diff --git a/include/linux/mpi.h b/include/linux/mpi.h
index 06f8899..d02cca6 100644
--- a/include/linux/mpi.h
+++ b/include/linux/mpi.h
@@ -57,8 +57,6 @@
typedef struct gcry_mpi *MPI;
-#define MPI_NULL NULL
-
#define mpi_get_nlimbs(a) ((a)->nlimbs)
#define mpi_is_neg(a) ((a)->sign)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 1a81fde..d43dc25 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -427,9 +427,7 @@
static inline int mtd_suspend(struct mtd_info *mtd)
{
- if (!mtd->suspend)
- return -EOPNOTSUPP;
- return mtd->suspend(mtd);
+ return mtd->suspend ? mtd->suspend(mtd) : 0;
}
static inline void mtd_resume(struct mtd_info *mtd)
@@ -441,7 +439,7 @@
static inline int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
if (!mtd->block_isbad)
- return -EOPNOTSUPP;
+ return 0;
return mtd->block_isbad(mtd, ofs);
}
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 0885561..abb2776 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -587,6 +587,7 @@
u64 sample_period;
u64 last_period;
local64_t period_left;
+ u64 interrupts_seq;
u64 interrupts;
u64 freq_time_stamp;
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index e5bbcba..4d99e4e 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -110,7 +110,19 @@
{ return; }
static inline int pm_qos_request(int pm_qos_class)
- { return 0; }
+{
+ switch (pm_qos_class) {
+ case PM_QOS_CPU_DMA_LATENCY:
+ return PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+ case PM_QOS_NETWORK_LATENCY:
+ return PM_QOS_NETWORK_LAT_DEFAULT_VALUE;
+ case PM_QOS_NETWORK_THROUGHPUT:
+ return PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE;
+ default:
+ return PM_QOS_DEFAULT_VALUE;
+ }
+}
+
static inline int pm_qos_add_notifier(int pm_qos_class,
struct notifier_block *notifier)
{ return 0; }
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 513f524..7d379a6 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2090,7 +2090,7 @@
* is_idle_task - is the specified task an idle task?
* @p: the task in question.
*/
-static inline bool is_idle_task(struct task_struct *p)
+static inline bool is_idle_task(const struct task_struct *p)
{
return p->pid == 0;
}
@@ -2259,6 +2259,12 @@
extern void mmput(struct mm_struct *);
/* Grab a reference to a task's mm, if it is not already going away */
extern struct mm_struct *get_task_mm(struct task_struct *task);
+/*
+ * Grab a reference to a task's mm, if it is not already going away
+ * and ptrace_may_access with the mode parameter passed to it
+ * succeeds.
+ */
+extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode);
/* Remove the current tasks stale references to the old mm_struct */
extern void mm_release(struct task_struct *, struct mm_struct *);
/* Allocate a new mm structure and copy contents from tsk->mm */
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 8cd7fe5..425450b 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -70,6 +70,7 @@
unsigned int needs_tend_set:1;
unsigned int no_dmars:1;
unsigned int chclr_present:1;
+ unsigned int slave_only:1;
};
/* DMA register */
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
deleted file mode 100644
index 20f63d3..0000000
--- a/include/linux/sysdev.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- * System devices follow a slightly different driver model.
- * They don't need to do dynammic driver binding, can't be probed,
- * and don't reside on any type of peripheral bus.
- * So, we represent and treat them a little differently.
- *
- * We still have a notion of a driver for a system device, because we still
- * want to perform basic operations on these devices.
- *
- * We also support auxiliary drivers binding to devices of a certain class.
- *
- * This allows configurable drivers to register themselves for devices of
- * a certain type. And, it allows class definitions to reside in generic
- * code while arch-specific code can register specific drivers.
- *
- * Auxiliary drivers registered with a NULL cls are registered as drivers
- * for all system devices, and get notification calls for each device.
- */
-
-
-#ifndef _SYSDEV_H_
-#define _SYSDEV_H_
-
-#include <linux/kobject.h>
-#include <linux/pm.h>
-
-
-struct sys_device;
-struct sysdev_class_attribute;
-
-struct sysdev_class {
- const char *name;
- struct list_head drivers;
- struct sysdev_class_attribute **attrs;
- struct kset kset;
-};
-
-struct sysdev_class_attribute {
- struct attribute attr;
- ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
- char *);
- ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
- const char *, size_t);
-};
-
-#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
-{ \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-}
-
-#define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
- struct sysdev_class_attribute attr_##_name = \
- _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
-
-
-extern int sysdev_class_register(struct sysdev_class *);
-extern void sysdev_class_unregister(struct sysdev_class *);
-
-extern int sysdev_class_create_file(struct sysdev_class *,
- struct sysdev_class_attribute *);
-extern void sysdev_class_remove_file(struct sysdev_class *,
- struct sysdev_class_attribute *);
-/**
- * Auxiliary system device drivers.
- */
-
-struct sysdev_driver {
- struct list_head entry;
- int (*add)(struct sys_device *);
- int (*remove)(struct sys_device *);
-};
-
-
-extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
-extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
-
-
-/**
- * sys_devices can be simplified a lot from regular devices, because they're
- * simply not as versatile.
- */
-
-struct sys_device {
- u32 id;
- struct sysdev_class * cls;
- struct kobject kobj;
-};
-
-extern int sysdev_register(struct sys_device *);
-extern void sysdev_unregister(struct sys_device *);
-
-
-struct sysdev_attribute {
- struct attribute attr;
- ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
- ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
- const char *, size_t);
-};
-
-
-#define _SYSDEV_ATTR(_name, _mode, _show, _store) \
-{ \
- .attr = { .name = __stringify(_name), .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-}
-
-#define SYSDEV_ATTR(_name, _mode, _show, _store) \
- struct sysdev_attribute attr_##_name = \
- _SYSDEV_ATTR(_name, _mode, _show, _store);
-
-extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
-extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
-
-/* Create/remove NULL terminated attribute list */
-static inline int
-sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
-{
- return sysfs_create_files(&d->kobj, (const struct attribute **)a);
-}
-
-static inline void
-sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
-{
- return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
-}
-
-struct sysdev_ext_attribute {
- struct sysdev_attribute attr;
- void *var;
-};
-
-/*
- * Support for simple variable sysdev attributes.
- * The pointer to the variable is stored in a sysdev_ext_attribute
- */
-
-/* Add more types as needed */
-
-extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
- char *);
-extern ssize_t sysdev_store_ulong(struct sys_device *,
- struct sysdev_attribute *, const char *, size_t);
-extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
- char *);
-extern ssize_t sysdev_store_int(struct sys_device *,
- struct sysdev_attribute *, const char *, size_t);
-
-#define _SYSDEV_ULONG_ATTR(_name, _mode, _var) \
- { _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
- &(_var) }
-#define SYSDEV_ULONG_ATTR(_name, _mode, _var) \
- struct sysdev_ext_attribute attr_##_name = \
- _SYSDEV_ULONG_ATTR(_name, _mode, _var);
-#define _SYSDEV_INT_ATTR(_name, _mode, _var) \
- { _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
- &(_var) }
-#define SYSDEV_INT_ATTR(_name, _mode, _var) \
- struct sysdev_ext_attribute attr_##_name = \
- _SYSDEV_INT_ATTR(_name, _mode, _var);
-
-#endif /* _SYSDEV_H_ */
diff --git a/include/linux/usb/langwell_otg.h b/include/linux/usb/langwell_otg.h
deleted file mode 100644
index 51f17b1..0000000
--- a/include/linux/usb/langwell_otg.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Intel Langwell USB OTG transceiver driver
- * Copyright (C) 2008 - 2010, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#ifndef __LANGWELL_OTG_H
-#define __LANGWELL_OTG_H
-
-#include <linux/usb/intel_mid_otg.h>
-
-#define CI_USBCMD 0x30
-# define USBCMD_RST BIT(1)
-# define USBCMD_RS BIT(0)
-#define CI_USBSTS 0x34
-# define USBSTS_SLI BIT(8)
-# define USBSTS_URI BIT(6)
-# define USBSTS_PCI BIT(2)
-#define CI_PORTSC1 0x74
-# define PORTSC_PP BIT(12)
-# define PORTSC_LS (BIT(11) | BIT(10))
-# define PORTSC_SUSP BIT(7)
-# define PORTSC_CCS BIT(0)
-#define CI_HOSTPC1 0xb4
-# define HOSTPC1_PHCD BIT(22)
-#define CI_OTGSC 0xf4
-# define OTGSC_DPIE BIT(30)
-# define OTGSC_1MSE BIT(29)
-# define OTGSC_BSEIE BIT(28)
-# define OTGSC_BSVIE BIT(27)
-# define OTGSC_ASVIE BIT(26)
-# define OTGSC_AVVIE BIT(25)
-# define OTGSC_IDIE BIT(24)
-# define OTGSC_DPIS BIT(22)
-# define OTGSC_1MSS BIT(21)
-# define OTGSC_BSEIS BIT(20)
-# define OTGSC_BSVIS BIT(19)
-# define OTGSC_ASVIS BIT(18)
-# define OTGSC_AVVIS BIT(17)
-# define OTGSC_IDIS BIT(16)
-# define OTGSC_DPS BIT(14)
-# define OTGSC_1MST BIT(13)
-# define OTGSC_BSE BIT(12)
-# define OTGSC_BSV BIT(11)
-# define OTGSC_ASV BIT(10)
-# define OTGSC_AVV BIT(9)
-# define OTGSC_ID BIT(8)
-# define OTGSC_HABA BIT(7)
-# define OTGSC_HADP BIT(6)
-# define OTGSC_IDPU BIT(5)
-# define OTGSC_DP BIT(4)
-# define OTGSC_OT BIT(3)
-# define OTGSC_HAAR BIT(2)
-# define OTGSC_VC BIT(1)
-# define OTGSC_VD BIT(0)
-# define OTGSC_INTEN_MASK (0x7f << 24)
-# define OTGSC_INT_MASK (0x5f << 24)
-# define OTGSC_INTSTS_MASK (0x7f << 16)
-#define CI_USBMODE 0xf8
-# define USBMODE_CM (BIT(1) | BIT(0))
-# define USBMODE_IDLE 0
-# define USBMODE_DEVICE 0x2
-# define USBMODE_HOST 0x3
-#define USBCFG_ADDR 0xff10801c
-#define USBCFG_LEN 4
-# define USBCFG_VBUSVAL BIT(14)
-# define USBCFG_AVALID BIT(13)
-# define USBCFG_BVALID BIT(12)
-# define USBCFG_SESEND BIT(11)
-
-#define INTR_DUMMY_MASK (USBSTS_SLI | USBSTS_URI | USBSTS_PCI)
-
-enum langwell_otg_timer_type {
- TA_WAIT_VRISE_TMR,
- TA_WAIT_BCON_TMR,
- TA_AIDL_BDIS_TMR,
- TB_ASE0_BRST_TMR,
- TB_SE0_SRP_TMR,
- TB_SRP_INIT_TMR,
- TB_SRP_FAIL_TMR,
- TB_BUS_SUSPEND_TMR
-};
-
-#define TA_WAIT_VRISE 100
-#define TA_WAIT_BCON 30000
-#define TA_AIDL_BDIS 15000
-#define TB_ASE0_BRST 5000
-#define TB_SE0_SRP 2
-#define TB_SRP_INIT 100
-#define TB_SRP_FAIL 5500
-#define TB_BUS_SUSPEND 500
-
-struct langwell_otg_timer {
- unsigned long expires; /* Number of count increase to timeout */
- unsigned long count; /* Tick counter */
- void (*function)(unsigned long); /* Timeout function */
- unsigned long data; /* Data passed to function */
- struct list_head list;
-};
-
-struct langwell_otg {
- struct intel_mid_otg_xceiv iotg;
- struct device *dev;
-
- void __iomem *usbcfg; /* SCCBUSB config Reg */
-
- unsigned region;
- unsigned cfg_region;
-
- struct work_struct work;
- struct workqueue_struct *qwork;
- struct timer_list hsm_timer;
-
- spinlock_t lock;
- spinlock_t wq_lock;
-
- struct notifier_block iotg_notifier;
-};
-
-static inline
-struct langwell_otg *mid_xceiv_to_lnw(struct intel_mid_otg_xceiv *iotg)
-{
- return container_of(iotg, struct langwell_otg, iotg);
-}
-
-#endif /* __LANGWELL_OTG_H__ */
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
index 3419bf5..d55f434 100644
--- a/include/net/netns/generic.h
+++ b/include/net/netns/generic.h
@@ -41,6 +41,7 @@
ptr = ng->ptr[id - 1];
rcu_read_unlock();
+ BUG_ON(!ptr);
return ptr;
}
#endif
diff --git a/include/net/sock.h b/include/net/sock.h
index 4c69ac1..91c1c8b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -55,6 +55,7 @@
#include <linux/uaccess.h>
#include <linux/memcontrol.h>
#include <linux/res_counter.h>
+#include <linux/jump_label.h>
#include <linux/filter.h>
#include <linux/rculist_nulls.h>
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 0118ea9..d49db01 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -311,6 +311,8 @@
#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
+extern void tcp_init_mem(struct net *net);
+
extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how);
diff --git a/include/sound/core.h b/include/sound/core.h
index 5ab255f..cea1b54 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -417,6 +417,7 @@
#define gameport_get_port_data(gp) (gp)->port_data
#endif
+#ifdef CONFIG_PCI
/* PCI quirk list helper */
struct snd_pci_quirk {
unsigned short subvendor; /* PCI subvendor ID */
@@ -456,5 +457,6 @@
const struct snd_pci_quirk *
snd_pci_quirk_lookup_id(u16 vendor, u16 device,
const struct snd_pci_quirk *list);
+#endif
#endif /* __SOUND_CORE_H */
diff --git a/kernel/events/callchain.c b/kernel/events/callchain.c
index 057e24b..6581a04 100644
--- a/kernel/events/callchain.c
+++ b/kernel/events/callchain.c
@@ -115,8 +115,6 @@
}
err = alloc_callchain_buffers();
- if (err)
- release_callchain_buffers();
exit:
mutex_unlock(&callchain_mutex);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a8f4ac0..ba36013 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -815,7 +815,7 @@
* here.
*/
if (is_cgroup_event(event))
- run_end = perf_event_time(event);
+ run_end = perf_cgroup_event_time(event);
else if (ctx->is_active)
run_end = ctx->time;
else
@@ -2300,6 +2300,9 @@
return div64_u64(dividend, divisor);
}
+static DEFINE_PER_CPU(int, perf_throttled_count);
+static DEFINE_PER_CPU(u64, perf_throttled_seq);
+
static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count)
{
struct hw_perf_event *hwc = &event->hw;
@@ -2325,16 +2328,29 @@
}
}
-static void perf_ctx_adjust_freq(struct perf_event_context *ctx, u64 period)
+/*
+ * combine freq adjustment with unthrottling to avoid two passes over the
+ * events. At the same time, make sure, having freq events does not change
+ * the rate of unthrottling as that would introduce bias.
+ */
+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx,
+ int needs_unthr)
{
struct perf_event *event;
struct hw_perf_event *hwc;
- u64 interrupts, now;
+ u64 now, period = TICK_NSEC;
s64 delta;
- if (!ctx->nr_freq)
+ /*
+ * only need to iterate over all events iff:
+ * - context have events in frequency mode (needs freq adjust)
+ * - there are events to unthrottle on this cpu
+ */
+ if (!(ctx->nr_freq || needs_unthr))
return;
+ raw_spin_lock(&ctx->lock);
+
list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
if (event->state != PERF_EVENT_STATE_ACTIVE)
continue;
@@ -2344,13 +2360,8 @@
hwc = &event->hw;
- interrupts = hwc->interrupts;
- hwc->interrupts = 0;
-
- /*
- * unthrottle events on the tick
- */
- if (interrupts == MAX_INTERRUPTS) {
+ if (needs_unthr && hwc->interrupts == MAX_INTERRUPTS) {
+ hwc->interrupts = 0;
perf_log_throttle(event, 1);
event->pmu->start(event, 0);
}
@@ -2358,14 +2369,26 @@
if (!event->attr.freq || !event->attr.sample_freq)
continue;
- event->pmu->read(event);
+ /*
+ * stop the event and update event->count
+ */
+ event->pmu->stop(event, PERF_EF_UPDATE);
+
now = local64_read(&event->count);
delta = now - hwc->freq_count_stamp;
hwc->freq_count_stamp = now;
+ /*
+ * restart the event
+ * reload only if value has changed
+ */
if (delta > 0)
perf_adjust_period(event, period, delta);
+
+ event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0);
}
+
+ raw_spin_unlock(&ctx->lock);
}
/*
@@ -2388,16 +2411,13 @@
*/
static void perf_rotate_context(struct perf_cpu_context *cpuctx)
{
- u64 interval = (u64)cpuctx->jiffies_interval * TICK_NSEC;
struct perf_event_context *ctx = NULL;
- int rotate = 0, remove = 1, freq = 0;
+ int rotate = 0, remove = 1;
if (cpuctx->ctx.nr_events) {
remove = 0;
if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active)
rotate = 1;
- if (cpuctx->ctx.nr_freq)
- freq = 1;
}
ctx = cpuctx->task_ctx;
@@ -2405,37 +2425,26 @@
remove = 0;
if (ctx->nr_events != ctx->nr_active)
rotate = 1;
- if (ctx->nr_freq)
- freq = 1;
}
- if (!rotate && !freq)
+ if (!rotate)
goto done;
perf_ctx_lock(cpuctx, cpuctx->task_ctx);
perf_pmu_disable(cpuctx->ctx.pmu);
- if (freq) {
- perf_ctx_adjust_freq(&cpuctx->ctx, interval);
- if (ctx)
- perf_ctx_adjust_freq(ctx, interval);
- }
+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
+ if (ctx)
+ ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
- if (rotate) {
- cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
- if (ctx)
- ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE);
+ rotate_ctx(&cpuctx->ctx);
+ if (ctx)
+ rotate_ctx(ctx);
- rotate_ctx(&cpuctx->ctx);
- if (ctx)
- rotate_ctx(ctx);
-
- perf_event_sched_in(cpuctx, ctx, current);
- }
+ perf_event_sched_in(cpuctx, ctx, current);
perf_pmu_enable(cpuctx->ctx.pmu);
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
-
done:
if (remove)
list_del_init(&cpuctx->rotation_list);
@@ -2445,10 +2454,22 @@
{
struct list_head *head = &__get_cpu_var(rotation_list);
struct perf_cpu_context *cpuctx, *tmp;
+ struct perf_event_context *ctx;
+ int throttled;
WARN_ON(!irqs_disabled());
+ __this_cpu_inc(perf_throttled_seq);
+ throttled = __this_cpu_xchg(perf_throttled_count, 0);
+
list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) {
+ ctx = &cpuctx->ctx;
+ perf_adjust_freq_unthr_context(ctx, throttled);
+
+ ctx = cpuctx->task_ctx;
+ if (ctx)
+ perf_adjust_freq_unthr_context(ctx, throttled);
+
if (cpuctx->jiffies_interval == 1 ||
!(jiffies % cpuctx->jiffies_interval))
perf_rotate_context(cpuctx);
@@ -4509,6 +4530,7 @@
{
int events = atomic_read(&event->event_limit);
struct hw_perf_event *hwc = &event->hw;
+ u64 seq;
int ret = 0;
/*
@@ -4518,14 +4540,20 @@
if (unlikely(!is_sampling_event(event)))
return 0;
- if (unlikely(hwc->interrupts >= max_samples_per_tick)) {
- if (throttle) {
+ seq = __this_cpu_read(perf_throttled_seq);
+ if (seq != hwc->interrupts_seq) {
+ hwc->interrupts_seq = seq;
+ hwc->interrupts = 1;
+ } else {
+ hwc->interrupts++;
+ if (unlikely(throttle
+ && hwc->interrupts >= max_samples_per_tick)) {
+ __this_cpu_inc(perf_throttled_count);
hwc->interrupts = MAX_INTERRUPTS;
perf_log_throttle(event, 0);
ret = 1;
}
- } else
- hwc->interrupts++;
+ }
if (event->attr.freq) {
u64 now = perf_clock();
diff --git a/kernel/exit.c b/kernel/exit.c
index 294b170..4b4042f 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1038,6 +1038,22 @@
if (tsk->nr_dirtied)
__this_cpu_add(dirty_throttle_leaks, tsk->nr_dirtied);
exit_rcu();
+
+ /*
+ * The setting of TASK_RUNNING by try_to_wake_up() may be delayed
+ * when the following two conditions become true.
+ * - There is race condition of mmap_sem (It is acquired by
+ * exit_mm()), and
+ * - SMI occurs before setting TASK_RUNINNG.
+ * (or hypervisor of virtual machine switches to other guest)
+ * As a result, we may become TASK_RUNNING after becoming TASK_DEAD
+ *
+ * To avoid it, we have to wait for releasing tsk->pi_lock which
+ * is held by try_to_wake_up()
+ */
+ smp_mb();
+ raw_spin_unlock_wait(&tsk->pi_lock);
+
/* causes final put_task_struct in finish_task_switch(). */
tsk->state = TASK_DEAD;
tsk->flags |= PF_NOFREEZE; /* tell freezer to ignore us */
diff --git a/kernel/fork.c b/kernel/fork.c
index 051f090..1b2ef3c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -647,6 +647,26 @@
}
EXPORT_SYMBOL_GPL(get_task_mm);
+struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
+{
+ struct mm_struct *mm;
+ int err;
+
+ err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+ if (err)
+ return ERR_PTR(err);
+
+ mm = get_task_mm(task);
+ if (mm && mm != current->mm &&
+ !ptrace_may_access(task, mode)) {
+ mmput(mm);
+ mm = ERR_PTR(-EACCES);
+ }
+ mutex_unlock(&task->signal->cred_guard_mutex);
+
+ return mm;
+}
+
/* Please note the differences between mmput and mm_release.
* mmput is called whenever we stop holding onto a mm_struct,
* error success whatever.
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 29f5b65..9788c0e 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1673,8 +1673,12 @@
ri->rp = rp;
ri->task = current;
- if (rp->entry_handler && rp->entry_handler(ri, regs))
+ if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+ raw_spin_lock_irqsave(&rp->lock, flags);
+ hlist_add_head(&ri->hlist, &rp->free_instances);
+ raw_spin_unlock_irqrestore(&rp->lock, flags);
return 0;
+ }
arch_prepare_kretprobe(ri, regs);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index 0c4defe..21724ee 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -231,8 +231,28 @@
#ifdef CONFIG_SUSPEND_FREEZER
static inline int suspend_freeze_processes(void)
{
- int error = freeze_processes();
- return error ? : freeze_kernel_threads();
+ int error;
+
+ error = freeze_processes();
+
+ /*
+ * freeze_processes() automatically thaws every task if freezing
+ * fails. So we need not do anything extra upon error.
+ */
+ if (error)
+ goto Finish;
+
+ error = freeze_kernel_threads();
+
+ /*
+ * freeze_kernel_threads() thaws only kernel threads upon freezing
+ * failure. So we have to thaw the userspace tasks ourselves.
+ */
+ if (error)
+ thaw_processes();
+
+ Finish:
+ return error;
}
static inline void suspend_thaw_processes(void)
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 77274c9..7e42645 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -143,7 +143,10 @@
/**
* freeze_kernel_threads - Make freezable kernel threads go to the refrigerator.
*
- * On success, returns 0. On failure, -errno and system is fully thawed.
+ * On success, returns 0. On failure, -errno and only the kernel threads are
+ * thawed, so as to give a chance to the caller to do additional cleanups
+ * (if any) before thawing the userspace tasks. So, it is the responsibility
+ * of the caller to thaw the userspace tasks, when the time is right.
*/
int freeze_kernel_threads(void)
{
@@ -159,7 +162,7 @@
BUG_ON(in_atomic());
if (error)
- thaw_processes();
+ thaw_kernel_threads();
return error;
}
@@ -188,3 +191,22 @@
printk("done.\n");
}
+void thaw_kernel_threads(void)
+{
+ struct task_struct *g, *p;
+
+ pm_nosig_freezing = false;
+ printk("Restarting kernel threads ... ");
+
+ thaw_workqueues();
+
+ read_lock(&tasklist_lock);
+ do_each_thread(g, p) {
+ if (p->flags & (PF_KTHREAD | PF_WQ_WORKER))
+ __thaw_task(p);
+ } while_each_thread(g, p);
+ read_unlock(&tasklist_lock);
+
+ schedule();
+ printk("done.\n");
+}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 6b1ab7a..3e10007 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -249,13 +249,15 @@
}
pm_restore_gfp_mask();
error = hibernation_snapshot(data->platform_support);
- if (!error) {
+ if (error) {
+ thaw_kernel_threads();
+ } else {
error = put_user(in_suspend, (int __user *)arg);
if (!error && !freezer_test_done)
data->ready = 1;
if (freezer_test_done) {
freezer_test_done = false;
- thaw_processes();
+ thaw_kernel_threads();
}
}
break;
@@ -274,6 +276,15 @@
swsusp_free();
memset(&data->handle, 0, sizeof(struct snapshot_handle));
data->ready = 0;
+ /*
+ * It is necessary to thaw kernel threads here, because
+ * SNAPSHOT_CREATE_IMAGE may be invoked directly after
+ * SNAPSHOT_FREE. In that case, if kernel threads were not
+ * thawed, the preallocation of memory carried out by
+ * hibernation_snapshot() might run into problems (i.e. it
+ * might fail or even deadlock).
+ */
+ thaw_kernel_threads();
break;
case SNAPSHOT_PREF_IMAGE_SIZE:
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 88f17b8..a58ac28 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -56,8 +56,8 @@
static int nfakewriters = 4; /* # fake writer threads */
static int stat_interval; /* Interval between stats, in seconds. */
/* Defaults to "only at end of test". */
-static int verbose; /* Print more debug info. */
-static int test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
+static bool verbose; /* Print more debug info. */
+static bool test_no_idle_hz; /* Test RCU's support for tickless idle CPUs. */
static int shuffle_interval = 3; /* Interval between shuffles (in sec)*/
static int stutter = 5; /* Start/stop testing interval (in sec) */
static int irqreader = 1; /* RCU readers from irq (timers). */
@@ -1399,7 +1399,7 @@
* Execute random CPU-hotplug operations at the interval specified
* by the onoff_interval.
*/
-static int
+static int __cpuinit
rcu_torture_onoff(void *arg)
{
int cpu;
@@ -1447,7 +1447,7 @@
return 0;
}
-static int
+static int __cpuinit
rcu_torture_onoff_init(void)
{
if (onoff_interval <= 0)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index df00cb0..5255c9d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -74,6 +74,7 @@
#include <asm/tlb.h>
#include <asm/irq_regs.h>
+#include <asm/mutex.h>
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
@@ -723,9 +724,6 @@
p->sched_class->dequeue_task(rq, p, flags);
}
-/*
- * activate_task - move a task to the runqueue.
- */
void activate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
@@ -734,9 +732,6 @@
enqueue_task(rq, p, flags);
}
-/*
- * deactivate_task - remove a task from the runqueue.
- */
void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
{
if (task_contributes_to_load(p))
@@ -4134,7 +4129,7 @@
on_rq = p->on_rq;
running = task_current(rq, p);
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
if (running)
p->sched_class->put_prev_task(rq, p);
@@ -4147,7 +4142,7 @@
if (running)
p->sched_class->set_curr_task(rq);
if (on_rq)
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
check_class_changed(rq, p, prev_class, oldprio);
task_rq_unlock(rq, p, &flags);
@@ -4998,9 +4993,9 @@
* placed properly.
*/
if (p->on_rq) {
- deactivate_task(rq_src, p, 0);
+ dequeue_task(rq_src, p, 0);
set_task_cpu(p, dest_cpu);
- activate_task(rq_dest, p, 0);
+ enqueue_task(rq_dest, p, 0);
check_preempt_curr(rq_dest, p, 0);
}
done:
@@ -7032,10 +7027,10 @@
on_rq = p->on_rq;
if (on_rq)
- deactivate_task(rq, p, 0);
+ dequeue_task(rq, p, 0);
__setscheduler(rq, p, SCHED_NORMAL, 0);
if (on_rq) {
- activate_task(rq, p, 0);
+ enqueue_task(rq, p, 0);
resched_task(rq->curr);
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 84adb2d..7c6414f 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4866,6 +4866,15 @@
return;
}
+static inline void clear_nohz_tick_stopped(int cpu)
+{
+ if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
+ cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
+ atomic_dec(&nohz.nr_cpus);
+ clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
+ }
+}
+
static inline void set_cpu_sd_state_busy(void)
{
struct sched_domain *sd;
@@ -4904,6 +4913,12 @@
{
int cpu = smp_processor_id();
+ /*
+ * If this cpu is going down, then nothing needs to be done.
+ */
+ if (!cpu_active(cpu))
+ return;
+
if (stop_tick) {
if (test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))
return;
@@ -4914,6 +4929,18 @@
}
return;
}
+
+static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_DYING:
+ clear_nohz_tick_stopped(smp_processor_id());
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+}
#endif
static DEFINE_SPINLOCK(balancing);
@@ -5070,11 +5097,7 @@
* busy tick after returning from idle, we will update the busy stats.
*/
set_cpu_sd_state_busy();
- if (unlikely(test_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu)))) {
- clear_bit(NOHZ_TICK_STOPPED, nohz_flags(cpu));
- cpumask_clear_cpu(cpu, nohz.idle_cpus_mask);
- atomic_dec(&nohz.nr_cpus);
- }
+ clear_nohz_tick_stopped(cpu);
/*
* None are in tickless mode and hence no need for NOHZ idle load
@@ -5590,6 +5613,7 @@
#ifdef CONFIG_NO_HZ
zalloc_cpumask_var(&nohz.idle_cpus_mask, GFP_NOWAIT);
+ cpu_notifier(sched_ilb_notifier, 0);
#endif
#endif /* SMP */
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 3640ebb..f42ae7f 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1587,6 +1587,11 @@
if (!next_task)
return 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ if (unlikely(task_running(rq, next_task)))
+ return 0;
+#endif
+
retry:
if (unlikely(next_task == rq->curr)) {
WARN_ON(1);
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 1d7bca7..d117262 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -296,7 +296,7 @@
if (__this_cpu_read(soft_watchdog_warn) == true)
return HRTIMER_RESTART;
- printk(KERN_ERR "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
+ printk(KERN_EMERG "BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
smp_processor_id(), duration,
current->comm, task_pid_nr(current));
print_modules();
diff --git a/lib/Kconfig b/lib/Kconfig
index 169eb7c..d69d321 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -279,6 +279,9 @@
If unsure, say N.
+config CLZ_TAB
+ bool
+
config CORDIC
tristate "CORDIC algorithm"
help
@@ -287,6 +290,7 @@
config MPILIB
tristate
+ select CLZ_TAB
help
Multiprecision maths library from GnuPG.
It is used to implement RSA digital signature verification,
diff --git a/lib/Makefile b/lib/Makefile
index d71aae1..18515f0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -121,6 +121,8 @@
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_SIGNATURE) += digsig.o
+obj-$(CONFIG_CLZ_TAB) += clz_tab.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/bug.c b/lib/bug.c
index 1955209..a28c141 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -169,7 +169,7 @@
return BUG_TRAP_TYPE_WARN;
}
- printk(KERN_EMERG "------------[ cut here ]------------\n");
+ printk(KERN_DEFAULT "------------[ cut here ]------------\n");
if (file)
printk(KERN_CRIT "kernel BUG at %s:%u!\n",
diff --git a/lib/clz_tab.c b/lib/clz_tab.c
new file mode 100644
index 0000000..7287b4a
--- /dev/null
+++ b/lib/clz_tab.c
@@ -0,0 +1,18 @@
+const unsigned char __clz_tab[] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+};
diff --git a/lib/digsig.c b/lib/digsig.c
index fd2402f..286d558 100644
--- a/lib/digsig.c
+++ b/lib/digsig.c
@@ -34,14 +34,9 @@
unsigned long msglen,
unsigned long modulus_bitlen,
unsigned char *out,
- unsigned long *outlen,
- int *is_valid)
+ unsigned long *outlen)
{
unsigned long modulus_len, ps_len, i;
- int result;
-
- /* default to invalid packet */
- *is_valid = 0;
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
@@ -50,39 +45,30 @@
return -EINVAL;
/* separate encoded message */
- if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
- result = -EINVAL;
- goto bail;
- }
+ if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
+ return -EINVAL;
for (i = 2; i < modulus_len - 1; i++)
if (msg[i] != 0xFF)
break;
/* separator check */
- if (msg[i] != 0) {
+ if (msg[i] != 0)
/* There was no octet with hexadecimal value 0x00
to separate ps from m. */
- result = -EINVAL;
- goto bail;
- }
+ return -EINVAL;
ps_len = i - 2;
if (*outlen < (msglen - (2 + ps_len + 1))) {
*outlen = msglen - (2 + ps_len + 1);
- result = -EOVERFLOW;
- goto bail;
+ return -EOVERFLOW;
}
*outlen = (msglen - (2 + ps_len + 1));
memcpy(out, &msg[2 + ps_len + 1], *outlen);
- /* valid packet */
- *is_valid = 1;
- result = 0;
-bail:
- return result;
+ return 0;
}
/*
@@ -96,7 +82,7 @@
unsigned long len;
unsigned long mlen, mblen;
unsigned nret, l;
- int valid, head, i;
+ int head, i;
unsigned char *out1 = NULL, *out2 = NULL;
MPI in = NULL, res = NULL, pkey[2];
uint8_t *p, *datap, *endp;
@@ -105,6 +91,10 @@
down_read(&key->sem);
ukp = key->payload.data;
+
+ if (ukp->datalen < sizeof(*pkh))
+ goto err1;
+
pkh = (struct pubkey_hdr *)ukp->data;
if (pkh->version != 1)
@@ -117,18 +107,23 @@
goto err1;
datap = pkh->mpi;
- endp = datap + ukp->datalen;
+ endp = ukp->data + ukp->datalen;
+
+ err = -ENOMEM;
for (i = 0; i < pkh->nmpi; i++) {
unsigned int remaining = endp - datap;
pkey[i] = mpi_read_from_buffer(datap, &remaining);
+ if (!pkey[i])
+ goto err;
datap += remaining;
}
mblen = mpi_get_nbits(pkey[0]);
mlen = (mblen + 7)/8;
- err = -ENOMEM;
+ if (mlen == 0)
+ goto err;
out1 = kzalloc(mlen, GFP_KERNEL);
if (!out1)
@@ -167,10 +162,9 @@
memset(out1, 0, head);
memcpy(out1 + head, p, l);
- err = -EINVAL;
- pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
+ err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
- if (valid && len == hlen)
+ if (!err && len == hlen)
err = memcmp(out2, h, hlen);
err:
@@ -178,8 +172,8 @@
mpi_free(res);
kfree(out1);
kfree(out2);
- mpi_free(pkey[0]);
- mpi_free(pkey[1]);
+ while (--i >= 0)
+ mpi_free(pkey[i]);
err1:
up_read(&key->sem);
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
index b87487b..29f9862 100644
--- a/lib/mpi/longlong.h
+++ b/lib/mpi/longlong.h
@@ -1200,18 +1200,40 @@
"r" ((USItype)(v)) \
: "%g1", "%g2" __AND_CLOBBER_CC)
#define UMUL_TIME 39 /* 39 instructions */
-#endif
-#ifndef udiv_qrnnd
-#ifndef LONGLONG_STANDALONE
+/* It's quite necessary to add this much assembler for the sparc.
+ The default udiv_qrnnd (in C) is more than 10 times slower! */
#define udiv_qrnnd(q, r, n1, n0, d) \
-do { USItype __r; \
- (q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
- (r) = __r; \
-} while (0)
- extern USItype __udiv_qrnnd();
-#define UDIV_TIME 140
-#endif /* LONGLONG_STANDALONE */
-#endif /* udiv_qrnnd */
+ __asm__ ("! Inlined udiv_qrnnd\n\t" \
+ "mov 32,%%g1\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "1: bcs 5f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "addx %1,%1,%1 ! so this can't give carry\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "2: bne 1b\n\t" \
+ "subcc %1,%2,%%g0\n\t" \
+ "bcs 3f\n\t" \
+ "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
+ "b 3f\n\t" \
+ "sub %1,%2,%1 ! this kills msb of n\n\t" \
+ "4: sub %1,%2,%1\n\t" \
+ "5: addxcc %1,%1,%1\n\t" \
+ "bcc 2b\n\t" \
+ "subcc %%g1,1,%%g1\n\t" \
+ "! Got carry from n. Subtract next step to cancel this carry.\n\t" \
+ "bne 4b\n\t" \
+ "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \
+ "sub %1,%2,%1\n\t" \
+ "3: xnor %0,0,%0\n\t" \
+ "! End of inline udiv_qrnnd\n" \
+ : "=&r" ((USItype)(q)), \
+ "=&r" ((USItype)(r)) \
+ : "r" ((USItype)(d)), \
+ "1" ((USItype)(n1)), \
+ "0" ((USItype)(n0)) : "%g1", "cc")
+#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
+#endif
#endif /* __sparc__ */
/***************************************
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c
index 854c9c6..2f52662 100644
--- a/lib/mpi/mpi-bit.c
+++ b/lib/mpi/mpi-bit.c
@@ -21,25 +21,6 @@
#include "mpi-internal.h"
#include "longlong.h"
-const unsigned char __clz_tab[] = {
- 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8,
-};
-
#define A_LIMB_1 ((mpi_limb_t) 1)
/****************
diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c
index c3087d1..f68cbbb 100644
--- a/lib/mpi/mpi-div.c
+++ b/lib/mpi/mpi-div.c
@@ -149,6 +149,9 @@
mpi_ptr_t marker[5];
int markidx = 0;
+ if (!dsize)
+ return -EINVAL;
+
memset(marker, 0, sizeof(marker));
/* Ensure space is enough for quotient and remainder.
@@ -207,6 +210,8 @@
* numerator would be gradually overwritten by the quotient limbs. */
if (qp == np) { /* Copy NP object to temporary space. */
np = marker[markidx++] = mpi_alloc_limb_space(nsize);
+ if (!np)
+ goto nomem;
MPN_COPY(np, qp, nsize);
}
} else /* Put quotient at top of remainder. */
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
index b04a3cf..67f3e79 100644
--- a/lib/mpi/mpi-pow.c
+++ b/lib/mpi/mpi-pow.c
@@ -59,7 +59,7 @@
ep = exp->d;
if (!msize)
- msize = 1 / msize; /* provoke a signal */
+ return -EINVAL;
if (!esize) {
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
diff --git a/lib/mpi/mpicoder.c b/lib/mpi/mpicoder.c
index 716802b..f26b41f 100644
--- a/lib/mpi/mpicoder.c
+++ b/lib/mpi/mpicoder.c
@@ -20,78 +20,15 @@
#include "mpi-internal.h"
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
#define MAX_EXTERN_MPI_BITS 16384
-static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
-{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
- 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
-};
-
-MPI do_encode_md(const void *sha_buffer, unsigned nbits)
-{
- int nframe = (nbits + 7) / 8;
- uint8_t *frame, *fr_pt;
- int i = 0, n;
- size_t asnlen = DIM(asn);
- MPI a = MPI_NULL;
-
- if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
- pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
- (int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
-
- /* We encode the MD in this way:
- *
- * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
- *
- * PAD consists of FF bytes.
- */
- frame = kmalloc(nframe, GFP_KERNEL);
- if (!frame)
- return MPI_NULL;
- n = 0;
- frame[n++] = 0;
- frame[n++] = 1; /* block type */
- i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
-
- if (i <= 1) {
- pr_info("MPI: message digest encoding failed\n");
- kfree(frame);
- return a;
- }
-
- memset(frame + n, 0xff, i);
- n += i;
- frame[n++] = 0;
- memcpy(frame + n, &asn, asnlen);
- n += asnlen;
- memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
- n += SHA1_DIGEST_LENGTH;
-
- i = nframe;
- fr_pt = frame;
-
- if (n != nframe) {
- printk
- ("MPI: message digest encoding failed, frame length is wrong\n");
- kfree(frame);
- return a;
- }
-
- a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
- mpi_set_buffer(a, frame, nframe, 0);
- kfree(frame);
-
- return a;
-}
-
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
{
const uint8_t *buffer = xbuffer;
int i, j;
unsigned nbits, nbytes, nlimbs, nread = 0;
mpi_limb_t a;
- MPI val = MPI_NULL;
+ MPI val = NULL;
if (*ret_nread < 2)
goto leave;
@@ -108,7 +45,7 @@
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
val = mpi_alloc(nlimbs);
if (!val)
- return MPI_NULL;
+ return NULL;
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
i %= BYTES_PER_MPI_LIMB;
val->nbits = nbits;
@@ -212,30 +149,6 @@
EXPORT_SYMBOL_GPL(mpi_fromstr);
/****************
- * Special function to get the low 8 bytes from an mpi.
- * This can be used as a keyid; KEYID is an 2 element array.
- * Return the low 4 bytes.
- */
-u32 mpi_get_keyid(const MPI a, u32 *keyid)
-{
-#if BYTES_PER_MPI_LIMB == 4
- if (keyid) {
- keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
- keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
- }
- return a->nlimbs >= 1 ? a->d[0] : 0;
-#elif BYTES_PER_MPI_LIMB == 8
- if (keyid) {
- keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
- keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
- }
- return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
-#else
-#error Make this function work with other LIMB sizes
-#endif
-}
-
-/****************
* Return an allocated buffer with the MPI (msb first).
* NBYTES receives the length of this buffer. Caller must free the
* return string (This function does return a 0 byte buffer with NBYTES
diff --git a/lib/mpi/mpih-div.c b/lib/mpi/mpih-div.c
index 87ede16..cde1aae 100644
--- a/lib/mpi/mpih-div.c
+++ b/lib/mpi/mpih-div.c
@@ -217,6 +217,10 @@
case 0:
/* We are asked to divide by zero, so go ahead and do it! (To make
the compiler not remove this statement, return the value.) */
+ /*
+ * existing clients of this function have been modified
+ * not to call it with dsize == 0, so this should not happen
+ */
return 1 / dsize;
case 1:
diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c
index eefc55d..26e4ed3 100644
--- a/lib/mpi/mpiutil.c
+++ b/lib/mpi/mpiutil.c
@@ -58,6 +58,9 @@
{
size_t len = nlimbs * sizeof(mpi_limb_t);
+ if (!len)
+ return NULL;
+
return kmalloc(len, GFP_KERNEL);
}
@@ -135,7 +138,7 @@
size_t i;
MPI b;
- *copied = MPI_NULL;
+ *copied = NULL;
if (a) {
b = mpi_alloc(a->nlimbs);
diff --git a/mm/compaction.c b/mm/compaction.c
index 71a58f6..bd939a5 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -313,6 +313,19 @@
} else if (!locked)
spin_lock_irq(&zone->lru_lock);
+ /*
+ * migrate_pfn does not necessarily start aligned to a
+ * pageblock. Ensure that pfn_valid is called when moving
+ * into a new MAX_ORDER_NR_PAGES range in case of large
+ * memory holes within the zone
+ */
+ if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) {
+ if (!pfn_valid(low_pfn)) {
+ low_pfn += MAX_ORDER_NR_PAGES - 1;
+ continue;
+ }
+ }
+
if (!pfn_valid_within(low_pfn))
continue;
nr_scanned++;
diff --git a/mm/filemap.c b/mm/filemap.c
index 97f49ed..b662757 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1400,15 +1400,12 @@
unsigned long seg = 0;
size_t count;
loff_t *ppos = &iocb->ki_pos;
- struct blk_plug plug;
count = 0;
retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
if (retval)
return retval;
- blk_start_plug(&plug);
-
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
loff_t size;
@@ -1424,8 +1421,12 @@
retval = filemap_write_and_wait_range(mapping, pos,
pos + iov_length(iov, nr_segs) - 1);
if (!retval) {
+ struct blk_plug plug;
+
+ blk_start_plug(&plug);
retval = mapping->a_ops->direct_IO(READ, iocb,
iov, pos, nr_segs);
+ blk_finish_plug(&plug);
}
if (retval > 0) {
*ppos = pos + retval;
@@ -1481,7 +1482,6 @@
break;
}
out:
- blk_finish_plug(&plug);
return retval;
}
EXPORT_SYMBOL(generic_file_aio_read);
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index f91b2f6..a4eb311 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -263,7 +263,12 @@
xip_pfn);
if (err == -ENOMEM)
return VM_FAULT_OOM;
- BUG_ON(err);
+ /*
+ * err == -EBUSY is fine, we've raced against another thread
+ * that faulted-in the same page
+ */
+ if (err != -EBUSY)
+ BUG_ON(err);
return VM_FAULT_NOPAGE;
} else {
int err, ret = VM_FAULT_OOM;
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index c833add..45eb621 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1036,7 +1036,7 @@
{
pr_debug("%s(0x%p)\n", __func__, ptr);
- if (atomic_read(&kmemleak_enabled) && ptr && !IS_ERR(ptr))
+ if (atomic_read(&kmemleak_enabled) && ptr && size && !IS_ERR(ptr))
add_scan_area((unsigned long)ptr, size, gfp);
else if (atomic_read(&kmemleak_early_log))
log_early(KMEMLEAK_SCAN_AREA, ptr, size, 0);
@@ -1757,6 +1757,7 @@
#ifdef CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF
if (!kmemleak_skip_disable) {
+ atomic_set(&kmemleak_early_log, 0);
kmemleak_disable();
return;
}
diff --git a/mm/memblock.c b/mm/memblock.c
index 2f55f19..77b5f22 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -106,14 +106,17 @@
if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
end = memblock.current_limit;
- /* adjust @start to avoid underflow and allocating the first page */
- start = max3(start, size, (phys_addr_t)PAGE_SIZE);
+ /* avoid allocating the first page */
+ start = max_t(phys_addr_t, start, PAGE_SIZE);
end = max(start, end);
for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
this_start = clamp(this_start, start, end);
this_end = clamp(this_end, start, end);
+ if (this_end < size)
+ continue;
+
cand = round_down(this_end - size, align);
if (cand >= this_start)
return cand;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 556859f..6728a7a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -776,7 +776,8 @@
/* threshold event is triggered in finer grain than soft limit */
if (unlikely(mem_cgroup_event_ratelimit(memcg,
MEM_CGROUP_TARGET_THRESH))) {
- bool do_softlimit, do_numainfo;
+ bool do_softlimit;
+ bool do_numainfo __maybe_unused;
do_softlimit = mem_cgroup_event_ratelimit(memcg,
MEM_CGROUP_TARGET_SOFTLIMIT);
diff --git a/mm/migrate.c b/mm/migrate.c
index 9871a56..df141f6 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -445,7 +445,6 @@
ClearPageSwapCache(page);
ClearPagePrivate(page);
set_page_private(page, 0);
- page->mapping = NULL;
/*
* If any waiters have accumulated on the new page then
@@ -667,6 +666,7 @@
} else {
if (remap_swapcache)
remove_migration_ptes(page, newpage);
+ page->mapping = NULL;
}
unlock_page(newpage);
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index e920aa3..c20ff48 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -298,22 +298,17 @@
goto free_proc_pages;
}
- task_lock(task);
- if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
- task_unlock(task);
- rc = -EPERM;
+ mm = mm_access(task, PTRACE_MODE_ATTACH);
+ if (!mm || IS_ERR(mm)) {
+ rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
+ /*
+ * Explicitly map EACCES to EPERM as EPERM is a more a
+ * appropriate error code for process_vw_readv/writev
+ */
+ if (rc == -EACCES)
+ rc = -EPERM;
goto put_task_struct;
}
- mm = task->mm;
-
- if (!mm || (task->flags & PF_KTHREAD)) {
- task_unlock(task);
- rc = -EINVAL;
- goto put_task_struct;
- }
-
- atomic_inc(&mm->mm_users);
- task_unlock(task);
for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {
rc = process_vm_rw_single_vec(
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index 673728a..82c5706 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -59,8 +59,6 @@
{
struct caif_net *caifn;
caifn = net_generic(net, caif_net_id);
- if (!caifn)
- return NULL;
return caifn->cfg;
}
EXPORT_SYMBOL(get_cfcnfg);
@@ -69,8 +67,6 @@
{
struct caif_net *caifn;
caifn = net_generic(net, caif_net_id);
- if (!caifn)
- return NULL;
return &caifn->caifdevs;
}
@@ -99,8 +95,6 @@
struct caif_device_entry *caifd;
caifdevs = caif_device_list(dev_net(dev));
- if (!caifdevs)
- return NULL;
caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
if (!caifd)
@@ -120,8 +114,6 @@
struct caif_device_entry_list *caifdevs =
caif_device_list(dev_net(dev));
struct caif_device_entry *caifd;
- if (!caifdevs)
- return NULL;
list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
if (caifd->netdev == dev)
@@ -321,8 +313,6 @@
struct caif_device_entry_list *caifdevs;
caifdevs = caif_device_list(dev_net(dev));
- if (!cfg || !caifdevs)
- return;
caifd = caif_device_alloc(dev);
if (!caifd)
return;
@@ -374,8 +364,6 @@
cfg = get_cfcnfg(dev_net(dev));
caifdevs = caif_device_list(dev_net(dev));
- if (!cfg || !caifdevs)
- return 0;
caifd = caif_get(dev);
if (caifd == NULL && dev->type != ARPHRD_CAIF)
@@ -507,9 +495,6 @@
static int caif_init_net(struct net *net)
{
struct caif_net *caifn = net_generic(net, caif_net_id);
- if (WARN_ON(!caifn))
- return -EINVAL;
-
INIT_LIST_HEAD(&caifn->caifdevs.list);
mutex_init(&caifn->caifdevs.lock);
@@ -527,9 +512,6 @@
caif_device_list(net);
struct cfcnfg *cfg = get_cfcnfg(net);
- if (!cfg || !caifdevs)
- return;
-
rtnl_lock();
mutex_lock(&caifdevs->lock);
@@ -569,7 +551,7 @@
{
int result;
- result = register_pernet_device(&caif_net_ops);
+ result = register_pernet_subsys(&caif_net_ops);
if (result)
return result;
@@ -582,7 +564,7 @@
static void __exit caif_device_exit(void)
{
- unregister_pernet_device(&caif_net_ops);
+ unregister_pernet_subsys(&caif_net_ops);
unregister_netdevice_notifier(&caif_device_notifier);
dev_remove_pack(&caif_packet_type);
}
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 598aafb..ba9cfd4 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -309,7 +309,6 @@
int err;
struct cfctrl_link_param param;
struct cfcnfg *cfg = get_cfcnfg(net);
- caif_assert(cfg != NULL);
rcu_read_lock();
err = caif_connect_req_to_link_param(cfg, conn_req, ¶m);
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index 97f70e5..761ad9d 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -85,8 +85,6 @@
} else {
pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid);
memcpy(&client->fsid, fsid, sizeof(*fsid));
- ceph_debugfs_client_init(client);
- client->have_fsid = true;
}
return 0;
}
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 0b62dea..1845cde 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -8,8 +8,8 @@
#include <linux/ceph/mon_client.h>
#include <linux/ceph/libceph.h>
+#include <linux/ceph/debugfs.h>
#include <linux/ceph/decode.h>
-
#include <linux/ceph/auth.h>
/*
@@ -340,8 +340,19 @@
client->monc.monmap = monmap;
kfree(old);
+ if (!client->have_fsid) {
+ client->have_fsid = true;
+ mutex_unlock(&monc->mutex);
+ /*
+ * do debugfs initialization without mutex to avoid
+ * creating a locking dependency
+ */
+ ceph_debugfs_client_init(client);
+ goto out_unlocked;
+ }
out:
mutex_unlock(&monc->mutex);
+out_unlocked:
wake_up_all(&client->auth_wq);
}
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index aefcd7a..0e950fd 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -30,6 +30,20 @@
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
+static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+
+static struct net_generic *net_alloc_generic(void)
+{
+ struct net_generic *ng;
+ size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+
+ ng = kzalloc(generic_size, GFP_KERNEL);
+ if (ng)
+ ng->len = max_gen_ptrs;
+
+ return ng;
+}
+
static int net_assign_generic(struct net *net, int id, void *data)
{
struct net_generic *ng, *old_ng;
@@ -43,8 +57,7 @@
if (old_ng->len >= id)
goto assign;
- ng = kzalloc(sizeof(struct net_generic) +
- id * sizeof(void *), GFP_KERNEL);
+ ng = net_alloc_generic();
if (ng == NULL)
return -ENOMEM;
@@ -59,7 +72,6 @@
* the old copy for kfree after a grace period.
*/
- ng->len = id;
memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
rcu_assign_pointer(net->gen, ng);
@@ -161,18 +173,6 @@
goto out;
}
-static struct net_generic *net_alloc_generic(void)
-{
- struct net_generic *ng;
- size_t generic_size = sizeof(struct net_generic) +
- INITIAL_NET_GEN_PTRS * sizeof(void *);
-
- ng = kzalloc(generic_size, GFP_KERNEL);
- if (ng)
- ng->len = INITIAL_NET_GEN_PTRS;
-
- return ng;
-}
#ifdef CONFIG_NET_NS
static struct kmem_cache *net_cachep;
@@ -483,6 +483,7 @@
}
return error;
}
+ max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
}
error = __register_pernet_operations(list, ops);
if (error) {
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index f16444b..65aebd4 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1509,6 +1509,9 @@
if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev),
+ min_ifinfo_dump_size);
+
return err;
}
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 2e4e244..19d66ce 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -123,11 +123,14 @@
smallest_size = tb->num_owners;
smallest_rover = rover;
if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
- spin_unlock(&head->lock);
snum = smallest_rover;
- goto have_snum;
+ goto tb_found;
}
}
+ if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+ snum = rover;
+ goto tb_found;
+ }
goto next;
}
break;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 2b53a1f..6b3ca5b 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -422,6 +422,10 @@
if (register_netdevice(dev) < 0)
goto failed_free;
+ /* Can use a lockless transmit, unless we generate output sequences */
+ if (!(nt->parms.o_flags & GRE_SEQ))
+ dev->features |= NETIF_F_LLTX;
+
dev_hold(dev);
ipgre_tunnel_link(ign, nt);
return nt;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 4aa7e9d..4cb9cd2 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -814,6 +814,7 @@
net->ipv4.sysctl_rt_cache_rebuild_count = 4;
+ tcp_init_mem(net);
limit = nr_free_buffer_pages() / 8;
limit = max(limit, 128UL);
net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 9bcdec3..06373b4 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3216,6 +3216,16 @@
}
__setup("thash_entries=", set_thash_entries);
+void tcp_init_mem(struct net *net)
+{
+ /* Set per-socket limits to no more than 1/128 the pressure threshold */
+ unsigned long limit = nr_free_buffer_pages() / 8;
+ limit = max(limit, 128UL);
+ net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
+ net->ipv4.sysctl_tcp_mem[1] = limit;
+ net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
+}
+
void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
@@ -3276,9 +3286,9 @@
sysctl_tcp_max_orphans = cnt / 2;
sysctl_max_syn_backlog = max(128, cnt / 256);
- /* Set per-socket limits to no more than 1/128 the pressure threshold */
- limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1])
- << (PAGE_SHIFT - 7);
+ tcp_init_mem(&init_net);
+ limit = nr_free_buffer_pages() / 8;
+ limit = max(limit, 128UL);
max_share = min(4UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 8c8de27..4ff3b6d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1141,11 +1141,9 @@
sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
- /* Any change of skb->len requires recalculation of tso
- * factor and mss.
- */
+ /* Any change of skb->len requires recalculation of tso factor. */
if (tcp_skb_pcount(skb) > 1)
- tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
+ tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
return 0;
}
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index d21e7eb..55670ec 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -393,11 +393,6 @@
{
int rc;
- if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
- goto drop;
-
- nf_reset(skb);
-
/* Charge it to the socket, dropping if the queue is full. */
rc = sock_queue_rcv_skb(sk, skb);
if (rc < 0)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index b3d76b7..a464396 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -106,6 +106,7 @@
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
+ local->oper_channel = chan;
channel_type = ifibss->channel_type;
if (channel_type > NL80211_CHAN_HT20 &&
!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e47768c..01a21c2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1314,6 +1314,7 @@
continue;
}
/* count everything else */
+ sdata->vif.bss_conf.idle = false;
count++;
}
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c
index 1426ec3..75762f3 100644
--- a/net/sunrpc/auth_generic.c
+++ b/net/sunrpc/auth_generic.c
@@ -92,6 +92,7 @@
if (gcred->acred.group_info != NULL)
get_group_info(gcred->acred.group_info);
gcred->acred.machine_cred = acred->machine_cred;
+ gcred->acred.principal = acred->principal;
dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
gcred->acred.machine_cred ? "machine" : "generic",
@@ -123,6 +124,17 @@
call_rcu(&cred->cr_rcu, generic_free_cred_callback);
}
+static int
+machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags)
+{
+ if (!gcred->acred.machine_cred ||
+ gcred->acred.principal != acred->principal ||
+ gcred->acred.uid != acred->uid ||
+ gcred->acred.gid != acred->gid)
+ return 0;
+ return 1;
+}
+
/*
* Match credentials against current process creds.
*/
@@ -132,9 +144,12 @@
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
int i;
+ if (acred->machine_cred)
+ return machine_cred_match(acred, gcred, flags);
+
if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
- gcred->acred.machine_cred != acred->machine_cred)
+ gcred->acred.machine_cred != 0)
goto out_nomatch;
/* Optimisation in the case where pointers are identical... */
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index aad8fb6..85d3bb7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1918,7 +1918,7 @@
struct sk_buff *skb;
unix_state_lock(sk);
- skb = skb_dequeue(&sk->sk_receive_queue);
+ skb = skb_peek(&sk->sk_receive_queue);
if (skb == NULL) {
unix_sk(sk)->recursion_level = 0;
if (copied >= target)
@@ -1958,11 +1958,8 @@
if (check_creds) {
/* Never glue messages from different writers */
if ((UNIXCB(skb).pid != siocb->scm->pid) ||
- (UNIXCB(skb).cred != siocb->scm->cred)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ (UNIXCB(skb).cred != siocb->scm->cred))
break;
- }
} else {
/* Copy credentials */
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
@@ -1977,8 +1974,6 @@
chunk = min_t(unsigned int, skb->len, size);
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
if (copied == 0)
copied = -EFAULT;
break;
@@ -1993,13 +1988,10 @@
if (UNIXCB(skb).fp)
unix_detach_fds(siocb->scm, skb);
- /* put the skb back if we didn't use it up.. */
- if (skb->len) {
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ if (skb->len)
break;
- }
+ skb_unlink(skb, &sk->sk_receive_queue);
consume_skb(skb);
if (siocb->scm->fp)
@@ -2010,9 +2002,6 @@
if (UNIXCB(skb).fp)
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
- /* put message back and return */
- skb_queue_head(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
break;
}
} while (size);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index c0e14b3..e8c9695 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -823,16 +823,6 @@
}
ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry);
-/* Looks like: mcp:S */
-static int do_mcp_entry(const char *filename, struct mcp_device_id *id,
- char *alias)
-{
- sprintf(alias, MCP_MODULE_PREFIX "%s", id->name);
-
- return 1;
-}
-ADD_TO_DEVTABLE("mcp", struct mcp_device_id, do_mcp_entry);
-
static const struct dmifield {
const char *prefix;
int field;
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index dac3633..a68aed7 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -441,19 +441,22 @@
params = kmalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
- if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
- return -EFAULT;
+ if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
+ retval = -EFAULT;
+ goto out;
+ }
retval = snd_compr_allocate_buffer(stream, params);
if (retval) {
- kfree(params);
- return -ENOMEM;
+ retval = -ENOMEM;
+ goto out;
}
retval = stream->ops->set_params(stream, params);
if (retval)
goto out;
stream->runtime->state = SNDRV_PCM_STATE_SETUP;
- } else
+ } else {
return -EPERM;
+ }
out:
kfree(params);
return retval;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 4df72c0..c2c65f6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1447,7 +1447,7 @@
for (i = 0; i < c->cvt_setups.used; i++) {
p = snd_array_elem(&c->cvt_setups, i);
if (!p->active && p->stream_tag == stream_tag &&
- get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+ get_wcaps_type(get_wcaps(c, p->nid)) == type)
p->dirty = 1;
}
}
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index d8a35da..9d819c4 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -282,7 +282,8 @@
EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
- const struct auto_pin_cfg *cfg)
+ const struct auto_pin_cfg *cfg,
+ char *lastname, int *lastidx)
{
unsigned int def_conf, conn;
char name[44];
@@ -298,6 +299,10 @@
return 0;
snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+ if (!strcmp(name, lastname) && idx == *lastidx)
+ idx++;
+ strncpy(lastname, name, 44);
+ *lastidx = idx;
err = snd_hda_jack_add_kctl(codec, nid, name, idx);
if (err < 0)
return err;
@@ -311,41 +316,42 @@
const struct auto_pin_cfg *cfg)
{
const hda_nid_t *p;
- int i, err;
+ int i, err, lastidx = 0;
+ char lastname[44] = "";
for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */
break;
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
if (*p == *cfg->line_out_pins) /* might be duplicated */
break;
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0; i < cfg->num_inputs; i++) {
- err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
+ err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
- err = add_jack_kctl(codec, *p, cfg);
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
if (err < 0)
return err;
}
- err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
+ err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
- err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
+ err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
if (err < 0)
return err;
return 0;
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 0e99357..bc5a993 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -988,8 +988,10 @@
change_cur_input(codec, !spec->automic_idx, 0);
} else {
if (present) {
- spec->last_input = spec->cur_input;
- spec->cur_input = spec->automic_idx;
+ if (spec->cur_input != spec->automic_idx) {
+ spec->last_input = spec->cur_input;
+ spec->cur_input = spec->automic_idx;
+ }
} else {
spec->cur_input = spec->last_input;
}
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index c95c8bd..a8e82be 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -177,6 +177,7 @@
unsigned int detect_lo:1; /* Line-out detection enabled */
unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
unsigned int automute_lo_possible:1; /* there are line outs and HP */
+ unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
@@ -495,13 +496,24 @@
for (i = 0; i < num_pins; i++) {
hda_nid_t nid = pins[i];
+ unsigned int val;
if (!nid)
break;
switch (spec->automute_mode) {
case ALC_AUTOMUTE_PIN:
+ /* don't reset VREF value in case it's controlling
+ * the amp (see alc861_fixup_asus_amp_vref_0f())
+ */
+ if (spec->keep_vref_in_automute) {
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val &= ~PIN_HP;
+ } else
+ val = 0;
+ val |= pin_bits;
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_bits);
+ val);
break;
case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -4735,7 +4747,6 @@
ALC262_FIXUP_FSC_H270,
ALC262_FIXUP_HP_Z200,
ALC262_FIXUP_TYAN,
- ALC262_FIXUP_TOSHIBA_RX1,
ALC262_FIXUP_LENOVO_3000,
ALC262_FIXUP_BENQ,
ALC262_FIXUP_BENQ_T31,
@@ -4765,16 +4776,6 @@
{ }
}
},
- [ALC262_FIXUP_TOSHIBA_RX1] = {
- .type = ALC_FIXUP_PINS,
- .v.pins = (const struct alc_pincfg[]) {
- { 0x14, 0x90170110 }, /* speaker */
- { 0x15, 0x0421101f }, /* HP */
- { 0x1a, 0x40f000f0 }, /* N/A */
- { 0x1b, 0x40f000f0 }, /* N/A */
- { 0x1e, 0x40f000f0 }, /* N/A */
- }
- },
[ALC262_FIXUP_LENOVO_3000] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -4807,8 +4808,6 @@
SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
- SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
- ALC262_FIXUP_TOSHIBA_RX1),
SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
@@ -5377,7 +5376,6 @@
SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
@@ -5586,8 +5584,28 @@
/* Pin config fixes */
enum {
PINFIX_FSC_AMILO_PI1505,
+ PINFIX_ASUS_A6RP,
};
+/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
+static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ val = snd_hda_codec_read(codec, 0x0f, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
+ val |= AC_PINCTL_IN_EN;
+ val |= AC_PINCTL_VREF_50;
+ snd_hda_codec_write(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ spec->keep_vref_in_automute = 1;
+}
+
static const struct alc_fixup alc861_fixups[] = {
[PINFIX_FSC_AMILO_PI1505] = {
.type = ALC_FIXUP_PINS,
@@ -5597,9 +5615,15 @@
{ }
}
},
+ [PINFIX_ASUS_A6RP] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861_fixup_asus_amp_vref_0f,
+ },
};
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", PINFIX_ASUS_A6RP),
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
{}
};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 336cfcd..948f0be 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4870,7 +4870,14 @@
/* BIOS bug: unfilled OEM string */
if (strstr(dev->name, "HP_Mute_LED_P_G")) {
set_hp_led_gpio(codec);
- spec->gpio_led_polarity = 1;
+ switch (codec->subsystem_id) {
+ case 0x103c148a:
+ spec->gpio_led_polarity = 0;
+ break;
+ default:
+ spec->gpio_led_polarity = 1;
+ break;
+ }
return 1;
}
}
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 03e63fe..284e311 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -199,6 +199,9 @@
unsigned int no_pin_power_ctl;
enum VIA_HDA_CODEC codec_type;
+ /* analog low-power control */
+ bool alc_mode;
+
/* smart51 setup */
unsigned int smart51_nums;
hda_nid_t smart51_pins[2];
@@ -687,6 +690,15 @@
}
}
+static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int parm)
+{
+ if (snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_POWER_STATE, 0) == parm)
+ return;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int *affected_parm)
{
@@ -709,7 +721,7 @@
} else
parm = AC_PWRST_D3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, nid, parm);
}
static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
@@ -749,6 +761,7 @@
return 0;
spec->no_pin_power_ctl = val;
set_widgets_power_state(codec);
+ analog_low_current_mode(codec);
return 1;
}
@@ -1036,13 +1049,19 @@
}
/* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
{
struct via_spec *spec = codec->spec;
bool enable;
unsigned int verb, parm;
- enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+ if (spec->no_pin_power_ctl)
+ enable = false;
+ else
+ enable = is_aa_path_mute(codec) && !spec->opened_streams;
+ if (enable == spec->alc_mode && !force)
+ return;
+ spec->alc_mode = enable;
/* decide low current mode's verb & parameter */
switch (spec->codec_type) {
@@ -1074,6 +1093,11 @@
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
}
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+ return __analog_low_current_mode(codec, false);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -1446,6 +1470,7 @@
struct snd_kcontrol *kctl;
int err, i;
+ spec->no_pin_power_ctl = 1;
if (spec->set_widgets_power_state)
if (!via_clone_control(spec, &via_pin_power_ctl_enum))
return -ENOMEM;
@@ -1499,10 +1524,6 @@
return err;
}
- /* init power states */
- set_widgets_power_state(codec);
- analog_low_current_mode(codec);
-
via_free_kctls(codec); /* no longer needed */
err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
@@ -2295,10 +2316,7 @@
if (mux) {
/* switch to D0 beofre change index */
- if (snd_hda_codec_read(codec, mux, 0,
- AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
- snd_hda_codec_write(codec, mux, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, mux, AC_PWRST_D0);
snd_hda_codec_write(codec, mux, 0,
AC_VERB_SET_CONNECT_SEL,
spec->inputs[cur].mux_idx);
@@ -2776,6 +2794,10 @@
for (i = 0; i < spec->num_iverbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ /* init power states */
+ set_widgets_power_state(codec);
+ __analog_low_current_mode(codec, true);
+
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_speaker_out(codec);
@@ -2922,9 +2944,9 @@
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW 0/1 (13h/14h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -2932,8 +2954,8 @@
set_pin_power_state(codec, 0x19, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW6 (22h), SW2 (26h), AOW2 (24h) */
if (is_8ch) {
@@ -2941,20 +2963,16 @@
set_pin_power_state(codec, 0x22, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x24, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x24, parm);
} else if (codec->vendor_id == 0x11064397) {
/* PW7(23h), SW2(27h), AOW2(25h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x23, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
+ update_power_state(codec, 0x25, parm);
}
/* PW 3/4/7 (1ch/1dh/23h) */
@@ -2966,17 +2984,13 @@
set_pin_power_state(codec, 0x23, &parm);
/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
if (is_8ch) {
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
+ update_power_state(codec, 0x27, parm);
} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
}
static int patch_vt1708S(struct hda_codec *codec);
@@ -3149,10 +3163,10 @@
if (imux_is_smixer)
parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x12, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x20, parm);
/* outputs */
/* PW 3/4 (16h/17h) */
@@ -3160,10 +3174,9 @@
set_pin_power_state(codec, 0x17, &parm);
set_pin_power_state(codec, 0x16, &parm);
/* MW0 (1ah), AOW 0/1 (10h/1dh) */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x1d, parm);
}
static int patch_vt1702(struct hda_codec *codec)
@@ -3228,52 +3241,48 @@
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x27, &parm);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, parm);
+ update_power_state(codec, 0xb, parm);
/* PW2 (26h), AOW2 (ah) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2b, &parm);
- snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0xa, parm);
/* PW0 (24h), AOW0 (8h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (!spec->hp_independent_mode) /* check for redirected HP */
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
/* PW1 (25h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2a, &parm);
- snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x9, parm);
if (spec->hp_independent_mode) {
/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1b, parm);
+ update_power_state(codec, 0x34, parm);
+ update_power_state(codec, 0xc, parm);
}
}
@@ -3433,8 +3442,8 @@
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW0(13h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x1e, &parm);
@@ -3442,12 +3451,11 @@
if (spec->dmic_enabled)
set_pin_power_state(codec, 0x22, &parm);
else
- snd_hda_codec_write(codec, 0x22, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x22, AC_PWRST_D3);
/* SW2(26h), AIW1(14h) */
- snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -3456,8 +3464,8 @@
/* Smart 5.1 PW2(1bh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW7 (23h), SW3 (27h), AOW3 (25h) */
parm = AC_PWRST_D3;
@@ -3465,12 +3473,12 @@
/* Smart 5.1 PW1(1ah) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
/* Smart 5.1 PW5(1eh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1e, &parm);
- snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* Mono out */
/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
@@ -3486,9 +3494,9 @@
mono_out = 1;
}
parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
- snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x28, parm);
+ update_power_state(codec, 0x29, parm);
+ update_power_state(codec, 0x2a, parm);
/* PW 3/4 (1ch/1dh) */
parm = AC_PWRST_D3;
@@ -3496,15 +3504,12 @@
set_pin_power_state(codec, 0x1d, &parm);
/* HP Independent Mode, power on AOW3 */
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* force to D0 for internal Speaker */
/* MW0 (16h), AOW0 (10h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- mono_out ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
}
static int patch_vt1716S(struct hda_codec *codec)
@@ -3580,54 +3585,45 @@
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
if (spec->codec_type == VT1802) {
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
} else {
/* PW4 (26h), MW4 (1ch), MUX4(37h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x37, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x37, parm);
}
if (spec->codec_type == VT1802) {
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
} else {
/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x19, parm);
+ update_power_state(codec, 0x35, parm);
}
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Class-D */
/* PW0 (24h), MW0(18h/14h), MUX0(34h) */
@@ -3637,12 +3633,10 @@
set_pin_power_state(codec, 0x24, &parm);
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x14, parm);
else
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x34, parm);
/* Mono Out */
present = snd_hda_jack_detect(codec, 0x26);
@@ -3650,28 +3644,20 @@
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802) {
/* PW15 (33h), MW8(1ch), MUX8(3ch) */
- snd_hda_codec_write(codec, 0x33, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x33, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x3c, parm);
} else {
/* PW15 (31h), MW8(17h), MUX8(3bh) */
- snd_hda_codec_write(codec, 0x31, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x31, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x3b, parm);
}
/* MW9 (21h) */
if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x21, AC_PWRST_D0);
else
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x21, AC_PWRST_D3);
}
/* patch for vt2002P */
@@ -3731,30 +3717,28 @@
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x8, AC_PWRST_D0);
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Internal Speaker */
/* PW0 (24h), MW0(14h), MUX0(34h) */
@@ -3763,15 +3747,11 @@
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x14, AC_PWRST_D3);
+ update_power_state(codec, 0x34, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x14, AC_PWRST_D0);
+ update_power_state(codec, 0x34, AC_PWRST_D0);
}
@@ -3782,26 +3762,20 @@
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x31, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x1c, AC_PWRST_D3);
+ update_power_state(codec, 0x3c, AC_PWRST_D3);
+ update_power_state(codec, 0x3e, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x1c, AC_PWRST_D0);
+ update_power_state(codec, 0x3c, AC_PWRST_D0);
+ update_power_state(codec, 0x3e, AC_PWRST_D0);
}
/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x33, &parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1d, parm);
+ update_power_state(codec, 0x3d, parm);
}
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index e57b89e8..94ab728 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -286,17 +286,22 @@
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) {
+ err = snd_ymfpci_mixer(chip, rear_switch[dev]);
+ if (err < 0) {
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) {
- snd_card_free(card);
- return err;
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ err = snd_ymfpci_pcm_4ch(chip, 2, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ err = snd_ymfpci_pcm2(chip, 3, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
}
if ((err = snd_ymfpci_timer(chip, 0)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 03ee4e3..12a9a2b 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1614,6 +1614,14 @@
return change;
}
+static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "4ch Duplication",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ymfpci_info_dup4ch,
+ .get = snd_ymfpci_get_dup4ch,
+ .put = snd_ymfpci_put_dup4ch,
+};
static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
{
@@ -1642,13 +1650,6 @@
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "4ch Duplication",
- .info = snd_ymfpci_info_dup4ch,
- .get = snd_ymfpci_get_dup4ch,
- .put = snd_ymfpci_put_dup4ch,
-},
};
@@ -1838,6 +1839,12 @@
if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
return err;
}
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip);
+ err = snd_ctl_add(chip->card, kctl);
+ if (err < 0)
+ return err;
+ }
/* add S/PDIF control */
if (snd_BUG_ON(!chip->pcm_spdif))
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index f8863eb..7f4ba81 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -987,12 +987,12 @@
/* restore regular registers */
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
- /* this regs depends on the others */
+ /* These regs should restore in particular order */
if (reg == SGTL5000_CHIP_ANA_POWER ||
reg == SGTL5000_CHIP_CLK_CTRL ||
reg == SGTL5000_CHIP_LINREG_CTRL ||
reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
- reg == SGTL5000_CHIP_CLK_CTRL)
+ reg == SGTL5000_CHIP_REF_CTRL)
continue;
snd_soc_write(codec, reg, cache[reg]);
@@ -1003,8 +1003,17 @@
snd_soc_write(codec, reg, cache[reg]);
/*
- * restore power and other regs according
- * to set_power() and set_clock()
+ * restore these regs according to the power setting sequence in
+ * sgtl5000_set_power_regs() and clock setting sequence in
+ * sgtl5000_set_clock().
+ *
+ * The order of restore is:
+ * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+ * SGTL5000_CHIP_ANA_POWER PLL bits set
+ * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+ * SGTL5000_CHIP_ANA_POWER LINREG_D restored
+ * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+ * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
*/
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
cache[SGTL5000_CHIP_LINREG_CTRL]);
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index eb401ef..372b0b8 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -60,7 +60,6 @@
struct aic32x4_priv {
u32 sysclk;
- s32 master;
u8 page_no;
void *control_data;
u32 power_cfg;
@@ -369,7 +368,6 @@
static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u8 iface_reg_1;
u8 iface_reg_2;
u8 iface_reg_3;
@@ -384,11 +382,9 @@
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
- aic32x4->master = 1;
iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
- aic32x4->master = 0;
break;
default:
printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
@@ -526,64 +522,58 @@
static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
-
switch (level) {
case SND_SOC_BIAS_ON:
- if (aic32x4->master) {
- /* Switch on PLL */
- snd_soc_update_bits(codec, AIC32X4_PLLPR,
- AIC32X4_PLLEN, AIC32X4_PLLEN);
+ /* Switch on PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, AIC32X4_PLLEN);
- /* Switch on NDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_NDAC,
- AIC32X4_NDACEN, AIC32X4_NDACEN);
+ /* Switch on NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, AIC32X4_NDACEN);
- /* Switch on MDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_MDAC,
- AIC32X4_MDACEN, AIC32X4_MDACEN);
+ /* Switch on MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, AIC32X4_MDACEN);
- /* Switch on NADC Divider */
- snd_soc_update_bits(codec, AIC32X4_NADC,
- AIC32X4_NADCEN, AIC32X4_NADCEN);
+ /* Switch on NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, AIC32X4_NADCEN);
- /* Switch on MADC Divider */
- snd_soc_update_bits(codec, AIC32X4_MADC,
- AIC32X4_MADCEN, AIC32X4_MADCEN);
+ /* Switch on MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, AIC32X4_MADCEN);
- /* Switch on BCLK_N Divider */
- snd_soc_update_bits(codec, AIC32X4_BCLKN,
- AIC32X4_BCLKEN, AIC32X4_BCLKEN);
- }
+ /* Switch on BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, AIC32X4_BCLKEN);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- if (aic32x4->master) {
- /* Switch off PLL */
- snd_soc_update_bits(codec, AIC32X4_PLLPR,
- AIC32X4_PLLEN, 0);
+ /* Switch off PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, 0);
- /* Switch off NDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_NDAC,
- AIC32X4_NDACEN, 0);
+ /* Switch off NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, 0);
- /* Switch off MDAC Divider */
- snd_soc_update_bits(codec, AIC32X4_MDAC,
- AIC32X4_MDACEN, 0);
+ /* Switch off MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, 0);
- /* Switch off NADC Divider */
- snd_soc_update_bits(codec, AIC32X4_NADC,
- AIC32X4_NADCEN, 0);
+ /* Switch off NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, 0);
- /* Switch off MADC Divider */
- snd_soc_update_bits(codec, AIC32X4_MADC,
- AIC32X4_MADCEN, 0);
+ /* Switch off MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, 0);
- /* Switch off BCLK_N Divider */
- snd_soc_update_bits(codec, AIC32X4_BCLKN,
- AIC32X4_BCLKEN, 0);
- }
+ /* Switch off BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, 0);
break;
case SND_SOC_BIAS_OFF:
break;
@@ -651,9 +641,11 @@
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
}
- if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
- snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
- }
+
+ tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
+ AIC32X4_LDOCTLEN : 0;
+ snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
+
tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
tmp_reg |= AIC32X4_LDOIN_18_36;
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index c288090..a75c376 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -733,8 +733,9 @@
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
const char *filename;
- const struct firmware *fw;
- int reg, ret;
+ const struct firmware *fw = NULL;
+ int ret;
+ int reg;
u16 id;
wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
@@ -751,7 +752,7 @@
ret = PTR_ERR(wm2000->regmap);
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
ret);
- goto err;
+ goto out;
}
/* Verify that this is a WM2000 */
@@ -763,7 +764,7 @@
if (id != 0x2000) {
dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
ret = -ENODEV;
- goto err_regmap;
+ goto out_regmap_exit;
}
reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -782,7 +783,7 @@
ret = request_firmware(&fw, filename, &i2c->dev);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
- goto err_regmap;
+ goto out_regmap_exit;
}
/* Pre-cook the concatenation of the register address onto the image */
@@ -793,15 +794,13 @@
if (wm2000->anc_download == NULL) {
dev_err(&i2c->dev, "Out of memory\n");
ret = -ENOMEM;
- goto err_fw;
+ goto out_regmap_exit;
}
wm2000->anc_download[0] = 0x80;
wm2000->anc_download[1] = 0x00;
memcpy(wm2000->anc_download + 2, fw->data, fw->size);
- release_firmware(fw);
-
wm2000->anc_eng_ena = 1;
wm2000->anc_active = 1;
wm2000->spk_ena = 1;
@@ -809,18 +808,14 @@
wm2000_reset(wm2000);
- ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000,
- NULL, 0);
- if (ret != 0)
- goto err_fw;
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
+ if (!ret)
+ goto out;
- return 0;
-
-err_fw:
- release_firmware(fw);
-err_regmap:
+out_regmap_exit:
regmap_exit(wm2000->regmap);
-err:
+out:
+ release_firmware(fw);
return ret;
}
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 8b24323..89f2af7 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1377,6 +1377,7 @@
switch (wm5100->rev) {
case 0:
+ regcache_cache_bypass(wm5100->regmap, true);
snd_soc_write(codec, 0x11, 0x3);
snd_soc_write(codec, 0x203, 0xc);
snd_soc_write(codec, 0x206, 0);
@@ -1392,6 +1393,7 @@
snd_soc_write(codec,
wm5100_reva_patches[i].reg,
wm5100_reva_patches[i].val);
+ regcache_cache_bypass(wm5100->regmap, false);
break;
default:
break;
@@ -1402,6 +1404,8 @@
break;
case SND_SOC_BIAS_OFF:
+ regcache_cache_only(wm5100->regmap, true);
+ regcache_mark_dirty(wm5100->regmap);
if (wm5100->pdata.ldo_ena)
gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
@@ -2180,6 +2184,7 @@
if (wm5100->jack_detecting) {
dev_dbg(codec->dev, "Microphone detected\n");
wm5100->jack_mic = true;
+ wm5100->jack_detecting = false;
snd_soc_jack_report(wm5100->jack,
SND_JACK_HEADSET,
SND_JACK_HEADSET | SND_JACK_BTN_0);
@@ -2218,6 +2223,7 @@
SND_JACK_BTN_0);
} else if (wm5100->jack_detecting) {
dev_dbg(codec->dev, "Headphone detected\n");
+ wm5100->jack_detecting = false;
snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
SND_JACK_HEADPHONE);
@@ -2607,6 +2613,13 @@
.cache_type = REGCACHE_RBTREE,
};
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+ WM5100_IN1L_CONTROL,
+ WM5100_IN2L_CONTROL,
+ WM5100_IN3L_CONTROL,
+ WM5100_IN4L_CONTROL,
+};
+
static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
@@ -2739,7 +2752,7 @@
}
for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
- regmap_update_bits(wm5100->regmap, WM5100_IN1L_CONTROL,
+ regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
WM5100_IN1_MODE_MASK |
WM5100_IN1_DMIC_SUP_MASK,
(wm5100->pdata.in_mode[i] <<
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 8d4ea43..40ac888 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -55,7 +55,7 @@
return 0;
if (fw->size < 32) {
- dev_err(codec->dev, "%s: firmware too short (%d bytes)\n",
+ dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
name, fw->size);
goto err;
}
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 296de4e..bda3da8 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -96,7 +96,7 @@
struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- regcache_cache_only(wm8962->regmap, true); \
+ regcache_mark_dirty(wm8962->regmap); \
} \
return 0; \
}
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index d8da10f..61f7daa 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -108,7 +108,7 @@
struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- regcache_cache_only(wm8996->regmap, true); \
+ regcache_mark_dirty(wm8996->regmap); \
} \
return 0; \
}
@@ -1120,7 +1120,8 @@
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
@@ -2007,6 +2008,7 @@
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int lfclk = 0;
int ratediv = 0;
+ int sync = WM8996_REG_SYNC;
int src;
int old;
@@ -2051,6 +2053,7 @@
case 32000:
case 32768:
lfclk = WM8996_LFCLK_ENA;
+ sync = 0;
break;
default:
dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
@@ -2064,6 +2067,8 @@
WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
+ snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1,
+ WM8996_REG_SYNC, sync);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
WM8996_SYSCLK_ENA, old);
diff --git a/sound/soc/codecs/wm8996.h b/sound/soc/codecs/wm8996.h
index 0fde643..de9ac3e 100644
--- a/sound/soc/codecs/wm8996.h
+++ b/sound/soc/codecs/wm8996.h
@@ -1567,6 +1567,10 @@
/*
* R257 (0x101) - Control Interface (1)
*/
+#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */
+#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */
#define WM8996_AUTO_INC 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 2a61094..ea26724 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -592,8 +592,8 @@
};
static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
};
static const struct snd_kcontrol_new line2p_mix[] = {
@@ -613,6 +613,8 @@
SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)),
SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -834,9 +836,11 @@
};
static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+ { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -853,9 +857,11 @@
};
static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+ { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index dccfb37..f204dba 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -124,6 +124,8 @@
*
* If MCLK is not used, we just set saif clk to 512*fs.
*/
+ clk_prepare_enable(master_saif->clk);
+
if (master_saif->mclk_in_use) {
if (mclk % 32 == 0) {
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
@@ -133,6 +135,7 @@
ret = clk_set_rate(master_saif->clk, 384 * rate);
} else {
/* SAIF MCLK should be either 32x or 48x */
+ clk_disable_unprepare(master_saif->clk);
return -EINVAL;
}
} else {
@@ -140,6 +143,8 @@
scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
}
+ clk_disable_unprepare(master_saif->clk);
+
if (ret)
return ret;
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 7ac0ba2..c6012ff 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -230,8 +230,6 @@
/* GTA02 specific routes and controls */
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
static int gta02_speaker_enabled;
static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -311,10 +309,6 @@
return 0;
}
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@
int ret;
/* set up NC codec pins */
- if (machine_is_neo1973_gta01()) {
- snd_soc_dapm_nc_pin(dapm, "LOUT2");
- snd_soc_dapm_nc_pin(dapm, "ROUT2");
- }
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "OUT4");
snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -370,50 +360,6 @@
return 0;
}
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
- {"Amp IN", NULL, "ROUT1"},
- {"Amp IN", NULL, "LOUT1"},
-
- {"Handset Spk", NULL, "Amp EP"},
- {"Stereo Out", NULL, "Amp LS"},
- {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
- SND_SOC_DAPM_SPK("Handset Spk", NULL),
- SND_SOC_DAPM_SPK("Stereo Out", NULL),
- SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
- ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
- if (ret)
- return ret;
-
- ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
- ARRAY_SIZE(neo1973_lm4857_routes));
- if (ret)
- return ret;
-
- snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
- snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
- snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
- return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
static struct snd_soc_dai_link neo1973_dai[] = {
{ /* Hifi Playback - for similatious use with voice below */
.name = "WM8753",
@@ -440,11 +386,6 @@
.name = "dfbmcs320",
.codec_name = "dfbmcs320.0",
},
- {
- .name = "lm4857",
- .codec_name = "lm4857.0-007c",
- .init = neo1973_lm4857_init,
- },
};
static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -454,14 +395,10 @@
},
};
-#ifdef CONFIG_MACH_NEO1973_GTA02
static const struct gpio neo1973_gta02_gpios[] = {
{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
};
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
static struct snd_soc_card neo1973 = {
.name = "neo1973",
@@ -480,7 +417,7 @@
{
int ret;
- if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+ if (!machine_is_neo1973_gta02())
return -ENODEV;
if (machine_is_neo1973_gta02()) {
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ac86d67..7c12650 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -104,7 +104,7 @@
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm
-ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS)
STRIP ?= strip
@@ -168,10 +168,7 @@
### --- END CONFIGURATION SECTION ---
-# Those must not be GNU-specific; they are shared with perl/ which may
-# be built by a different compiler. (Note that this is an artifact now
-# but it still might be nice to keep that distinction.)
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =
# Guard against environment variables
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 59d43ab..fb85661 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -20,7 +20,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
-#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -31,7 +30,6 @@
#include <stdlib.h>
#include <string.h>
-#undef _GNU_SOURCE
#include "perf.h"
#include "builtin.h"
#include "util/util.h"
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8f80df8..dd162aa 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -89,8 +89,6 @@
static void perf_top__update_print_entries(struct perf_top *top)
{
- top->print_entries = top->winsize.ws_row;
-
if (top->print_entries > 9)
top->print_entries -= 9;
}
@@ -100,6 +98,13 @@
struct perf_top *top = arg;
get_term_dimensions(&top->winsize);
+ if (!top->print_entries
+ || (top->print_entries+4) > top->winsize.ws_row) {
+ top->print_entries = top->winsize.ws_row;
+ } else {
+ top->print_entries += 4;
+ top->winsize.ws_row = top->print_entries;
+ }
perf_top__update_print_entries(top);
}
@@ -453,8 +458,10 @@
};
perf_top__sig_winch(SIGWINCH, NULL, top);
sigaction(SIGWINCH, &act, NULL);
- } else
+ } else {
+ perf_top__sig_winch(SIGWINCH, NULL, top);
signal(SIGWINCH, SIG_DFL);
+ }
break;
case 'E':
if (top->evlist->nr_entries > 1) {
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e7e0b0..ecd7f4d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2105,7 +2105,7 @@
strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
- size = strlen(name);
+ size = strlen(ev.event_type.event_type.name);
size = ALIGN(size, sizeof(u64));
ev.event_type.header.size = sizeof(ev.event_type) -
(sizeof(ev.event_type.event_type.name) - size);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900..29cb654 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,7 +19,6 @@
*
*/
-#define _GNU_SOURCE
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -33,7 +32,6 @@
#include <limits.h>
#include <elf.h>
-#undef _GNU_SOURCE
#include "util.h"
#include "event.h"
#include "string.h"
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 215d50f..0975438 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc..1a8d4dc 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,14 +21,13 @@
* The parts for function graph printing was taken and modified from the
* Linux Kernel that were written by Frederic Weisbecker.
*/
-#define _GNU_SOURCE
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
-#undef _GNU_SOURCE
#include "../perf.h"
#include "util.h"
#include "trace-event.h"
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 1212a38..e81aef1 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1,6 +1,4 @@
-#define _GNU_SOURCE
#include <stdio.h>
-#undef _GNU_SOURCE
#include "../libslang.h"
#include <stdlib.h>
#include <string.h>
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 6ef3c56..4f48f59 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -1,4 +1,3 @@
-#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b9c530c..ecf9898 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -40,7 +40,6 @@
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
#define _ALL_SOURCE 1
-#define _GNU_SOURCE 1
#define _BSD_SOURCE 1
#define HAS_BOOL