Merge tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"Slightly more than expected as rc7, but all are reasonablly small
fixes. A few additions of HD-audio fixup entries, a couple of other
regression fixes including a revert, and a few other trivial
oneliners."
* tag 'sound-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ASoC: sh: fix migor.c compilation
ALSA: HDA: Lessen CPU usage when waiting for chip to respond
Revert "ALSA: hda - Set codec to D3 forcibly even if not used"
ALSA: hda/realtek - Call alc_auto_parse_customize_define() always after fixup
ALSA: hdsp - Provide ioctl_compat
ALSA: hda/realtek - Add missing CD-input pin for MSI-7350 mobo
ALSA: hda/realtek - Add a fixup for Acer Aspire 5739G
ALSA: echoaudio: Remove incorrect part of assertion
diff --git a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
index 2a7f9a0..e960cd0 100644
--- a/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
+++ b/Documentation/ABI/stable/sysfs-driver-usb-usbtmc
@@ -1,5 +1,5 @@
-What: /sys/bus/usb/drivers/usbtmc/devices/*/interface_capabilities
-What: /sys/bus/usb/drivers/usbtmc/devices/*/device_capabilities
+What: /sys/bus/usb/drivers/usbtmc/*/interface_capabilities
+What: /sys/bus/usb/drivers/usbtmc/*/device_capabilities
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
@@ -12,8 +12,8 @@
The files are read only.
-What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_interface_capabilities
-What: /sys/bus/usb/drivers/usbtmc/devices/*/usb488_device_capabilities
+What: /sys/bus/usb/drivers/usbtmc/*/usb488_interface_capabilities
+What: /sys/bus/usb/drivers/usbtmc/*/usb488_device_capabilities
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
@@ -27,7 +27,7 @@
The files are read only.
-What: /sys/bus/usb/drivers/usbtmc/devices/*/TermChar
+What: /sys/bus/usb/drivers/usbtmc/*/TermChar
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
@@ -40,7 +40,7 @@
sent to the device or not.
-What: /sys/bus/usb/drivers/usbtmc/devices/*/TermCharEnabled
+What: /sys/bus/usb/drivers/usbtmc/*/TermCharEnabled
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
@@ -51,7 +51,7 @@
published by the USB-IF.
-What: /sys/bus/usb/drivers/usbtmc/devices/*/auto_abort
+What: /sys/bus/usb/drivers/usbtmc/*/auto_abort
Date: August 2008
Contact: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Description:
diff --git a/Documentation/ABI/testing/sysfs-block-rssd b/Documentation/ABI/testing/sysfs-block-rssd
new file mode 100644
index 0000000..d535757
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-block-rssd
@@ -0,0 +1,18 @@
+What: /sys/block/rssd*/registers
+Date: March 2012
+KernelVersion: 3.3
+Contact: Asai Thambi S P <asamymuthupa@micron.com>
+Description: This is a read-only file. Dumps below driver information and
+ hardware registers.
+ - S ACTive
+ - Command Issue
+ - Allocated
+ - Completed
+ - PORT IRQ STAT
+ - HOST IRQ STAT
+
+What: /sys/block/rssd*/status
+Date: April 2012
+KernelVersion: 3.4
+Contact: Asai Thambi S P <asamymuthupa@micron.com>
+Description: This is a read-only file. Indicates the status of the device.
diff --git a/Documentation/ABI/testing/sysfs-bus-hsi b/Documentation/ABI/testing/sysfs-bus-hsi
new file mode 100644
index 0000000..1b1b282
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-hsi
@@ -0,0 +1,19 @@
+What: /sys/bus/hsi
+Date: April 2012
+KernelVersion: 3.4
+Contact: Carlos Chinea <carlos.chinea@nokia.com>
+Description:
+ High Speed Synchronous Serial Interface (HSI) is a
+ serial interface mainly used for connecting application
+ engines (APE) with cellular modem engines (CMT) in cellular
+ handsets.
+ The bus will be populated with devices (hsi_clients) representing
+ the protocols available in the system. Bus drivers implement
+ those protocols.
+
+What: /sys/bus/hsi/devices/.../modalias
+Date: April 2012
+KernelVersion: 3.4
+Contact: Carlos Chinea <carlos.chinea@nokia.com>
+Description: Stores the same MODALIAS value emitted by uevent
+ Format: hsi:<hsi_client device name>
diff --git a/Documentation/ABI/testing/sysfs-cfq-target-latency b/Documentation/ABI/testing/sysfs-cfq-target-latency
new file mode 100644
index 0000000..df0f782
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-cfq-target-latency
@@ -0,0 +1,8 @@
+What: /sys/block/<device>/iosched/target_latency
+Date: March 2012
+contact: Tao Ma <boyu.mt@taobao.com>
+Description:
+ The /sys/block/<device>/iosched/target_latency only exists
+ when the user sets cfq to /sys/block/<device>/scheduler.
+ It contains an estimated latency time for the cfq. cfq will
+ use it to calculate the time slice used for every task.
diff --git a/Documentation/DMA-attributes.txt b/Documentation/DMA-attributes.txt
index b768cc0..5c72eed 100644
--- a/Documentation/DMA-attributes.txt
+++ b/Documentation/DMA-attributes.txt
@@ -31,3 +31,21 @@
Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
those that do not will simply ignore the attribute and exhibit default
behavior.
+
+DMA_ATTR_WRITE_COMBINE
+----------------------
+
+DMA_ATTR_WRITE_COMBINE specifies that writes to the mapping may be
+buffered to improve performance.
+
+Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE,
+those that do not will simply ignore the attribute and exhibit default
+behavior.
+
+DMA_ATTR_NON_CONSISTENT
+-----------------------
+
+DMA_ATTR_NON_CONSISTENT lets the platform to choose to return either
+consistent or non-consistent memory as it sees fit. By using this API,
+you are guaranteeing to the platform that you have all the correct and
+necessary sync points for this memory in the driver.
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 9c27e51..7514dbf 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -446,4 +446,21 @@
!Edrivers/i2c/i2c-core.c
</chapter>
+ <chapter id="hsi">
+ <title>High Speed Synchronous Serial Interface (HSI)</title>
+
+ <para>
+ High Speed Synchronous Serial Interface (HSI) is a
+ serial interface mainly used for connecting application
+ engines (APE) with cellular modem engines (CMT) in cellular
+ handsets.
+
+ HSI provides multiplexing for up to 16 logical channels,
+ low-latency and full duplex communication.
+ </para>
+
+!Iinclude/linux/hsi/hsi.h
+!Edrivers/hsi/hsi.c
+ </chapter>
+
</book>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
index 3fd3ce5..5274c24 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-nv12m.xml
@@ -1,6 +1,6 @@
<refentry id="V4L2-PIX-FMT-NV12M">
<refmeta>
- <refentrytitle>V4L2_PIX_FMT_NV12M ('NV12M')</refentrytitle>
+ <refentrytitle>V4L2_PIX_FMT_NV12M ('NM12')</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
index 9957863..60308f1 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-yuv420m.xml
@@ -1,6 +1,6 @@
<refentry id="V4L2-PIX-FMT-YUV420M">
<refmeta>
- <refentrytitle>V4L2_PIX_FMT_YUV420M ('YU12M')</refentrytitle>
+ <refentrytitle>V4L2_PIX_FMT_YUV420M ('YM12')</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5c51ed4..cefd3d8 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -217,7 +217,7 @@
The cpus and mems files in the root (top_cpuset) cpuset are
read-only. The cpus file automatically tracks the value of
-cpu_online_map using a CPU hotplug notifier, and the mems file
+cpu_online_mask using a CPU hotplug notifier, and the mems file
automatically tracks the value of node_states[N_HIGH_MEMORY]--i.e.,
nodes with memory--using the cpuset_track_online_nodes() hook.
diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt
index 4c95c00..9b1067a 100644
--- a/Documentation/cgroups/memory.txt
+++ b/Documentation/cgroups/memory.txt
@@ -34,8 +34,7 @@
Features:
- accounting anonymous pages, file caches, swap caches usage and limiting them.
- - private LRU and reclaim routine. (system's global LRU and private LRU
- work independently from each other)
+ - pages are linked to per-memcg LRU exclusively, and there is no global LRU.
- optionally, memory+swap usage can be accounted and limited.
- hierarchical accounting
- soft limit
@@ -154,7 +153,7 @@
2.2.1 Accounting details
All mapped anon pages (RSS) and cache pages (Page Cache) are accounted.
-Some pages which are never reclaimable and will not be on the global LRU
+Some pages which are never reclaimable and will not be on the LRU
are not accounted. We just account pages under usual VM management.
RSS pages are accounted at page_fault unless they've already been accounted
diff --git a/Documentation/cpu-hotplug.txt b/Documentation/cpu-hotplug.txt
index a20bfd4..66ef8f3 100644
--- a/Documentation/cpu-hotplug.txt
+++ b/Documentation/cpu-hotplug.txt
@@ -47,7 +47,7 @@
other cpus later online, read FAQ's for more info.
additional_cpus=n (*) Use this to limit hotpluggable cpus. This option sets
- cpu_possible_map = cpu_present_map + additional_cpus
+ cpu_possible_mask = cpu_present_mask + additional_cpus
cede_offline={"off","on"} Use this option to disable/enable putting offlined
processors to an extended H_CEDE state on
@@ -64,11 +64,11 @@
on the apicid values in those tables for disabled apics. In the event
BIOS doesn't mark such hot-pluggable cpus as disabled entries, one could
use this parameter "additional_cpus=x" to represent those cpus in the
-cpu_possible_map.
+cpu_possible_mask.
possible_cpus=n [s390,x86_64] use this to set hotpluggable cpus.
This option sets possible_cpus bits in
- cpu_possible_map. Thus keeping the numbers of bits set
+ cpu_possible_mask. Thus keeping the numbers of bits set
constant even if the machine gets rebooted.
CPU maps and such
@@ -76,7 +76,7 @@
[More on cpumaps and primitive to manipulate, please check
include/linux/cpumask.h that has more descriptive text.]
-cpu_possible_map: Bitmap of possible CPUs that can ever be available in the
+cpu_possible_mask: Bitmap of possible CPUs that can ever be available in the
system. This is used to allocate some boot time memory for per_cpu variables
that aren't designed to grow/shrink as CPUs are made available or removed.
Once set during boot time discovery phase, the map is static, i.e no bits
@@ -84,13 +84,13 @@
upfront can save some boot time memory. See below for how we use heuristics
in x86_64 case to keep this under check.
-cpu_online_map: Bitmap of all CPUs currently online. Its set in __cpu_up()
+cpu_online_mask: Bitmap of all CPUs currently online. Its set in __cpu_up()
after a cpu is available for kernel scheduling and ready to receive
interrupts from devices. Its cleared when a cpu is brought down using
__cpu_disable(), before which all OS services including interrupts are
migrated to another target CPU.
-cpu_present_map: Bitmap of CPUs currently present in the system. Not all
+cpu_present_mask: Bitmap of CPUs currently present in the system. Not all
of them may be online. When physical hotplug is processed by the relevant
subsystem (e.g ACPI) can change and new bit either be added or removed
from the map depending on the event is hot-add/hot-remove. There are currently
@@ -99,22 +99,22 @@
You really dont need to manipulate any of the system cpu maps. They should
be read-only for most use. When setting up per-cpu resources almost always use
-cpu_possible_map/for_each_possible_cpu() to iterate.
+cpu_possible_mask/for_each_possible_cpu() to iterate.
Never use anything other than cpumask_t to represent bitmap of CPUs.
#include <linux/cpumask.h>
- for_each_possible_cpu - Iterate over cpu_possible_map
- for_each_online_cpu - Iterate over cpu_online_map
- for_each_present_cpu - Iterate over cpu_present_map
+ for_each_possible_cpu - Iterate over cpu_possible_mask
+ for_each_online_cpu - Iterate over cpu_online_mask
+ for_each_present_cpu - Iterate over cpu_present_mask
for_each_cpu_mask(x,mask) - Iterate over some random collection of cpu mask.
#include <linux/cpu.h>
get_online_cpus() and put_online_cpus():
The above calls are used to inhibit cpu hotplug operations. While the
-cpu_hotplug.refcount is non zero, the cpu_online_map will not change.
+cpu_hotplug.refcount is non zero, the cpu_online_mask will not change.
If you merely need to avoid cpus going away, you could also use
preempt_disable() and preempt_enable() for those sections.
Just remember the critical section cannot call any
diff --git a/Documentation/devicetree/bindings/ata/calxeda-sata.txt b/Documentation/devicetree/bindings/ata/ahci-platform.txt
similarity index 90%
rename from Documentation/devicetree/bindings/ata/calxeda-sata.txt
rename to Documentation/devicetree/bindings/ata/ahci-platform.txt
index 79caa56..8bb8a76 100644
--- a/Documentation/devicetree/bindings/ata/calxeda-sata.txt
+++ b/Documentation/devicetree/bindings/ata/ahci-platform.txt
@@ -1,10 +1,10 @@
-* Calxeda SATA Controller
+* AHCI SATA Controller
SATA nodes are defined to describe on-chip Serial ATA controllers.
Each SATA controller should have its own node.
Required properties:
-- compatible : compatible list, contains "calxeda,hb-ahci"
+- compatible : compatible list, contains "calxeda,hb-ahci" or "snps,spear-ahci"
- interrupts : <interrupt mapping for SATA IRQ>
- reg : <registers mapping>
@@ -14,4 +14,3 @@
reg = <0xffe08000 0x1000>;
interrupts = <115>;
};
-
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index 5903ecf..a200695 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -27,13 +27,13 @@
reg = <0x40000000 0x10000000
0xffffe800 0x200
>;
- atmel,nand-addr-offset = <21>;
- atmel,nand-cmd-offset = <22>;
+ atmel,nand-addr-offset = <21>; /* ale */
+ atmel,nand-cmd-offset = <22>; /* cle */
nand-on-flash-bbt;
nand-ecc-mode = "soft";
- gpios = <&pioC 13 0
- &pioC 14 0
- 0
+ gpios = <&pioC 13 0 /* rdy */
+ &pioC 14 0 /* nce */
+ 0 /* cd */
>;
partition@0 {
...
diff --git a/Documentation/devicetree/bindings/regulator/anatop-regulator.txt b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
new file mode 100644
index 0000000..357758c
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/anatop-regulator.txt
@@ -0,0 +1,29 @@
+Anatop Voltage regulators
+
+Required properties:
+- compatible: Must be "fsl,anatop-regulator"
+- anatop-reg-offset: Anatop MFD register offset
+- anatop-vol-bit-shift: Bit shift for the register
+- anatop-vol-bit-width: Number of bits used in the register
+- anatop-min-bit-val: Minimum value of this register
+- anatop-min-voltage: Minimum voltage of this regulator
+- anatop-max-voltage: Maximum voltage of this regulator
+
+Any property defined as part of the core regulator
+binding, defined in regulator.txt, can also be used.
+
+Example:
+
+ regulator-vddpu {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vddpu";
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ anatop-reg-offset = <0x140>;
+ anatop-vol-bit-shift = <9>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <1>;
+ anatop-min-voltage = <725000>;
+ anatop-max-voltage = <1300000>;
+ };
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index c1be806..03ca210 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -6,14 +6,6 @@
---------------------------
-What: x86 floppy disable_hlt
-When: 2012
-Why: ancient workaround of dubious utility clutters the
- code used by everybody else.
-Who: Len Brown <len.brown@intel.com>
-
----------------------------
-
What: CONFIG_APM_CPU_IDLE, and its ability to call APM BIOS in idle
When: 2012
Why: This optional sub-feature of APM is of dubious reliability,
@@ -539,3 +531,11 @@
of ASLR. It was only ever intended for debugging, so it should be
removed.
Who: Kees Cook <keescook@chromium.org>
+
+----------------------------
+
+What: setitimer accepts user NULL pointer (value)
+When: 3.6
+Why: setitimer is not returning -EFAULT if user pointer is NULL. This
+ violates the spec.
+Who: Sasikantha Babu <sasikanth.v19@gmail.com>
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt
index e916e3d..0d04920 100644
--- a/Documentation/filesystems/vfs.txt
+++ b/Documentation/filesystems/vfs.txt
@@ -114,7 +114,7 @@
struct file_system_type {
const char *name;
int fs_flags;
- struct dentry (*mount) (struct file_system_type *, int,
+ struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *);
struct module *owner;
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp
index a10f736..90956b6 100644
--- a/Documentation/hwmon/k10temp
+++ b/Documentation/hwmon/k10temp
@@ -11,7 +11,7 @@
Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
-* AMD Family 15h processors: "Bulldozer"
+* AMD Family 15h processors: "Bulldozer" (FX-Series), "Trinity"
Prefix: 'k10temp'
Addresses scanned: PCI space
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 3b7488f..e34b531d 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -225,6 +225,7 @@
'j' 00-3F linux/joystick.h
'k' 00-0F linux/spi/spidev.h conflict!
'k' 00-05 video/kyro.h conflict!
+'k' 10-17 linux/hsi/hsi_char.h HSI character device
'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system
<http://web.archive.org/web/*/http://mikonos.dia.unisa.it/tcfs>
'l' 40-7F linux/udf_fs_i.h in development:
diff --git a/Documentation/networking/driver.txt b/Documentation/networking/driver.txt
index 03283da..da59e28 100644
--- a/Documentation/networking/driver.txt
+++ b/Documentation/networking/driver.txt
@@ -2,16 +2,16 @@
Transmit path guidelines:
-1) The hard_start_xmit method must never return '1' under any
- normal circumstances. It is considered a hard error unless
+1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under
+ any normal circumstances. It is considered a hard error unless
there is no way your device can tell ahead of time when it's
transmit function will become busy.
Instead it must maintain the queue properly. For example,
for a driver implementing scatter-gather this means:
- static int drv_hard_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
+ static netdev_tx_t drv_hard_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
struct drv *dp = netdev_priv(dev);
@@ -23,7 +23,7 @@
unlock_tx(dp);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
- return 1;
+ return NETDEV_TX_BUSY;
}
... queue packet to card ...
@@ -35,6 +35,7 @@
...
unlock_tx(dp);
...
+ return NETDEV_TX_OK;
}
And then at the end of your TX reclamation event handling:
@@ -58,15 +59,12 @@
TX_BUFFS_AVAIL(dp) > 0)
netif_wake_queue(dp->dev);
-2) Do not forget to update netdev->trans_start to jiffies after
- each new tx packet is given to the hardware.
-
-3) A hard_start_xmit method must not modify the shared parts of a
+2) An ndo_start_xmit method must not modify the shared parts of a
cloned SKB.
-4) Do not forget that once you return 0 from your hard_start_xmit
- method, it is your driver's responsibility to free up the SKB
- and in some finite amount of time.
+3) Do not forget that once you return NETDEV_TX_OK from your
+ ndo_start_xmit method, it is your driver's responsibility to free
+ up the SKB and in some finite amount of time.
For example, this means that it is not allowed for your TX
mitigation scheme to let TX packets "hang out" in the TX
@@ -74,8 +72,9 @@
This error can deadlock sockets waiting for send buffer room
to be freed up.
- If you return 1 from the hard_start_xmit method, you must not keep
- any reference to that SKB and you must not attempt to free it up.
+ If you return NETDEV_TX_BUSY from the ndo_start_xmit method, you
+ must not keep any reference to that SKB and you must not attempt
+ to free it up.
Probing guidelines:
@@ -85,10 +84,10 @@
Close/stop guidelines:
-1) After the dev->stop routine has been called, the hardware must
+1) After the ndo_stop routine has been called, the hardware must
not receive or transmit any data. All in flight packets must
be aborted. If necessary, poll or wait for completion of
any reset commands.
-2) The dev->stop routine will be called by unregister_netdevice
+2) The ndo_stop routine will be called by unregister_netdevice
if device is still UP.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index ad3e80e..1619a8c 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -147,7 +147,7 @@
(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
if it is <= 0.
Possible values are [-31, 31], inclusive.
- Default: 2
+ Default: 1
tcp_allowed_congestion_control - STRING
Show/set the congestion control choices available to non-privileged
@@ -410,7 +410,7 @@
net.core.rmem_max. Calling setsockopt() with SO_RCVBUF disables
automatic tuning of that socket's receive buffer size, in which
case this value is ignored.
- Default: between 87380B and 4MB, depending on RAM size.
+ Default: between 87380B and 6MB, depending on RAM size.
tcp_sack - BOOLEAN
Enable select acknowledgments (SACKS).
@@ -604,15 +604,8 @@
ip_local_port_range - 2 INTEGERS
Defines the local port range that is used by TCP and UDP to
choose the local port. The first number is the first, the
- second the last local port number. Default value depends on
- amount of memory available on the system:
- > 128Mb 32768-61000
- < 128Mb 1024-4999 or even less.
- This number defines number of active connections, which this
- system can issue simultaneously to systems not supporting
- TCP extensions (timestamps). With tcp_tw_recycle enabled
- (i.e. by default) range 1024-4999 is enough to issue up to
- 2000 connections per second to systems supporting timestamps.
+ second the last local port number. The default values are
+ 32768 and 61000 respectively.
ip_local_reserved_ports - list of comma separated ranges
Specify the ports which are reserved for known third-party
diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
index 8935834..c7ecc70 100644
--- a/Documentation/networking/netdevices.txt
+++ b/Documentation/networking/netdevices.txt
@@ -47,26 +47,25 @@
struct net_device synchronization rules
=======================================
-dev->open:
+ndo_open:
Synchronization: rtnl_lock() semaphore.
Context: process
-dev->stop:
+ndo_stop:
Synchronization: rtnl_lock() semaphore.
Context: process
- Note1: netif_running() is guaranteed false
- Note2: dev->poll() is guaranteed to be stopped
+ Note: netif_running() is guaranteed false
-dev->do_ioctl:
+ndo_do_ioctl:
Synchronization: rtnl_lock() semaphore.
Context: process
-dev->get_stats:
+ndo_get_stats:
Synchronization: dev_base_lock rwlock.
Context: nominally process, but don't sleep inside an rwlock
-dev->hard_start_xmit:
- Synchronization: netif_tx_lock spinlock.
+ndo_start_xmit:
+ Synchronization: __netif_tx_lock spinlock.
When the driver sets NETIF_F_LLTX in dev->features this will be
called without holding netif_tx_lock. In this case the driver
@@ -87,20 +86,20 @@
o NETDEV_TX_LOCKED Locking failed, please retry quickly.
Only valid when NETIF_F_LLTX is set.
-dev->tx_timeout:
- Synchronization: netif_tx_lock spinlock.
+ndo_tx_timeout:
+ Synchronization: netif_tx_lock spinlock; all TX queues frozen.
Context: BHs disabled
Notes: netif_queue_stopped() is guaranteed true
-dev->set_rx_mode:
- Synchronization: netif_tx_lock spinlock.
+ndo_set_rx_mode:
+ Synchronization: netif_addr_lock spinlock.
Context: BHs disabled
struct napi_struct synchronization rules
========================================
napi->poll:
Synchronization: NAPI_STATE_SCHED bit in napi->state. Device
- driver's dev->close method will invoke napi_disable() on
+ driver's ndo_stop method will invoke napi_disable() on
all NAPI instances which will do a sleeping poll on the
NAPI_STATE_SCHED napi->state bit, waiting for all pending
NAPI activity to cease.
diff --git a/Documentation/power/freezing-of-tasks.txt b/Documentation/power/freezing-of-tasks.txt
index ec715cd..6ec291e 100644
--- a/Documentation/power/freezing-of-tasks.txt
+++ b/Documentation/power/freezing-of-tasks.txt
@@ -9,7 +9,7 @@
II. How does it work?
-There are four per-task flags used for that, PF_NOFREEZE, PF_FROZEN, TIF_FREEZE
+There are three per-task flags used for that, PF_NOFREEZE, PF_FROZEN
and PF_FREEZER_SKIP (the last one is auxiliary). The tasks that have
PF_NOFREEZE unset (all user space processes and some kernel threads) are
regarded as 'freezable' and treated in a special way before the system enters a
@@ -17,30 +17,31 @@
we only consider hibernation, but the description also applies to suspend).
Namely, as the first step of the hibernation procedure the function
-freeze_processes() (defined in kernel/power/process.c) is called. It executes
-try_to_freeze_tasks() that sets TIF_FREEZE for all of the freezable tasks and
-either wakes them up, if they are kernel threads, or sends fake signals to them,
-if they are user space processes. A task that has TIF_FREEZE set, should react
-to it by calling the function called __refrigerator() (defined in
-kernel/freezer.c), which sets the task's PF_FROZEN flag, changes its state
-to TASK_UNINTERRUPTIBLE and makes it loop until PF_FROZEN is cleared for it.
-Then, we say that the task is 'frozen' and therefore the set of functions
-handling this mechanism is referred to as 'the freezer' (these functions are
-defined in kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h).
-User space processes are generally frozen before kernel threads.
+freeze_processes() (defined in kernel/power/process.c) is called. A system-wide
+variable system_freezing_cnt (as opposed to a per-task flag) is used to indicate
+whether the system is to undergo a freezing operation. And freeze_processes()
+sets this variable. After this, it executes try_to_freeze_tasks() that sends a
+fake signal to all user space processes, and wakes up all the kernel threads.
+All freezable tasks must react to that by calling try_to_freeze(), which
+results in a call to __refrigerator() (defined in kernel/freezer.c), which sets
+the task's PF_FROZEN flag, changes its state to TASK_UNINTERRUPTIBLE and makes
+it loop until PF_FROZEN is cleared for it. Then, we say that the task is
+'frozen' and therefore the set of functions handling this mechanism is referred
+to as 'the freezer' (these functions are defined in kernel/power/process.c,
+kernel/freezer.c & include/linux/freezer.h). User space processes are generally
+frozen before kernel threads.
__refrigerator() must not be called directly. Instead, use the
try_to_freeze() function (defined in include/linux/freezer.h), that checks
-the task's TIF_FREEZE flag and makes the task enter __refrigerator() if the
-flag is set.
+if the task is to be frozen and makes the task enter __refrigerator().
For user space processes try_to_freeze() is called automatically from the
signal-handling code, but the freezable kernel threads need to call it
explicitly in suitable places or use the wait_event_freezable() or
wait_event_freezable_timeout() macros (defined in include/linux/freezer.h)
-that combine interruptible sleep with checking if TIF_FREEZE is set and calling
-try_to_freeze(). The main loop of a freezable kernel thread may look like the
-following one:
+that combine interruptible sleep with checking if the task is to be frozen and
+calling try_to_freeze(). The main loop of a freezable kernel thread may look
+like the following one:
set_freezable();
do {
@@ -53,7 +54,7 @@
(from drivers/usb/core/hub.c::hub_thread()).
If a freezable kernel thread fails to call try_to_freeze() after the freezer has
-set TIF_FREEZE for it, the freezing of tasks will fail and the entire
+initiated a freezing operation, the freezing of tasks will fail and the entire
hibernation operation will be cancelled. For this reason, freezable kernel
threads must call try_to_freeze() somewhere or use one of the
wait_event_freezable() and wait_event_freezable_timeout() macros.
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt
index 7877170..d389acd 100644
--- a/Documentation/security/keys.txt
+++ b/Documentation/security/keys.txt
@@ -123,7 +123,7 @@
The key service provides a number of features besides keys:
- (*) The key service defines two special key types:
+ (*) The key service defines three special key types:
(+) "keyring"
@@ -137,6 +137,18 @@
blobs of data. These can be created, updated and read by userspace,
and aren't intended for use by kernel services.
+ (+) "logon"
+
+ Like a "user" key, a "logon" key has a payload that is an arbitrary
+ blob of data. It is intended as a place to store secrets which are
+ accessible to the kernel but not to userspace programs.
+
+ The description can be arbitrary, but must be prefixed with a non-zero
+ length string that describes the key "subclass". The subclass is
+ separated from the rest of the description by a ':'. "logon" keys can
+ be created and updated from userspace, but the payload is only
+ readable from kernel space.
+
(*) Each process subscribes to three keyrings: a thread-specific keyring, a
process-specific keyring, and a session-specific keyring.
diff --git a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt
index 8ffce74..00d2c64 100644
--- a/Documentation/usb/URB.txt
+++ b/Documentation/usb/URB.txt
@@ -168,6 +168,28 @@
they will get a -EPERM error. Thus you can be sure that when
usb_kill_urb() returns, the URB is totally idle.
+There is a lifetime issue to consider. An URB may complete at any
+time, and the completion handler may free the URB. If this happens
+while usb_unlink_urb or usb_kill_urb is running, it will cause a
+memory-access violation. The driver is responsible for avoiding this,
+which often means some sort of lock will be needed to prevent the URB
+from being deallocated while it is still in use.
+
+On the other hand, since usb_unlink_urb may end up calling the
+completion handler, the handler must not take any lock that is held
+when usb_unlink_urb is invoked. The general solution to this problem
+is to increment the URB's reference count while holding the lock, then
+drop the lock and call usb_unlink_urb or usb_kill_urb, and then
+decrement the URB's reference count. You increment the reference
+count by calling
+
+ struct urb *usb_get_urb(struct urb *urb)
+
+(ignore the return value; it is the same as the argument) and
+decrement the reference count by calling usb_free_urb. Of course,
+none of this is necessary if there's no danger of the URB being freed
+by the completion handler.
+
1.7. What about the completion handler?
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index 5335fa8..c42bb9c 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -183,10 +183,10 @@
d5ea89a0 3575914555 S Ci:1:001:0 s a3 00 0000 0003 0004 4 <
d5ea89a0 3575914560 C Ci:1:001:0 0 4 = 01050000
-An output bulk transfer to send a SCSI command 0x5E in a 31-byte Bulk wrapper
-to a storage device at address 5:
+An output bulk transfer to send a SCSI command 0x28 (READ_10) in a 31-byte
+Bulk wrapper to a storage device at address 5:
-dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 5e000000 00000000 00000600 00000000 00000000 00000000 000000
+dd65f0e8 4128379752 S Bo:1:005:2 -115 31 = 55534243 ad000000 00800000 80010a28 20000000 20000040 00000000 000000
dd65f0e8 4128379808 C Bo:1:005:2 0 31 >
* Raw binary format and API
diff --git a/MAINTAINERS b/MAINTAINERS
index 5190cf2..7071633 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -228,7 +228,7 @@
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
Q: http://patchwork.kernel.org/project/linux-acpi/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
S: Supported
F: drivers/acpi/
F: drivers/pnp/pnpacpi/
@@ -1251,7 +1251,6 @@
M: Jiri Slaby <jirislaby@gmail.com>
M: Nick Kossifidis <mickflemm@gmail.com>
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
-M: Bob Copeland <me@bobcopeland.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
W: http://wireless.kernel.org/en/users/Drivers/ath5k
@@ -1522,8 +1521,8 @@
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
S: Maintained
F: drivers/bluetooth/
@@ -1533,8 +1532,8 @@
M: Johan Hedberg <johan.hedberg@gmail.com>
L: linux-bluetooth@vger.kernel.org
W: http://www.bluez.org/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth.git
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/jh/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
S: Maintained
F: net/bluetooth/
F: include/net/bluetooth/
@@ -1969,10 +1968,7 @@
F: drivers/net/ethernet/ti/cpmac.c
CPU FREQUENCY DRIVERS
-M: Dave Jones <davej@redhat.com>
L: cpufreq@vger.kernel.org
-W: http://www.codemonkey.org.uk/projects/cpufreq/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
S: Maintained
F: drivers/cpufreq/
F: include/linux/cpufreq.h
@@ -2322,9 +2318,9 @@
F: drivers/acpi/dock.c
DOCUMENTATION
-M: Randy Dunlap <rdunlap@xenotime.net>
+M: Rob Landley <rob@landley.net>
L: linux-doc@vger.kernel.org
-T: quilt http://xenotime.net/kernel-doc-patches/current/
+T: TBD
S: Maintained
F: Documentation/
@@ -2451,17 +2447,17 @@
EDAC-CORE
M: Doug Thompson <dougthompson@xmission.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Supported
F: Documentation/edac.txt
-F: drivers/edac/edac_*
+F: drivers/edac/
F: include/linux/edac.h
EDAC-AMD64
M: Doug Thompson <dougthompson@xmission.com>
M: Borislav Petkov <borislav.petkov@amd.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Supported
F: drivers/edac/amd64_edac*
@@ -2469,35 +2465,35 @@
EDAC-E752X
M: Mark Gross <mark.gross@intel.com>
M: Doug Thompson <dougthompson@xmission.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e752x_edac.c
EDAC-E7XXX
M: Doug Thompson <dougthompson@xmission.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/e7xxx_edac.c
EDAC-I82443BXGX
M: Tim Small <tim@buttersideup.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82443bxgx_edac.c
EDAC-I3000
M: Jason Uhlenkott <juhlenko@akamai.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i3000_edac.c
EDAC-I5000
M: Doug Thompson <dougthompson@xmission.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5000_edac.c
@@ -2526,21 +2522,21 @@
EDAC-I82975X
M: Ranganathan Desikan <ravi@jetztechnologies.com>
M: "Arvind R." <arvino55@gmail.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i82975x_edac.c
EDAC-PASEMI
M: Egor Martovetsky <egor@pasemi.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/pasemi_edac.c
EDAC-R82600
M: Tim Small <tim@buttersideup.com>
-L: bluesmoke-devel@lists.sourceforge.net (moderated for non-subscribers)
+L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/r82600_edac.c
@@ -3557,17 +3553,13 @@
S: Supported
F: arch/x86/platform/mrst/pmu.*
-INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
+INTEL PRO/WIRELESS 2100, 2200BG, 2915ABG NETWORK CONNECTION SUPPORT
+M: Stanislav Yakovlev <stas.yakovlev@gmail.com>
L: linux-wireless@vger.kernel.org
-S: Orphan
+S: Maintained
F: Documentation/networking/README.ipw2100
-F: drivers/net/wireless/ipw2x00/ipw2100.*
-
-INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
-L: linux-wireless@vger.kernel.org
-S: Orphan
F: Documentation/networking/README.ipw2200
-F: drivers/net/wireless/ipw2x00/ipw2200.*
+F: drivers/net/wireless/ipw2x00/
INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
M: Joseph Cihula <joseph.cihula@intel.com>
@@ -3597,6 +3589,7 @@
F: drivers/net/wireless/iwlegacy/
INTEL WIRELESS WIFI LINK (iwlwifi)
+M: Johannes Berg <johannes.berg@intel.com>
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
M: Intel Linux Wireless <ilw@linux.intel.com>
L: linux-wireless@vger.kernel.org
@@ -4314,6 +4307,13 @@
L: linux-man@vger.kernel.org
S: Maintained
+MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
+M: Mirko Lindner <mlindner@marvell.com>
+M: Stephen Hemminger <shemminger@vyatta.com>
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/ethernet/marvell/sk*
+
MARVELL LIBERTAS WIRELESS DRIVER
M: Dan Williams <dcbw@redhat.com>
L: libertas-dev@lists.infradead.org
@@ -4344,12 +4344,6 @@
S: Odd Fixes
F: drivers/mmc/host/mvsdio.*
-MARVELL YUKON / SYSKONNECT DRIVER
-M: Mirko Lindner <mlindner@syskonnect.de>
-M: Ralph Roesler <rroesler@syskonnect.de>
-W: http://www.syskonnect.com
-S: Supported
-
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
@@ -4537,8 +4531,7 @@
F: drivers/net/ethernet/myricom/myri10ge/
NATSEMI ETHERNET DRIVER (DP8381x)
-M: Tim Hockin <thockin@hockin.org>
-S: Maintained
+S: Orphan
F: drivers/net/ethernet/natsemi/natsemi.c
NATIVE INSTRUMENTS USB SOUND INTERFACE DRIVER
@@ -5122,6 +5115,11 @@
F: include/linux/i2c-algo-pca.h
F: include/linux/i2c-pca-platform.h
+PCDP - PRIMARY CONSOLE AND DEBUG PORT
+M: Khalid Aziz <khalid.aziz@hp.com>
+S: Maintained
+F: drivers/firmware/pcdp.*
+
PCI ERROR RECOVERY
M: Linas Vepstas <linasvepstas@gmail.com>
L: linux-pci@vger.kernel.org
@@ -5643,7 +5641,7 @@
S: Maintained
F: drivers/remoteproc/
F: Documentation/remoteproc.txt
-F: include/linux/remoteproc.txt
+F: include/linux/remoteproc.h
RFKILL
M: Johannes Berg <johannes@sipsolutions.net>
@@ -5891,11 +5889,11 @@
F: drivers/scsi/st*
SCTP PROTOCOL
-M: Vlad Yasevich <vladislav.yasevich@hp.com>
+M: Vlad Yasevich <vyasevich@gmail.com>
M: Sridhar Samudrala <sri@us.ibm.com>
L: linux-sctp@vger.kernel.org
W: http://lksctp.sourceforge.net
-S: Supported
+S: Maintained
F: Documentation/networking/sctp.txt
F: include/linux/sctp.h
F: include/net/sctp/
@@ -6122,12 +6120,6 @@
S: Maintained
F: drivers/usb/misc/sisusbvga/
-SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
-M: Stephen Hemminger <shemminger@vyatta.com>
-L: netdev@vger.kernel.org
-S: Maintained
-F: drivers/net/ethernet/marvell/sk*
-
SLAB ALLOCATOR
M: Christoph Lameter <cl@linux-foundation.org>
M: Pekka Enberg <penberg@kernel.org>
@@ -6293,6 +6285,15 @@
F: drivers/tty/serial/sunzilog.c
F: drivers/tty/serial/sunzilog.h
+SPARSE CHECKER
+M: "Christopher Li" <sparse@chrisli.org>
+L: linux-sparse@vger.kernel.org
+W: https://sparse.wiki.kernel.org/
+T: git git://git.kernel.org/pub/scm/devel/sparse/sparse.git
+T: git git://git.kernel.org/pub/scm/devel/sparse/chrisl/sparse.git
+S: Maintained
+F: include/linux/compiler.h
+
SPEAR PLATFORM SUPPORT
M: Viresh Kumar <viresh.kumar@st.com>
L: spear-devel@list.st.com
@@ -6468,6 +6469,7 @@
F: drivers/staging/olpc_dcon/
STAGING - OZMO DEVICES USB OVER WIFI DRIVER
+M: Rupesh Gujare <rgujare@ozmodevices.com>
M: Chris Kelly <ckelly@ozmodevices.com>
S: Maintained
F: drivers/staging/ozwpan/
@@ -7574,8 +7576,8 @@
F: fs/xfs/
XILINX AXI ETHERNET DRIVER
-M: Ariane Keller <ariane.keller@tik.ee.ethz.ch>
-M: Daniel Borkmann <daniel.borkmann@tik.ee.ethz.ch>
+M: Anirudha Sarangi <anirudh@xilinx.com>
+M: John Linn <John.Linn@xilinx.com>
S: Maintained
F: drivers/net/ethernet/xilinx/xilinx_axienet*
diff --git a/Makefile b/Makefile
index 5e637c2..9e384ae 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 4
SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc6
NAME = Saber-toothed Squirrel
# *DOCUMENTATION*
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 56a4df9..22e58a9 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -477,7 +477,7 @@
config VGA_HOSE
bool
- depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI
+ depends on VGA_CONSOLE && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI)
default y
help
Support VGA on an arbitrary hose; needed for several platforms
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index f62251e..3bb7ffe 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <asm/barrier.h>
+#include <asm/cmpxchg.h>
/*
* Atomic operations that C can't guarantee us. Useful for
@@ -168,73 +169,6 @@
return result;
}
-/*
- * Atomic exchange routines.
- */
-
-#define __ASM__MB
-#define ____xchg(type, args...) __xchg ## type ## _local(args)
-#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args)
-#include <asm/xchg.h>
-
-#define xchg_local(ptr,x) \
- ({ \
- __typeof__(*(ptr)) _x_ = (x); \
- (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \
- sizeof(*(ptr))); \
- })
-
-#define cmpxchg_local(ptr, o, n) \
- ({ \
- __typeof__(*(ptr)) _o_ = (o); \
- __typeof__(*(ptr)) _n_ = (n); \
- (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
- (unsigned long)_n_, \
- sizeof(*(ptr))); \
- })
-
-#define cmpxchg64_local(ptr, o, n) \
- ({ \
- BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
- cmpxchg_local((ptr), (o), (n)); \
- })
-
-#ifdef CONFIG_SMP
-#undef __ASM__MB
-#define __ASM__MB "\tmb\n"
-#endif
-#undef ____xchg
-#undef ____cmpxchg
-#define ____xchg(type, args...) __xchg ##type(args)
-#define ____cmpxchg(type, args...) __cmpxchg ##type(args)
-#include <asm/xchg.h>
-
-#define xchg(ptr,x) \
- ({ \
- __typeof__(*(ptr)) _x_ = (x); \
- (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \
- sizeof(*(ptr))); \
- })
-
-#define cmpxchg(ptr, o, n) \
- ({ \
- __typeof__(*(ptr)) _o_ = (o); \
- __typeof__(*(ptr)) _n_ = (n); \
- (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
- (unsigned long)_n_, sizeof(*(ptr)));\
- })
-
-#define cmpxchg64(ptr, o, n) \
- ({ \
- BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
- cmpxchg((ptr), (o), (n)); \
- })
-
-#undef __ASM__MB
-#undef ____cmpxchg
-
-#define __HAVE_ARCH_CMPXCHG 1
-
#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h
new file mode 100644
index 0000000..429e8cd
--- /dev/null
+++ b/arch/alpha/include/asm/cmpxchg.h
@@ -0,0 +1,71 @@
+#ifndef _ALPHA_CMPXCHG_H
+#define _ALPHA_CMPXCHG_H
+
+/*
+ * Atomic exchange routines.
+ */
+
+#define __ASM__MB
+#define ____xchg(type, args...) __xchg ## type ## _local(args)
+#define ____cmpxchg(type, args...) __cmpxchg ## type ## _local(args)
+#include <asm/xchg.h>
+
+#define xchg_local(ptr, x) \
+({ \
+ __typeof__(*(ptr)) _x_ = (x); \
+ (__typeof__(*(ptr))) __xchg_local((ptr), (unsigned long)_x_, \
+ sizeof(*(ptr))); \
+})
+
+#define cmpxchg_local(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg_local((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, \
+ sizeof(*(ptr))); \
+})
+
+#define cmpxchg64_local(ptr, o, n) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg_local((ptr), (o), (n)); \
+})
+
+#ifdef CONFIG_SMP
+#undef __ASM__MB
+#define __ASM__MB "\tmb\n"
+#endif
+#undef ____xchg
+#undef ____cmpxchg
+#define ____xchg(type, args...) __xchg ##type(args)
+#define ____cmpxchg(type, args...) __cmpxchg ##type(args)
+#include <asm/xchg.h>
+
+#define xchg(ptr, x) \
+({ \
+ __typeof__(*(ptr)) _x_ = (x); \
+ (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \
+ sizeof(*(ptr))); \
+})
+
+#define cmpxchg(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr)));\
+})
+
+#define cmpxchg64(ptr, o, n) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg((ptr), (o), (n)); \
+})
+
+#undef __ASM__MB
+#undef ____cmpxchg
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+#endif /* _ALPHA_CMPXCHG_H */
diff --git a/arch/alpha/include/asm/dma-mapping.h b/arch/alpha/include/asm/dma-mapping.h
index 4567aca..dfa32f0 100644
--- a/arch/alpha/include/asm/dma-mapping.h
+++ b/arch/alpha/include/asm/dma-mapping.h
@@ -12,16 +12,22 @@
#include <asm-generic/dma-mapping-common.h>
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
- return get_dma_ops(dev)->alloc_coherent(dev, size, dma_handle, gfp);
+ return get_dma_ops(dev)->alloc(dev, size, dma_handle, gfp, attrs);
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
- get_dma_ops(dev)->free_coherent(dev, size, vaddr, dma_handle);
+ get_dma_ops(dev)->free(dev, size, vaddr, dma_handle, attrs);
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
diff --git a/arch/alpha/include/asm/rtc.h b/arch/alpha/include/asm/rtc.h
index 1f7fba6..d70408d 100644
--- a/arch/alpha/include/asm/rtc.h
+++ b/arch/alpha/include/asm/rtc.h
@@ -1,14 +1,10 @@
#ifndef _ALPHA_RTC_H
#define _ALPHA_RTC_H
-#if defined(CONFIG_ALPHA_GENERIC)
+#if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP) \
+ || defined(CONFIG_ALPHA_GENERIC)
# define get_rtc_time alpha_mv.rtc_get_time
# define set_rtc_time alpha_mv.rtc_set_time
-#else
-# if defined(CONFIG_ALPHA_MARVEL) && defined(CONFIG_SMP)
-# define get_rtc_time marvel_get_rtc_time
-# define set_rtc_time marvel_set_rtc_time
-# endif
#endif
#include <asm-generic/rtc.h>
diff --git a/arch/alpha/include/asm/xchg.h b/arch/alpha/include/asm/xchg.h
index 1d1b436..0ca9724 100644
--- a/arch/alpha/include/asm/xchg.h
+++ b/arch/alpha/include/asm/xchg.h
@@ -1,10 +1,10 @@
-#ifndef _ALPHA_ATOMIC_H
+#ifndef _ALPHA_CMPXCHG_H
#error Do not include xchg.h directly!
#else
/*
* xchg/xchg_local and cmpxchg/cmpxchg_local share the same code
* except that local version do not have the expensive memory barrier.
- * So this file is included twice from asm/system.h.
+ * So this file is included twice from asm/cmpxchg.h.
*/
/*
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
index 5e7c28f..61893d7 100644
--- a/arch/alpha/kernel/core_tsunami.c
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -11,6 +11,7 @@
#include <asm/core_tsunami.h>
#undef __EXTERN_INLINE
+#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
index 04eea48..df24b76 100644
--- a/arch/alpha/kernel/pci-noop.c
+++ b/arch/alpha/kernel/pci-noop.c
@@ -108,7 +108,8 @@
}
static void *alpha_noop_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
void *ret;
@@ -123,7 +124,8 @@
}
static void alpha_noop_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr)
+ void *cpu_addr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
{
free_pages((unsigned long)cpu_addr, get_order(size));
}
@@ -174,8 +176,8 @@
}
struct dma_map_ops alpha_noop_ops = {
- .alloc_coherent = alpha_noop_alloc_coherent,
- .free_coherent = alpha_noop_free_coherent,
+ .alloc = alpha_noop_alloc_coherent,
+ .free = alpha_noop_free_coherent,
.map_page = alpha_noop_map_page,
.map_sg = alpha_noop_map_sg,
.mapping_error = alpha_noop_mapping_error,
diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
index 4361080..cd63479 100644
--- a/arch/alpha/kernel/pci_iommu.c
+++ b/arch/alpha/kernel/pci_iommu.c
@@ -434,7 +434,8 @@
else DMA_ADDRP is undefined. */
static void *alpha_pci_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addrp, gfp_t gfp)
+ dma_addr_t *dma_addrp, gfp_t gfp,
+ struct dma_attrs *attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
void *cpu_addr;
@@ -478,7 +479,8 @@
DMA_ADDR past this call are illegal. */
static void alpha_pci_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_addr)
+ void *cpu_addr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
{
struct pci_dev *pdev = alpha_gendev_to_pci(dev);
pci_unmap_single(pdev, dma_addr, size, PCI_DMA_BIDIRECTIONAL);
@@ -952,8 +954,8 @@
}
struct dma_map_ops alpha_pci_ops = {
- .alloc_coherent = alpha_pci_alloc_coherent,
- .free_coherent = alpha_pci_free_coherent,
+ .alloc = alpha_pci_alloc_coherent,
+ .free = alpha_pci_free_coherent,
.map_page = alpha_pci_map_page,
.unmap_page = alpha_pci_unmap_page,
.map_sg = alpha_pci_map_sg,
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 6f7feb5..35f2ef4 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -120,12 +120,13 @@
*/
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(¤t->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(¤t->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -238,10 +239,7 @@
goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(sc, regs, sw))
goto give_sigsegv;
@@ -276,10 +274,7 @@
goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
goto give_sigsegv;
@@ -501,14 +496,8 @@
else
ret = setup_frame(sig, ka, oldset, regs, sw);
- if (ret == 0) {
- spin_lock_irq(¤t->sighand->siglock);
- sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(¤t->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);
return ret;
}
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 4087a56..50d438d 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -450,7 +450,7 @@
smp_num_probed = 1;
}
- printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
+ printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
smp_num_probed, cpumask_bits(cpu_present_mask)[0]);
}
diff --git a/arch/alpha/kernel/sys_marvel.c b/arch/alpha/kernel/sys_marvel.c
index 14a4b6a..407accc 100644
--- a/arch/alpha/kernel/sys_marvel.c
+++ b/arch/alpha/kernel/sys_marvel.c
@@ -317,7 +317,7 @@
}
static int
-marvel_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+marvel_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
{
struct pci_controller *hose = dev->sysdata;
struct io7_port *io7_port = hose->sysdata;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9318084..36586dba 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -338,6 +338,7 @@
select HAVE_CLK
select CLKDEV_LOOKUP
select IRQ_DOMAIN
+ select NEED_MACH_IO_H if PCCARD
help
This enables support for systems based on the Atmel AT91RM9200,
AT91SAM9 processors.
@@ -1185,6 +1186,15 @@
source "arch/arm/Kconfig-nommu"
endif
+config ARM_ERRATA_326103
+ bool "ARM errata: FSR write bit incorrect on a SWP to read-only memory"
+ depends on CPU_V6
+ help
+ Executing a SWP instruction to read-only memory does not set bit 11
+ of the FSR on the ARM 1136 prior to r1p0. This causes the kernel to
+ treat the access as a read, preventing a COW from occurring and
+ causing the faulting task to livelock.
+
config ARM_ERRATA_411920
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
depends on CPU_V6 || CPU_V6K
diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
index 6ce11c4..797f04b 100644
--- a/arch/arm/boot/compressed/atags_to_fdt.c
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -77,6 +77,8 @@
} else if (atag->hdr.tag == ATAG_MEM) {
if (memcount >= sizeof(mem_reg_property)/4)
continue;
+ if (!atag->u.mem.size)
+ continue;
mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
} else if (atag->hdr.tag == ATAG_INITRD2) {
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 5f6045f..dc7e8ce 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -273,7 +273,7 @@
add r0, r0, #0x100
mov r1, r6
sub r2, sp, r6
- blne atags_to_fdt
+ bleq atags_to_fdt
ldmfd sp!, {r0-r3, ip, lr}
sub sp, sp, #0x10000
diff --git a/arch/arm/boot/dts/at91sam9g20.dtsi b/arch/arm/boot/dts/at91sam9g20.dtsi
index 92f3662..773ef48 100644
--- a/arch/arm/boot/dts/at91sam9g20.dtsi
+++ b/arch/arm/boot/dts/at91sam9g20.dtsi
@@ -35,7 +35,7 @@
};
};
- memory@20000000 {
+ memory {
reg = <0x20000000 0x08000000>;
};
@@ -55,7 +55,6 @@
#interrupt-cells = <2>;
compatible = "atmel,at91rm9200-aic";
interrupt-controller;
- interrupt-parent;
reg = <0xfffff000 0x200>;
};
diff --git a/arch/arm/boot/dts/at91sam9g25ek.dts b/arch/arm/boot/dts/at91sam9g25ek.dts
index ac0dc00..7829a4d 100644
--- a/arch/arm/boot/dts/at91sam9g25ek.dts
+++ b/arch/arm/boot/dts/at91sam9g25ek.dts
@@ -37,8 +37,8 @@
usb0: ohci@00600000 {
status = "okay";
num-ports = <2>;
- atmel,vbus-gpio = <&pioD 19 0
- &pioD 20 0
+ atmel,vbus-gpio = <&pioD 19 1
+ &pioD 20 1
>;
};
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 3d0c32f..c804214 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -36,7 +36,7 @@
};
};
- memory@70000000 {
+ memory {
reg = <0x70000000 0x10000000>;
};
@@ -56,7 +56,6 @@
#interrupt-cells = <2>;
compatible = "atmel,at91rm9200-aic";
interrupt-controller;
- interrupt-parent;
reg = <0xfffff000 0x200>;
};
diff --git a/arch/arm/boot/dts/at91sam9m10g45ek.dts b/arch/arm/boot/dts/at91sam9m10g45ek.dts
index c4c8ae4..a3633bd 100644
--- a/arch/arm/boot/dts/at91sam9m10g45ek.dts
+++ b/arch/arm/boot/dts/at91sam9m10g45ek.dts
@@ -17,7 +17,7 @@
bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=jffs2";
};
- memory@70000000 {
+ memory {
reg = <0x70000000 0x4000000>;
};
@@ -73,8 +73,8 @@
usb0: ohci@00700000 {
status = "okay";
num-ports = <2>;
- atmel,vbus-gpio = <&pioD 1 0
- &pioD 3 0>;
+ atmel,vbus-gpio = <&pioD 1 1
+ &pioD 3 1>;
};
usb1: ehci@00800000 {
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index c111001..dd4ed74 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -34,7 +34,7 @@
};
};
- memory@20000000 {
+ memory {
reg = <0x20000000 0x10000000>;
};
@@ -54,7 +54,6 @@
#interrupt-cells = <2>;
compatible = "atmel,at91rm9200-aic";
interrupt-controller;
- interrupt-parent;
reg = <0xfffff000 0x200>;
};
@@ -201,8 +200,8 @@
>;
atmel,nand-addr-offset = <21>;
atmel,nand-cmd-offset = <22>;
- gpios = <&pioC 8 0
- &pioC 14 0
+ gpios = <&pioD 5 0
+ &pioD 4 0
0
>;
status = "disabled";
diff --git a/arch/arm/boot/dts/at91sam9x5cm.dtsi b/arch/arm/boot/dts/at91sam9x5cm.dtsi
index 67936f8..31e7be2 100644
--- a/arch/arm/boot/dts/at91sam9x5cm.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5cm.dtsi
@@ -8,7 +8,7 @@
*/
/ {
- memory@20000000 {
+ memory {
reg = <0x20000000 0x8000000>;
};
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi
index d73dce6..14bc307 100644
--- a/arch/arm/boot/dts/db8500.dtsi
+++ b/arch/arm/boot/dts/db8500.dtsi
@@ -24,7 +24,6 @@
#interrupt-cells = <3>;
#address-cells = <1>;
interrupt-controller;
- interrupt-parent;
reg = <0xa0411000 0x1000>,
<0xa0410100 0x100>;
};
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts
index 37c0ff9c..83e7229 100644
--- a/arch/arm/boot/dts/highbank.dts
+++ b/arch/arm/boot/dts/highbank.dts
@@ -89,7 +89,6 @@
#size-cells = <0>;
#address-cells = <1>;
interrupt-controller;
- interrupt-parent;
reg = <0xfff11000 0x1000>,
<0xfff10100 0x100>;
};
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 15ded0d..45bc4bb 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -10,7 +10,7 @@
intc: interrupt-controller@02080000 {
compatible = "qcom,msm-8660-qgic";
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <3>;
reg = < 0x02080000 0x1000 >,
< 0x02081000 0x1000 >;
};
@@ -19,6 +19,6 @@
compatible = "qcom,msm-hsuart", "qcom,msm-uart";
reg = <0x19c40000 0x1000>,
<0x19c00000 0x1000>;
- interrupts = <195>;
+ interrupts = <0 195 0x0>;
};
};
diff --git a/arch/arm/boot/dts/usb_a9g20.dts b/arch/arm/boot/dts/usb_a9g20.dts
index 3b3c4e0..7c2399c 100644
--- a/arch/arm/boot/dts/usb_a9g20.dts
+++ b/arch/arm/boot/dts/usb_a9g20.dts
@@ -16,7 +16,7 @@
bootargs = "mem=64M console=ttyS0,115200 root=/dev/mtdblock5 rw rootfstype=ubifs";
};
- memory@20000000 {
+ memory {
reg = <0x20000000 0x4000000>;
};
diff --git a/arch/arm/boot/dts/versatile-ab.dts b/arch/arm/boot/dts/versatile-ab.dts
index 0b32925..e2fe319 100644
--- a/arch/arm/boot/dts/versatile-ab.dts
+++ b/arch/arm/boot/dts/versatile-ab.dts
@@ -173,7 +173,7 @@
mmc@5000 {
compatible = "arm,primecell";
reg = < 0x5000 0x1000>;
- interrupts = <22>;
+ interrupts = <22 34>;
};
kmi@6000 {
compatible = "arm,pl050", "arm,primecell";
diff --git a/arch/arm/boot/dts/versatile-pb.dts b/arch/arm/boot/dts/versatile-pb.dts
index 1664610..7e81752 100644
--- a/arch/arm/boot/dts/versatile-pb.dts
+++ b/arch/arm/boot/dts/versatile-pb.dts
@@ -41,7 +41,7 @@
mmc@b000 {
compatible = "arm,primecell";
reg = <0xb000 0x1000>;
- interrupts = <23>;
+ interrupts = <23 34>;
};
};
};
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 7a66311..7e288f9 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -427,19 +427,18 @@
/*
* Handle each interrupt in a single VIC. Returns non-zero if we've
- * handled at least one interrupt. This does a single read of the
- * status register and handles all interrupts in order from LSB first.
+ * handled at least one interrupt. This reads the status register
+ * before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
*/
static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
{
u32 stat, irq;
int handled = 0;
- stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
- while (stat) {
+ while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
irq = ffs(stat) - 1;
handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
- stat &= ~(1 << irq);
handled = 1;
}
diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index b5ac644..6b31cb6 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -112,6 +112,7 @@
CONFIG_IMX2_WDT=y
CONFIG_MFD_MC13XXX=y
CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_FB=y
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index 42da918..082175c 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -14,6 +14,8 @@
# CONFIG_BLK_DEV_BSG is not set
CONFIG_BLK_DEV_INTEGRITY=y
CONFIG_ARCH_S3C24XX=y
+# CONFIG_CPU_S3C2410 is not set
+CONFIG_CPU_S3C2440=y
CONFIG_S3C_ADC=y
CONFIG_S3C24XX_PWM=y
CONFIG_MACH_MINI2440=y
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig
index 889d73a..7e84f45 100644
--- a/arch/arm/configs/u8500_defconfig
+++ b/arch/arm/configs/u8500_defconfig
@@ -8,8 +8,6 @@
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
CONFIG_ARCH_U8500=y
-CONFIG_UX500_SOC_DB5500=y
-CONFIG_UX500_SOC_DB8500=y
CONFIG_MACH_HREFV60=y
CONFIG_MACH_SNOWBALL=y
CONFIG_MACH_U5500=y
@@ -39,7 +37,6 @@
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=65536
-CONFIG_MISC_DEVICES=y
CONFIG_AB8500_PWM=y
CONFIG_SENSORS_BH1780=y
CONFIG_NETDEVICES=y
@@ -65,16 +62,18 @@
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_NOMADIK=y
-CONFIG_I2C=y
-CONFIG_I2C_NOMADIK=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
CONFIG_GPIO_STMPE=y
CONFIG_GPIO_TC3589X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_AB8500_BM=y
+CONFIG_AB8500_BATTERY_THERM_ON_BATCTRL=y
CONFIG_MFD_STMPE=y
CONFIG_MFD_TC3589X=y
CONFIG_AB5500_CORE=y
CONFIG_AB8500_CORE=y
+CONFIG_REGULATOR=y
CONFIG_REGULATOR_AB8500=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB_GADGET=y
diff --git a/arch/arm/include/asm/barrier.h b/arch/arm/include/asm/barrier.h
index 44f4a09..0511238 100644
--- a/arch/arm/include/asm/barrier.h
+++ b/arch/arm/include/asm/barrier.h
@@ -2,6 +2,7 @@
#define __ASM_BARRIER_H
#ifndef __ASSEMBLY__
+#include <asm/outercache.h>
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
@@ -39,7 +40,6 @@
#ifdef CONFIG_ARCH_HAS_BARRIERS
#include <mach/barriers.h>
#elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
-#include <asm/outercache.h>
#define mb() do { dsb(); outer_sync(); } while (0)
#define rmb() dsb()
#define wmb() mb()
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index df0ac0b..9af5563 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -119,7 +119,7 @@
#ifdef CONFIG_NEED_MACH_IO_H
#include <mach/io.h>
#else
-#define __io(a) ({ (void)(a); __typesafe_io(0); })
+#define __io(a) __typesafe_io((a) & IO_SPACE_LIMIT)
#endif
/*
diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 5c5ca2e..bfc198c 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -14,7 +14,7 @@
#define JUMP_LABEL_NOP "nop"
#endif
-static __always_inline bool arch_static_branch(struct jump_label_key *key)
+static __always_inline bool arch_static_branch(struct static_key *key)
{
asm goto("1:\n\t"
JUMP_LABEL_NOP "\n\t"
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index d4c24d4..0f04d84 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -118,6 +118,13 @@
extern void vfp_sync_hwstate(struct thread_info *);
extern void vfp_flush_hwstate(struct thread_info *);
+struct user_vfp;
+struct user_vfp_exc;
+
+extern int vfp_preserve_user_clear_hwstate(struct user_vfp __user *,
+ struct user_vfp_exc __user *);
+extern int vfp_restore_user_hwstate(struct user_vfp __user *,
+ struct user_vfp_exc __user *);
#endif
/*
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index 60843eb..73409e6 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -7,6 +7,8 @@
.macro set_tls_v6k, tp, tmp1, tmp2
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register
+ mov \tmp1, #0
+ mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
.endm
.macro set_tls_v6, tp, tmp1, tmp2
@@ -15,6 +17,8 @@
mov \tmp2, #0xffff0fff
tst \tmp1, #HWCAP_TLS @ hardware TLS available?
mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register
+ movne \tmp1, #0
+ mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0
.endm
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 632df9a..ede5f77 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -299,7 +299,6 @@
*/
void pcibios_fixup_bus(struct pci_bus *bus)
{
- struct pci_sys_data *root = bus->sysdata;
struct pci_dev *dev;
u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
diff --git a/arch/arm/kernel/insn.c b/arch/arm/kernel/insn.c
index ab312e5..b760340 100644
--- a/arch/arm/kernel/insn.c
+++ b/arch/arm/kernel/insn.c
@@ -1,3 +1,4 @@
+#include <linux/bug.h>
#include <linux/kernel.h>
#include <asm/opcodes.h>
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 71ccdbf..8349d4e97 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -155,10 +155,10 @@
}
c = irq_data_get_irq_chip(d);
- if (c->irq_set_affinity)
- c->irq_set_affinity(d, affinity, true);
- else
+ if (!c->irq_set_affinity)
pr_debug("IRQ%u: unable to set affinity\n", d->irq);
+ else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+ cpumask_copy(d->affinity, affinity);
return ret;
}
diff --git a/arch/arm/kernel/kprobes.c b/arch/arm/kernel/kprobes.c
index ab1869d..4dd41fc 100644
--- a/arch/arm/kernel/kprobes.c
+++ b/arch/arm/kernel/kprobes.c
@@ -152,7 +152,7 @@
void __kprobes arch_disarm_kprobe(struct kprobe *p)
{
- stop_machine(__arch_disarm_kprobe, p, &cpu_online_map);
+ stop_machine(__arch_disarm_kprobe, p, cpu_online_mask);
}
void __kprobes arch_remove_kprobe(struct kprobe *p)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 45956c9..9650c14 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -256,7 +256,7 @@
{
unsigned long tmp;
- if (off & 3 || off >= sizeof(struct user))
+ if (off & 3)
return -EIO;
tmp = 0;
@@ -268,6 +268,8 @@
tmp = tsk->mm->end_code;
else if (off < sizeof(struct pt_regs))
tmp = get_user_reg(tsk, off >> 2);
+ else if (off >= sizeof(struct user))
+ return -EIO;
return put_user(tmp, ret);
}
@@ -904,27 +906,14 @@
return ret;
}
-#ifdef __ARMEB__
-#define AUDIT_ARCH_NR AUDIT_ARCH_ARMEB
-#else
-#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
-#endif
-
asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
{
unsigned long ip;
- /*
- * Save IP. IP is used to denote syscall entry/exit:
- * IP = 0 -> entry, = 1 -> exit
- */
- ip = regs->ARM_ip;
- regs->ARM_ip = why;
-
- if (!ip)
+ if (why)
audit_syscall_exit(regs);
else
- audit_syscall_entry(AUDIT_ARCH_NR, scno, regs->ARM_r0,
+ audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
if (!test_thread_flag(TIF_SYSCALL_TRACE))
@@ -934,6 +923,13 @@
current_thread_info()->syscall = scno;
+ /*
+ * IP is used to denote syscall entry/exit:
+ * IP = 0 -> entry, =1 -> exit
+ */
+ ip = regs->ARM_ip;
+ regs->ARM_ip = why;
+
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index b914113..ebfac78 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -523,7 +523,21 @@
*/
size -= start & ~PAGE_MASK;
bank->start = PAGE_ALIGN(start);
- bank->size = size & PAGE_MASK;
+
+#ifndef CONFIG_LPAE
+ if (bank->start + size < bank->start) {
+ printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
+ "32-bit physical address space\n", (long long)start);
+ /*
+ * To ensure bank->start + bank->size is representable in
+ * 32 bits, we use ULONG_MAX as the upper limit rather than 4GB.
+ * This means we lose a page after masking.
+ */
+ size = ULONG_MAX - bank->start;
+ }
+#endif
+
+ bank->size = size & PAGE_MASK;
/*
* Check whether this memory region has non-zero size or
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 7cb532f..d68d1b6 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -180,44 +180,23 @@
static int preserve_vfp_context(struct vfp_sigframe __user *frame)
{
- struct thread_info *thread = current_thread_info();
- struct vfp_hard_struct *h = &thread->vfpstate.hard;
const unsigned long magic = VFP_MAGIC;
const unsigned long size = VFP_STORAGE_SIZE;
int err = 0;
- vfp_sync_hwstate(thread);
__put_user_error(magic, &frame->magic, err);
__put_user_error(size, &frame->size, err);
- /*
- * Copy the floating point registers. There can be unused
- * registers see asm/hwcap.h for details.
- */
- err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
- sizeof(h->fpregs));
- /*
- * Copy the status and control register.
- */
- __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
+ if (err)
+ return -EFAULT;
- /*
- * Copy the exception registers.
- */
- __put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err);
- __put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
- __put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
-
- return err ? -EFAULT : 0;
+ return vfp_preserve_user_clear_hwstate(&frame->ufp, &frame->ufp_exc);
}
static int restore_vfp_context(struct vfp_sigframe __user *frame)
{
- struct thread_info *thread = current_thread_info();
- struct vfp_hard_struct *h = &thread->vfpstate.hard;
unsigned long magic;
unsigned long size;
- unsigned long fpexc;
int err = 0;
__get_user_error(magic, &frame->magic, err);
@@ -228,33 +207,7 @@
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.
- */
- err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
- sizeof(h->fpregs));
- /*
- * Copy the status and control register.
- */
- __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
-
- /*
- * Sanitise and restore the exception registers.
- */
- __get_user_error(fpexc, &frame->ufp_exc.fpexc, err);
- /* Ensure the VFP is enabled. */
- fpexc |= FPEXC_EN;
- /* Ensure FPINST2 is invalid and the exception flag is cleared. */
- fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
- h->fpexc = fpexc;
-
- __get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
- __get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
-
- return err ? -EFAULT : 0;
+ return vfp_restore_user_hwstate(&frame->ufp, &frame->ufp_exc);
}
#endif
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 2cee7d1..8f46446 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -251,8 +251,6 @@
struct mm_struct *mm = &init_mm;
unsigned int cpu = smp_processor_id();
- printk("CPU%u: Booted secondary processor\n", cpu);
-
/*
* All kernel threads share the same mm context; grab a
* reference and switch to it.
@@ -264,6 +262,8 @@
enter_lazy_tlb(mm, current);
local_flush_tlb_all();
+ printk("CPU%u: Booted secondary processor\n", cpu);
+
cpu_init();
preempt_disable();
trace_hardirqs_off();
@@ -349,7 +349,7 @@
* re-initialize the map in platform_smp_prepare_cpus() if
* present != possible (e.g. physical hotplug).
*/
- init_cpu_present(&cpu_possible_map);
+ init_cpu_present(cpu_possible_mask);
/*
* Initialise the SCU if there are more than one CPU
@@ -510,10 +510,6 @@
local_fiq_disable();
local_irq_disable();
-#ifdef CONFIG_HOTPLUG_CPU
- platform_cpu_kill(cpu);
-#endif
-
while (1)
cpu_relax();
}
@@ -576,16 +572,25 @@
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}
+#ifdef CONFIG_HOTPLUG_CPU
+static void smp_kill_cpus(cpumask_t *mask)
+{
+ unsigned int cpu;
+ for_each_cpu(cpu, mask)
+ platform_cpu_kill(cpu);
+}
+#else
+static void smp_kill_cpus(cpumask_t *mask) { }
+#endif
+
void smp_send_stop(void)
{
unsigned long timeout;
+ struct cpumask mask;
- if (num_online_cpus() > 1) {
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
-
- smp_cross_call(&mask, IPI_CPU_STOP);
- }
+ cpumask_copy(&mask, cpu_online_mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
+ smp_cross_call(&mask, IPI_CPU_STOP);
/* Wait up to one second for other CPUs to stop */
timeout = USEC_PER_SEC;
@@ -594,6 +599,8 @@
if (num_online_cpus() > 1)
pr_warning("SMP: failed to stop secondary CPUs\n");
+
+ smp_kill_cpus(&mask);
}
/*
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index d2b1779..76cbb05 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -115,7 +115,7 @@
"Ir" (THREAD_START_SP - sizeof(regs)),
"r" (®s),
"Ir" (sizeof(regs))
- : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+ : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
out:
return ret;
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index 99ce5c9..05774e5 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -1173,7 +1173,6 @@
printk(KERN_INFO "AT91: No default serial console defined.\n");
}
#else
-void __init __deprecated at91_init_serial(struct at91_uart_config *config) {}
void __init at91_register_uart(unsigned id, unsigned portnr, unsigned pins) {}
void __init at91_set_serial_console(unsigned portnr) {}
void __init at91_add_device_serial(void) {}
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index dd7f782..104ca40 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -23,6 +23,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/clockchips.h>
+#include <linux/export.h>
#include <asm/mach/time.h>
@@ -176,6 +177,7 @@
};
void __iomem *at91_st_base;
+EXPORT_SYMBOL_GPL(at91_st_base);
void __init at91rm9200_ioremap_st(u32 addr)
{
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 7e5651e..5652dde 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -598,6 +598,9 @@
else
cs_pin = spi1_standard_cs[devices[i].chip_select];
+ if (!gpio_is_valid(cs_pin))
+ continue;
+
if (devices[i].bus_num == 0)
enable_spi0 = 1;
else
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 096da87..4db961a 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -415,6 +415,9 @@
else
cs_pin = spi1_standard_cs[devices[i].chip_select];
+ if (!gpio_is_valid(cs_pin))
+ continue;
+
if (devices[i].bus_num == 0)
enable_spi0 = 1;
else
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 53688c46..fe99206 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -72,7 +72,8 @@
/* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i]))
- at91_set_gpio_output(data->vbus_pin[i], 0);
+ at91_set_gpio_output(data->vbus_pin[i],
+ data->vbus_pin_active_low[i]);
}
/* Enable overcurrent notification */
@@ -671,6 +672,9 @@
else
cs_pin = spi1_standard_cs[devices[i].chip_select];
+ if (!gpio_is_valid(cs_pin))
+ continue;
+
if (devices[i].bus_num == 0)
enable_spi0 = 1;
else
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 698479f..6b008ae 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -127,12 +127,13 @@
/* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i]))
- at91_set_gpio_output(data->vbus_pin[i], 0);
+ at91_set_gpio_output(data->vbus_pin[i],
+ data->vbus_pin_active_low[i]);
}
/* Enable overcurrent notification */
for (i = 0; i < data->ports; i++) {
- if (data->overcurrent_pin[i])
+ if (gpio_is_valid(data->overcurrent_pin[i]))
at91_set_gpio_input(data->overcurrent_pin[i], 1);
}
@@ -188,7 +189,8 @@
/* Enable VBus control for UHP ports */
for (i = 0; i < data->ports; i++) {
if (gpio_is_valid(data->vbus_pin[i]))
- at91_set_gpio_output(data->vbus_pin[i], 0);
+ at91_set_gpio_output(data->vbus_pin[i],
+ data->vbus_pin_active_low[i]);
}
usbh_ehci_data = *data;
@@ -785,6 +787,9 @@
else
cs_pin = spi1_standard_cs[devices[i].chip_select];
+ if (!gpio_is_valid(cs_pin))
+ continue;
+
if (devices[i].bus_num == 0)
enable_spi0 = 1;
else
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index eda72e8..fe4ae22 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -419,6 +419,9 @@
else
cs_pin = spi_standard_cs[devices[i].chip_select];
+ if (!gpio_is_valid(cs_pin))
+ continue;
+
/* enable chip-select pin */
at91_set_gpio_output(cs_pin, 1);
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index b6831ee..13c8cae 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -223,6 +223,8 @@
CLKDEV_CON_DEV_ID("usart", "f8028000.serial", &usart3_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f8008000.timer", &tcb0_clk),
CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
+ CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
+ CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
CLKDEV_CON_ID("pioA", &pioAB_clk),
CLKDEV_CON_ID("pioB", &pioAB_clk),
CLKDEV_CON_ID("pioC", &pioCD_clk),
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 11cbaa8..b2e4fe2 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -117,7 +117,7 @@
};
#define EK_FLASH_BASE AT91_CHIPSELECT_0
-#define EK_FLASH_SIZE SZ_2M
+#define EK_FLASH_SIZE SZ_8M
static struct physmap_flash_data ek_flash_data = {
.width = 2,
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index c3f9944..065fed3 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -85,8 +85,6 @@
.flags = IORESOURCE_MEM
},
[2] = {
- .start = AT91_PIN_PC11,
- .end = AT91_PIN_PC11,
.flags = IORESOURCE_IRQ
| IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE,
}
@@ -130,6 +128,8 @@
static void __init ek_add_device_dm9000(void)
{
+ struct resource *r = &dm9000_resource[2];
+
/* Configure chip-select 2 (DM9000) */
sam9_smc_configure(0, 2, &dm9000_smc_config);
@@ -139,6 +139,7 @@
/* Configure Interrupt pin as input, no pull-up */
at91_set_gpio_input(AT91_PIN_PC11, 0);
+ r->start = r->end = gpio_to_irq(AT91_PIN_PC11);
platform_device_register(&dm9000_device);
}
#else
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 66f0ddf..2ffe50f 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -74,6 +74,7 @@
static struct at91_usbh_data __initdata ek_usbh_data = {
.ports = 2,
.vbus_pin = { AT91_PIN_PA24, AT91_PIN_PA21 },
+ .vbus_pin_active_low = {1, 1},
.overcurrent_pin= {-EINVAL, -EINVAL},
};
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index e1bea73..c88e908 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -71,6 +71,7 @@
static struct at91_usbh_data __initdata ek_usbh_hs_data = {
.ports = 2,
.vbus_pin = {AT91_PIN_PD1, AT91_PIN_PD3},
+ .vbus_pin_active_low = {1, 1},
.overcurrent_pin= {-EINVAL, -EINVAL},
};
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index a0f4d74..6b69282 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -35,6 +35,7 @@
#include "generic.h"
void __iomem *at91_pmc_base;
+EXPORT_SYMBOL_GPL(at91_pmc_base);
/*
* There's a lot more which can be done with clocks, including cpufreq
diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h
index 3660478..ea2c57a 100644
--- a/arch/arm/mach-at91/include/mach/at91_pmc.h
+++ b/arch/arm/mach-at91/include/mach/at91_pmc.h
@@ -25,7 +25,7 @@
#define at91_pmc_write(field, value) \
__raw_writel(value, at91_pmc_base + field)
#else
-.extern at91_aic_base
+.extern at91_pmc_base
#endif
#define AT91_PMC_SCER 0x00 /* System Clock Enable Register */
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index 544a5d5..49a8211 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -86,14 +86,15 @@
extern void __init at91_add_device_eth(struct macb_platform_data *data);
/* USB Host */
+#define AT91_MAX_USBH_PORTS 3
struct at91_usbh_data {
- u8 ports; /* number of ports on root hub */
- int vbus_pin[2]; /* port power-control pin */
- u8 vbus_pin_active_low[2];
+ int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
+ int overcurrent_pin[AT91_MAX_USBH_PORTS];
+ u8 ports; /* number of ports on root hub */
u8 overcurrent_supported;
- int overcurrent_pin[2];
- u8 overcurrent_status[2];
- u8 overcurrent_changed[2];
+ u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_status[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
};
extern void __init at91_add_device_usbh(struct at91_usbh_data *data);
extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data);
diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h
new file mode 100644
index 0000000..2d9ca04
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/io.h
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-at91/include/mach/io.h
+ *
+ * Copyright (C) 2003 SAN People
+ *
+ * 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
+ */
+
+#ifndef __ASM_ARCH_IO_H
+#define __ASM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xFFFFFFFF
+#define __io(a) __typesafe_io(a)
+
+#endif
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 97cc04d..f44a2e7 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -54,6 +54,7 @@
}
void __iomem *at91_ramc_base[2];
+EXPORT_SYMBOL_GPL(at91_ramc_base);
void __init at91_ioremap_ramc(int id, u32 addr, u32 size)
{
@@ -292,6 +293,7 @@
}
void __iomem *at91_matrix_base;
+EXPORT_SYMBOL_GPL(at91_matrix_base);
void __init at91_ioremap_matrix(u32 base_addr)
{
diff --git a/arch/arm/mach-bcmring/core.c b/arch/arm/mach-bcmring/core.c
index 22e4e0a..adbfb19 100644
--- a/arch/arm/mach-bcmring/core.c
+++ b/arch/arm/mach-bcmring/core.c
@@ -52,8 +52,8 @@
#include <mach/csp/chipcHw_inline.h>
#include <mach/csp/tmrHw_reg.h>
-static AMBA_APB_DEVICE(uartA, "uarta", MM_ADDR_IO_UARTA, { IRQ_UARTA }, NULL);
-static AMBA_APB_DEVICE(uartB, "uartb", MM_ADDR_IO_UARTB, { IRQ_UARTB }, NULL);
+static AMBA_APB_DEVICE(uartA, "uartA", 0, MM_ADDR_IO_UARTA, {IRQ_UARTA}, NULL);
+static AMBA_APB_DEVICE(uartB, "uartB", 0, MM_ADDR_IO_UARTB, {IRQ_UARTB}, NULL);
static struct clk pll1_clk = {
.name = "PLL1",
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 0491cee..e81c35f 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -368,6 +368,7 @@
config MACH_EXYNOS4_DT
bool "Samsung Exynos4 Machine using device tree"
+ depends on ARCH_EXYNOS4
select CPU_EXYNOS4210
select USE_OF
select ARM_AMBA
@@ -380,6 +381,7 @@
config MACH_EXYNOS5_DT
bool "SAMSUNG EXYNOS5 Machine using device tree"
+ depends on ARCH_EXYNOS5
select SOC_EXYNOS5250
select USE_OF
select ARM_AMBA
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
index df54c2a..6efd1e5 100644
--- a/arch/arm/mach-exynos/clock-exynos4.c
+++ b/arch/arm/mach-exynos/clock-exynos4.c
@@ -497,25 +497,25 @@
.ctrlbit = (1 << 3),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.0",
+ .devname = "exynos4-sdhci.0",
.parent = &exynos4_clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 5),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.1",
+ .devname = "exynos4-sdhci.1",
.parent = &exynos4_clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 6),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.2",
+ .devname = "exynos4-sdhci.2",
.parent = &exynos4_clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 7),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.3",
+ .devname = "exynos4-sdhci.3",
.parent = &exynos4_clk_aclk_133.clk,
.enable = exynos4_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 8),
@@ -1202,7 +1202,7 @@
static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
+ .devname = "exynos4-sdhci.0",
.parent = &exynos4_clk_dout_mmc0.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
@@ -1213,7 +1213,7 @@
static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
+ .devname = "exynos4-sdhci.1",
.parent = &exynos4_clk_dout_mmc1.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
@@ -1224,7 +1224,7 @@
static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
+ .devname = "exynos4-sdhci.2",
.parent = &exynos4_clk_dout_mmc2.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
@@ -1235,7 +1235,7 @@
static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.3",
+ .devname = "exynos4-sdhci.3",
.parent = &exynos4_clk_dout_mmc3.clk,
.enable = exynos4_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
@@ -1340,10 +1340,10 @@
CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
- CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
+ CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
+ CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
+ CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
+ CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
index d013982..5cd7a8b 100644
--- a/arch/arm/mach-exynos/clock-exynos5.c
+++ b/arch/arm/mach-exynos/clock-exynos5.c
@@ -455,25 +455,25 @@
.ctrlbit = (1 << 20),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.0",
+ .devname = "exynos4-sdhci.0",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 12),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.1",
+ .devname = "exynos4-sdhci.1",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 13),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.2",
+ .devname = "exynos4-sdhci.2",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 14),
}, {
.name = "hsmmc",
- .devname = "s3c-sdhci.3",
+ .devname = "exynos4-sdhci.3",
.parent = &exynos5_clk_aclk_200.clk,
.enable = exynos5_clk_ip_fsys_ctrl,
.ctrlbit = (1 << 15),
@@ -813,7 +813,7 @@
static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.0",
+ .devname = "exynos4-sdhci.0",
.parent = &exynos5_clk_dout_mmc0.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 0),
@@ -824,7 +824,7 @@
static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.1",
+ .devname = "exynos4-sdhci.1",
.parent = &exynos5_clk_dout_mmc1.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 4),
@@ -835,7 +835,7 @@
static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.2",
+ .devname = "exynos4-sdhci.2",
.parent = &exynos5_clk_dout_mmc2.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 8),
@@ -846,7 +846,7 @@
static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
.clk = {
.name = "sclk_mmc",
- .devname = "s3c-sdhci.3",
+ .devname = "exynos4-sdhci.3",
.parent = &exynos5_clk_dout_mmc3.clk,
.enable = exynos5_clksrc_mask_fsys_ctrl,
.ctrlbit = (1 << 12),
@@ -990,10 +990,10 @@
CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
- CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
- CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
- CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
- CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
+ CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
+ CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
+ CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
+ CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index e6cc50e..5ccd6e8 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -326,6 +326,11 @@
s3c_fimc_setname(2, "exynos4-fimc");
s3c_fimc_setname(3, "exynos4-fimc");
+ s3c_sdhci_setname(0, "exynos4-sdhci");
+ s3c_sdhci_setname(1, "exynos4-sdhci");
+ s3c_sdhci_setname(2, "exynos4-sdhci");
+ s3c_sdhci_setname(3, "exynos4-sdhci");
+
/* The I2C bus controllers are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
@@ -344,6 +349,11 @@
s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
s3c_device_i2c0.resource[1].end = EXYNOS5_IRQ_IIC;
+ s3c_sdhci_setname(0, "exynos4-sdhci");
+ s3c_sdhci_setname(1, "exynos4-sdhci");
+ s3c_sdhci_setname(2, "exynos4-sdhci");
+ s3c_sdhci_setname(3, "exynos4-sdhci");
+
/* The I2C bus controllers are directly compatible with s3c2440 */
s3c_i2c0_setname("s3c2440-i2c");
s3c_i2c1_setname("s3c2440-i2c");
@@ -537,7 +547,9 @@
{
int irq;
- gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+ of_irq_init(exynos4_dt_irq_match);
+#endif
for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
@@ -583,10 +595,11 @@
#ifdef CONFIG_CACHE_L2X0
static int __init exynos4_l2x0_cache_init(void)
{
+ int ret;
+
if (soc_is_exynos5250())
return 0;
- int ret;
ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
if (!ret) {
l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs);
diff --git a/arch/arm/mach-exynos/dev-dwmci.c b/arch/arm/mach-exynos/dev-dwmci.c
index b025db4..7903501 100644
--- a/arch/arm/mach-exynos/dev-dwmci.c
+++ b/arch/arm/mach-exynos/dev-dwmci.c
@@ -16,6 +16,7 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
+#include <linux/ioport.h>
#include <linux/mmc/dw_mmc.h>
#include <plat/devs.h>
@@ -33,16 +34,8 @@
}
static struct resource exynos4_dwmci_resource[] = {
- [0] = {
- .start = EXYNOS4_PA_DWMCI,
- .end = EXYNOS4_PA_DWMCI + SZ_4K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_DWMCI,
- .end = IRQ_DWMCI,
- .flags = IORESOURCE_IRQ,
- }
+ [0] = DEFINE_RES_MEM(EXYNOS4_PA_DWMCI, SZ_4K),
+ [1] = DEFINE_RES_IRQ(EXYNOS4_IRQ_DWMCI),
};
static struct dw_mci_board exynos4_dwci_pdata = {
diff --git a/arch/arm/mach-exynos/dma.c b/arch/arm/mach-exynos/dma.c
index 3983abe..69aaa45 100644
--- a/arch/arm/mach-exynos/dma.c
+++ b/arch/arm/mach-exynos/dma.c
@@ -35,8 +35,6 @@
#include <mach/irqs.h>
#include <mach/dma.h>
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
static u8 exynos4210_pdma0_peri[] = {
DMACH_PCM0_RX,
DMACH_PCM0_TX,
diff --git a/arch/arm/mach-exynos/include/mach/debug-macro.S b/arch/arm/mach-exynos/include/mach/debug-macro.S
index 6c857ff..e0c86ea 100644
--- a/arch/arm/mach-exynos/include/mach/debug-macro.S
+++ b/arch/arm/mach-exynos/include/mach/debug-macro.S
@@ -21,10 +21,9 @@
*/
.macro addruart, rp, rv, tmp
- mov \rp, #0x10000000
- ldr \rp, [\rp, #0x0]
- and \rp, \rp, #0xf00000
- teq \rp, #0x500000 @@ EXYNOS5
+ mrc p15, 0, \tmp, c0, c0, 0
+ and \tmp, \tmp, #0xf0
+ teq \tmp, #0xf0 @@ A15
ldreq \rp, =EXYNOS5_PA_UART
movne \rp, #EXYNOS4_PA_UART @@ EXYNOS4
ldr \rv, =S3C_VA_UART
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h
index 9bee853..591e785 100644
--- a/arch/arm/mach-exynos/include/mach/irqs.h
+++ b/arch/arm/mach-exynos/include/mach/irqs.h
@@ -212,6 +212,8 @@
#define IRQ_MFC EXYNOS4_IRQ_MFC
#define IRQ_SDO EXYNOS4_IRQ_SDO
+#define IRQ_I2S0 EXYNOS4_IRQ_I2S0
+
#define IRQ_ADC EXYNOS4_IRQ_ADC0
#define IRQ_TC EXYNOS4_IRQ_PEN0
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 024d38f..6e6d11f 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -89,6 +89,10 @@
#define EXYNOS4_PA_MDMA1 0x12840000
#define EXYNOS4_PA_PDMA0 0x12680000
#define EXYNOS4_PA_PDMA1 0x12690000
+#define EXYNOS5_PA_MDMA0 0x10800000
+#define EXYNOS5_PA_MDMA1 0x11C10000
+#define EXYNOS5_PA_PDMA0 0x121A0000
+#define EXYNOS5_PA_PDMA1 0x121B0000
#define EXYNOS4_PA_SYSMMU_MDMA 0x10A40000
#define EXYNOS4_PA_SYSMMU_SSS 0x10A50000
diff --git a/arch/arm/mach-exynos/include/mach/regs-clock.h b/arch/arm/mach-exynos/include/mach/regs-clock.h
index e141c1f..d9578a5 100644
--- a/arch/arm/mach-exynos/include/mach/regs-clock.h
+++ b/arch/arm/mach-exynos/include/mach/regs-clock.h
@@ -255,9 +255,15 @@
/* For EXYNOS5250 */
+#define EXYNOS5_APLL_LOCK EXYNOS_CLKREG(0x00000)
#define EXYNOS5_APLL_CON0 EXYNOS_CLKREG(0x00100)
#define EXYNOS5_CLKSRC_CPU EXYNOS_CLKREG(0x00200)
+#define EXYNOS5_CLKMUX_STATCPU EXYNOS_CLKREG(0x00400)
#define EXYNOS5_CLKDIV_CPU0 EXYNOS_CLKREG(0x00500)
+#define EXYNOS5_CLKDIV_CPU1 EXYNOS_CLKREG(0x00504)
+#define EXYNOS5_CLKDIV_STATCPU0 EXYNOS_CLKREG(0x00600)
+#define EXYNOS5_CLKDIV_STATCPU1 EXYNOS_CLKREG(0x00604)
+
#define EXYNOS5_MPLL_CON0 EXYNOS_CLKREG(0x04100)
#define EXYNOS5_CLKSRC_CORE1 EXYNOS_CLKREG(0x04204)
diff --git a/arch/arm/mach-exynos/include/mach/uncompress.h b/arch/arm/mach-exynos/include/mach/uncompress.h
index 493f4f3..2979995 100644
--- a/arch/arm/mach-exynos/include/mach/uncompress.h
+++ b/arch/arm/mach-exynos/include/mach/uncompress.h
@@ -20,9 +20,24 @@
#include <plat/uncompress.h>
+static unsigned int __raw_readl(unsigned int ptr)
+{
+ return *((volatile unsigned int *)ptr);
+}
+
static void arch_detect_cpu(void)
{
- if (machine_is_smdk5250())
+ u32 chip_id = __raw_readl(EXYNOS_PA_CHIPID);
+
+ /*
+ * product_id is bits 31:12
+ * bits 23:20 describe the exynosX family
+ *
+ */
+ chip_id >>= 20;
+ chip_id &= 0xf;
+
+ if (chip_id == 0x5)
uart_base = (volatile u8 *)EXYNOS5_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
else
uart_base = (volatile u8 *)EXYNOS4_PA_UART + (S3C_UART_OFFSET * CONFIG_S3C_LOWLEVEL_UART_PORT);
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index 0d26f50..4711c89 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -45,7 +45,7 @@
"exynos4210-uart.3", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
- OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.2", NULL),
+ OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
{},
};
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index b3982c8..ed90aef 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -112,6 +112,7 @@
.host_caps = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
MMC_CAP_ERASE),
+ .host_caps2 = MMC_CAP2_BROKEN_VOLTAGE,
.cd_type = S3C_SDHCI_CD_PERMANENT,
.clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
@@ -307,49 +308,7 @@
};
/* TSP */
-static u8 mxt_init_vals[] = {
- /* MXT_GEN_COMMAND(6) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* MXT_GEN_POWER(7) */
- 0x20, 0xff, 0x32,
- /* MXT_GEN_ACQUIRE(8) */
- 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
- /* MXT_TOUCH_MULTI(9) */
- 0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
- 0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- /* MXT_TOUCH_KEYARRAY(15) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
- 0x00,
- /* MXT_SPT_GPIOPWM(19) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* MXT_PROCI_GRIPFACE(20) */
- 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
- 0x0f, 0x0a,
- /* MXT_PROCG_NOISE(22) */
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
- 0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
- /* MXT_TOUCH_PROXIMITY(23) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00,
- /* MXT_PROCI_ONETOUCH(24) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* MXT_SPT_SELFTEST(25) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- /* MXT_PROCI_TWOTOUCH(27) */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* MXT_SPT_CTECONFIG(28) */
- 0x00, 0x00, 0x02, 0x08, 0x10, 0x00,
-};
-
static struct mxt_platform_data mxt_platform_data = {
- .config = mxt_init_vals,
- .config_length = ARRAY_SIZE(mxt_init_vals),
-
.x_line = 18,
.y_line = 11,
.x_size = 1024,
@@ -571,7 +530,7 @@
static struct regulator_init_data __initdata max8997_ldo8_data = {
.constraints = {
- .name = "VUSB/VDAC_3.3V_C210",
+ .name = "VUSB+VDAC_3.3V_C210",
.min_uV = 3300000,
.max_uV = 3300000,
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -1347,6 +1306,7 @@
static void __init nuri_map_io(void)
{
+ clk_xusbxti.rate = 24000000;
exynos_init_io(NULL, 0);
s3c24xx_init_clocks(24000000);
s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
@@ -1379,7 +1339,6 @@
nuri_camera_init();
nuri_ehci_init();
- clk_xusbxti.rate = 24000000;
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 6bb9dbd..cb2b027 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -29,6 +29,7 @@
#include <asm/mach-types.h>
#include <plat/regs-serial.h>
+#include <plat/clock.h>
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/iic.h>
@@ -746,6 +747,7 @@
.max_width = 8,
.host_caps = (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED),
+ .host_caps2 = MMC_CAP2_BROKEN_VOLTAGE,
.cd_type = S3C_SDHCI_CD_PERMANENT,
.clk_type = S3C_SDHCI_CLK_DIV_EXTERNAL,
};
@@ -1057,6 +1059,7 @@
static void __init universal_map_io(void)
{
+ clk_xusbxti.rate = 24000000;
exynos_init_io(NULL, 0);
s3c24xx_init_clocks(24000000);
s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c
index b9a95ed..98e04f5 100644
--- a/arch/arm/mach-imx/clock-imx27.c
+++ b/arch/arm/mach-imx/clock-imx27.c
@@ -662,6 +662,7 @@
_REGISTER_CLOCK(NULL, "dma", dma_clk)
_REGISTER_CLOCK(NULL, "rtic", rtic_clk)
_REGISTER_CLOCK(NULL, "brom", brom_clk)
+ _REGISTER_CLOCK(NULL, "emma", emma_clk)
_REGISTER_CLOCK("m2m-emmaprp.0", NULL, emma_clk)
_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk)
_REGISTER_CLOCK("imx27-fec.0", NULL, fec_clk)
diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c
index 1e279af..e56c1a8 100644
--- a/arch/arm/mach-imx/clock-imx35.c
+++ b/arch/arm/mach-imx/clock-imx35.c
@@ -483,7 +483,7 @@
_REGISTER_CLOCK("imx2-wdt.0", NULL, wdog_clk)
_REGISTER_CLOCK(NULL, "max", max_clk)
_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
- _REGISTER_CLOCK(NULL, "csi", csi_clk)
+ _REGISTER_CLOCK("mx3-camera.0", NULL, csi_clk)
_REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "gpu2d", gpu2d_clk)
_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index 861ceb8..ed38d03 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -35,7 +35,7 @@
static int __init imx27_avic_add_irq_domain(struct device_node *np,
struct device_node *interrupt_parent)
{
- irq_domain_add_simple(np, 0);
+ irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL);
return 0;
}
@@ -44,7 +44,9 @@
{
static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
- irq_domain_add_simple(np, gpio_irq_base);
+ gpio_irq_base -= 32;
+ irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
+ NULL);
return 0;
}
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 27bc27e..c650145 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -38,6 +38,8 @@
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -479,6 +481,11 @@
&armadillo5x0_smc911x_device,
};
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
/*
* Perform board specific initializations
*/
@@ -489,6 +496,8 @@
mxc_iomux_setup_multiple_pins(armadillo5x0_pins,
ARRAY_SIZE(armadillo5x0_pins), "armadillo5x0");
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
platform_add_devices(devices, ARRAY_SIZE(devices));
imx_add_gpio_keys(&armadillo5x0_button_data);
imx31_add_imx_i2c1(NULL);
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index fc78e80..15a26e9 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -24,6 +24,8 @@
#include <linux/serial_8250.h>
#include <linux/smsc911x.h>
#include <linux/types.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
@@ -166,6 +168,11 @@
},
};
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
static int __init kzm_init_smsc9118(void)
{
/*
@@ -175,6 +182,8 @@
gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2), "smsc9118-int");
gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
return platform_device_register(&kzm_smsc9118_device);
}
#else
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 02401bb..83714b0 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -34,6 +34,8 @@
#include <linux/mfd/mc13783.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -242,6 +244,11 @@
static int mx31lilly_baseboard;
core_param(mx31lilly_baseboard, mx31lilly_baseboard, int, 0444);
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
static void __init mx31lilly_board_init(void)
{
imx31_soc_init();
@@ -280,6 +287,8 @@
imx31_add_spi_imx1(&spi1_pdata);
spi_register_board_info(&mc13783_dev, 1);
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
platform_add_devices(devices, ARRAY_SIZE(devices));
/* USB */
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index ef80751..0abef5f 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -29,6 +29,8 @@
#include <linux/usb/ulpi.h>
#include <linux/mtd/physmap.h>
#include <linux/delay.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -226,6 +228,11 @@
static int mx31lite_baseboard;
core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
static void __init mx31lite_init(void)
{
int ret;
@@ -259,6 +266,8 @@
if (usbh2_pdata.otg)
imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+
/* SMSC9117 IRQ pin */
ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
if (ret)
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index e14291d..6ae51c6 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -97,7 +97,7 @@
static int lcd_power_gpio = -ENXIO;
static int mc9s08dz60_gpiochip_match(struct gpio_chip *chip,
- void *data)
+ const void *data)
{
return !strcmp(chip->label, data);
}
diff --git a/arch/arm/mach-imx/mach-mx53_ard.c b/arch/arm/mach-imx/mach-mx53_ard.c
index 753f4fc..0564198 100644
--- a/arch/arm/mach-imx/mach-mx53_ard.c
+++ b/arch/arm/mach-imx/mach-mx53_ard.c
@@ -23,6 +23,8 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/smsc911x.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
#include <mach/common.h>
#include <mach/hardware.h>
@@ -214,6 +216,11 @@
return 0;
}
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x"),
+};
+
void __init imx53_ard_common_init(void)
{
mxc_iomux_v3_setup_multiple_pads(mx53_ard_pads,
@@ -232,6 +239,7 @@
imx53_ard_common_init();
mx53_ard_io_init();
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
platform_add_devices(devices, ARRAY_SIZE(devices));
imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index 05250ae..e10f391 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -35,7 +35,7 @@
}
clk_enable(gpc_dvfs_clk);
mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
- if (tzic_enable_wake() != 0)
+ if (!tzic_enable_wake())
cpu_do_idle();
clk_disable(gpc_dvfs_clk);
}
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index 1c672d9..f7fe1b9 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/kexec.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <mach/bridge-regs.h>
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 3698a37..26aac36 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -86,9 +86,6 @@
static void __init halibut_fixup(struct tag *tags, char **cmdline,
struct meminfo *mi)
{
- mi->nr_banks=1;
- mi->bank[0].start = PHYS_OFFSET;
- mi->bank[0].size = (101*1024*1024);
}
static void __init halibut_map_io(void)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 962e711..fb3496a 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -17,6 +17,7 @@
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/memblock.h>
@@ -49,10 +50,22 @@
msm_map_msm8x60_io();
}
+#ifdef CONFIG_OF
+static struct of_device_id msm_dt_gic_match[] __initdata = {
+ { .compatible = "qcom,msm-8660-qgic", .data = gic_of_init },
+ {}
+};
+#endif
+
static void __init msm8x60_init_irq(void)
{
- gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
- (void *)MSM_QGIC_CPU_BASE);
+ if (!of_have_populated_dt())
+ gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+ (void *)MSM_QGIC_CPU_BASE);
+#ifdef CONFIG_OF
+ else
+ of_irq_init(msm_dt_gic_match);
+#endif
/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
@@ -73,16 +86,8 @@
{}
};
-static struct of_device_id msm_dt_gic_match[] __initdata = {
- { .compatible = "qcom,msm-8660-qgic", },
- {}
-};
-
static void __init msm8x60_dt_init(void)
{
- irq_domain_generate_simple(msm_dt_gic_match, MSM8X60_QGIC_DIST_PHYS,
- GIC_SPI_START);
-
if (of_machine_is_compatible("qcom,msm8660-surf")) {
printk(KERN_INFO "Init surf UART registers\n");
msm8x60_init_uart12dm();
diff --git a/arch/arm/mach-msm/board-trout-panel.c b/arch/arm/mach-msm/board-trout-panel.c
index 25105c1..89bf6b4 100644
--- a/arch/arm/mach-msm/board-trout-panel.c
+++ b/arch/arm/mach-msm/board-trout-panel.c
@@ -12,6 +12,7 @@
#include <asm/io.h>
#include <asm/mach-types.h>
+#include <asm/system_info.h>
#include <mach/msm_fb.h>
#include <mach/vreg.h>
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 5414f76..d4060a3 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/clkdev.h>
+#include <asm/system_info.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
index 169a840..c14011f 100644
--- a/arch/arm/mach-msm/include/mach/uncompress.h
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -16,6 +16,7 @@
#ifndef __ASM_ARCH_MSM_UNCOMPRESS_H
#define __ASM_ARCH_MSM_UNCOMPRESS_H
+#include <asm/barrier.h>
#include <asm/processor.h>
#include <mach/msm_iomap.h>
diff --git a/arch/arm/mach-msm/proc_comm.c b/arch/arm/mach-msm/proc_comm.c
index 67e701c..9980dc7 100644
--- a/arch/arm/mach-msm/proc_comm.c
+++ b/arch/arm/mach-msm/proc_comm.c
@@ -121,7 +121,7 @@
* and unknown state. This function should be called early to
* wait on the ARM9.
*/
-void __init proc_comm_boot_wait(void)
+void __devinit proc_comm_boot_wait(void)
{
void __iomem *base = MSM_SHARED_RAM_BASE;
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 0c56a5a..c56df9e 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -203,15 +203,9 @@
return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
}
-static int debug_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static const struct file_operations debug_ops = {
.read = debug_read,
- .open = debug_open,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/arch/arm/mach-omap1/ams-delta-fiq.c b/arch/arm/mach-omap1/ams-delta-fiq.c
index fcce7ff..cfd98b1 100644
--- a/arch/arm/mach-omap1/ams-delta-fiq.c
+++ b/arch/arm/mach-omap1/ams-delta-fiq.c
@@ -48,7 +48,7 @@
struct irq_chip *irq_chip = NULL;
int gpio, irq_num, fiq_count;
- irq_desc = irq_to_desc(IH_GPIO_BASE);
+ irq_desc = irq_to_desc(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
if (irq_desc)
irq_chip = irq_desc->irq_data.chip;
diff --git a/arch/arm/mach-omap1/include/mach/io.h b/arch/arm/mach-omap1/include/mach/io.h
new file mode 100644
index 0000000..ce4f800
--- /dev/null
+++ b/arch/arm/mach-omap1/include/mach/io.h
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-omap1/include/mach/io.h
+ *
+ * IO definitions for TI OMAP processors and boards
+ *
+ * Copied from arch/arm/mach-sa1100/include/mach/io.h
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Modifications:
+ * 06-12-1997 RMK Created.
+ * 07-04-1999 RMK Major cleanup
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a) __typesafe_io(a)
+
+#endif
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index 087dba0..e9cc52d 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/spinlock.h>
+#include <mach/hardware.h>
#include <plat/mux.h>
diff --git a/arch/arm/mach-omap1/timer.c b/arch/arm/mach-omap1/timer.c
index 6e90665..fb202af 100644
--- a/arch/arm/mach-omap1/timer.c
+++ b/arch/arm/mach-omap1/timer.c
@@ -47,9 +47,9 @@
int n = (pdev->id - 1) << 1;
u32 l;
- l = __raw_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
+ l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
l |= source << n;
- __raw_writel(l, MOD_CONF_CTRL_1);
+ omap_writel(l, MOD_CONF_CTRL_1);
return 0;
}
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index a39fc4b..130ab00 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -20,6 +20,7 @@
#include <linux/usb/otg.h>
#include <linux/spi/spi.h>
#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
#include <linux/gpio_keys.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
@@ -560,7 +561,7 @@
},
};
-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
.hs_right_step = 0x0f,
@@ -568,7 +569,7 @@
.hf_right_step = 0x1d,
};
-static struct twl4030_vibra_data twl6040_vibra = {
+static struct twl6040_vibra_data twl6040_vibra = {
.vibldrv_res = 8,
.vibrdrv_res = 3,
.viblmotor_res = 10,
@@ -577,16 +578,14 @@
.vddvibr_uV = 0, /* fixed volt supply - VBAT */
};
-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
.codec = &twl6040_codec,
.vibra = &twl6040_vibra,
.audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
.irq_base = TWL6040_CODEC_IRQ_BASE,
};
static struct twl4030_platform_data sdp4430_twldata = {
- .audio = &twl6040_audio,
/* Regulators */
.vusim = &sdp4430_vusim,
.vaux1 = &sdp4430_vaux1,
@@ -617,7 +616,8 @@
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
TWL_COMMON_REGULATOR_CLK32KG);
- omap4_pmic_init("twl6030", &sdp4430_twldata);
+ omap4_pmic_init("twl6030", &sdp4430_twldata,
+ &twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index 41b0a2f..909a8b9 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -26,6 +26,7 @@
#include <linux/i2c/at24.h>
#include <linux/i2c/twl.h>
+#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/mmc/host.h>
@@ -81,8 +82,23 @@
.flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
};
+static struct regulator_consumer_supply cm_t35_smsc911x_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
+static struct regulator_consumer_supply sb_t35_smsc911x_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.1"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.1"),
+};
+
static void __init cm_t35_init_ethernet(void)
{
+ regulator_register_fixed(0, cm_t35_smsc911x_supplies,
+ ARRAY_SIZE(cm_t35_smsc911x_supplies));
+ regulator_register_fixed(1, sb_t35_smsc911x_supplies,
+ ARRAY_SIZE(sb_t35_smsc911x_supplies));
+
gpmc_smsc911x_init(&cm_t35_smsc911x_cfg);
gpmc_smsc911x_init(&sb_t35_smsc911x_cfg);
}
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 74e1687..098d183 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -137,7 +137,7 @@
static void __init omap4_i2c_init(void)
{
- omap4_pmic_init("twl6030", &sdp4430_twldata);
+ omap4_pmic_init("twl6030", &sdp4430_twldata, NULL, 0);
}
static void __init omap4_init(void)
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index e558800..740cee9 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -634,8 +634,14 @@
static inline void __init igep_wlan_bt_init(void) { }
#endif
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
static void __init igep_init(void)
{
+ regulator_register_fixed(1, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
/* Get IGEP2 hardware revision */
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index d50a562a..1b60495 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -22,6 +22,7 @@
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/spi/spi.h>
+#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
#include <linux/io.h>
@@ -410,8 +411,14 @@
};
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
static void __init omap_ldp_init(void)
{
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
ldp_init_smsc911x();
omap_i2c_init();
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 4c90f07..49df127 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -114,15 +114,6 @@
static inline void __init omap3evm_init_smsc911x(void)
{
- struct clk *l3ck;
- unsigned int rate;
-
- l3ck = clk_get(NULL, "l3_ck");
- if (IS_ERR(l3ck))
- rate = 100000000;
- else
- rate = clk_get_rate(l3ck);
-
/* Configure ethernet controller reset gpio */
if (cpu_is_omap3430()) {
if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1)
@@ -632,9 +623,15 @@
#endif
}
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
static void __init omap3_evm_init(void)
{
omap3_evm_get_revision();
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
if (cpu_is_omap3630())
omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB);
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 4a7d8c8..9b3c141 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -23,6 +23,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
@@ -188,8 +189,14 @@
};
#endif
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
static void __init omap3logic_init(void)
{
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap3torpedo_fix_pbias_voltage();
omap3logic_i2c_init();
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 6410043..4dffc95 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -24,6 +24,7 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
+#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
#include <linux/mmc/host.h>
@@ -72,15 +73,6 @@
static inline void __init omap3stalker_init_eth(void)
{
- struct clk *l3ck;
- unsigned int rate;
-
- l3ck = clk_get(NULL, "l3_ck");
- if (IS_ERR(l3ck))
- rate = 100000000;
- else
- rate = clk_get_rate(l3ck);
-
omap_mux_init_gpio(19, OMAP_PIN_INPUT_PULLUP);
gpmc_smsc911x_init(&smsc911x_cfg);
}
@@ -419,8 +411,14 @@
};
#endif
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
static void __init omap3_stalker_init(void)
{
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
omap_board_config = omap3_stalker_config;
omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index d8c0e89..1b782ba 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/usb/otg.h>
#include <linux/i2c/twl.h>
+#include <linux/mfd/twl6040.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/wl12xx.h>
@@ -284,7 +285,7 @@
return 0;
}
-static struct twl4030_codec_data twl6040_codec = {
+static struct twl6040_codec_data twl6040_codec = {
/* single-step ramp for headset and handsfree */
.hs_left_step = 0x0f,
.hs_right_step = 0x0f,
@@ -292,17 +293,14 @@
.hf_right_step = 0x1d,
};
-static struct twl4030_audio_data twl6040_audio = {
+static struct twl6040_platform_data twl6040_data = {
.codec = &twl6040_codec,
.audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
.irq_base = TWL6040_CODEC_IRQ_BASE,
};
/* Panda board uses the common PMIC configuration */
-static struct twl4030_platform_data omap4_panda_twldata = {
- .audio = &twl6040_audio,
-};
+static struct twl4030_platform_data omap4_panda_twldata;
/*
* Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
@@ -326,7 +324,8 @@
TWL_COMMON_REGULATOR_VCXIO |
TWL_COMMON_REGULATOR_VUSB |
TWL_COMMON_REGULATOR_CLK32KG);
- omap4_pmic_init("twl6030", &omap4_panda_twldata);
+ omap4_pmic_init("twl6030", &omap4_panda_twldata,
+ &twl6040_data, OMAP44XX_IRQ_SYS_2N);
omap_register_i2c_bus(2, 400, NULL, 0);
/*
* Bus 3 is attached to the DVI port where devices like the pico DLP
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 668533e..33aa391 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -498,10 +498,18 @@
{ OVERO_GPIO_BT_NRESET, GPIOF_OUT_INIT_HIGH, "lcd bl enable" },
};
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+ REGULATOR_SUPPLY("vddvario", "smsc911x.1"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.1"),
+};
+
static void __init overo_init(void)
{
int ret;
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
omap_hsmmc_init(mmc);
overo_i2c_init();
diff --git a/arch/arm/mach-omap2/board-zoom-debugboard.c b/arch/arm/mach-omap2/board-zoom-debugboard.c
index 1e8540e..f64f441 100644
--- a/arch/arm/mach-omap2/board-zoom-debugboard.c
+++ b/arch/arm/mach-omap2/board-zoom-debugboard.c
@@ -14,6 +14,9 @@
#include <linux/smsc911x.h>
#include <linux/interrupt.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
+
#include <plat/gpmc.h>
#include <plat/gpmc-smsc911x.h>
@@ -117,11 +120,17 @@
&zoom_debugboard_serial_device,
};
+static struct regulator_consumer_supply dummy_supplies[] = {
+ REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
+ REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
+};
+
int __init zoom_debugboard_init(void)
{
if (!omap_zoom_debugboard_detect())
return 0;
+ regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
zoom_init_smsc911x();
zoom_init_quaduart();
return platform_add_devices(zoom_devices, ARRAY_SIZE(zoom_devices));
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
index 7072e0d..3d9d746 100644
--- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
+++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
@@ -165,83 +165,3 @@
return 0;
}
-
-#ifdef CONFIG_CPU_FREQ
-/*
- * Walk PRCM rate table and fillout cpufreq freq_table
- * XXX This should be replaced by an OPP layer in the near future
- */
-static struct cpufreq_frequency_table *freq_table;
-
-void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- const struct prcm_config *prcm;
- int i = 0;
- int tbl_sz = 0;
-
- if (!cpu_is_omap24xx())
- return;
-
- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
- if (!(prcm->flags & cpu_mask))
- continue;
- if (prcm->xtal_speed != sclk->rate)
- continue;
-
- /* don't put bypass rates in table */
- if (prcm->dpll_speed == prcm->xtal_speed)
- continue;
-
- tbl_sz++;
- }
-
- /*
- * XXX Ensure that we're doing what CPUFreq expects for this error
- * case and the following one
- */
- if (tbl_sz == 0) {
- pr_warning("%s: no matching entries in rate_table\n",
- __func__);
- return;
- }
-
- /* Include the CPUFREQ_TABLE_END terminator entry */
- tbl_sz++;
-
- freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) * tbl_sz,
- GFP_ATOMIC);
- if (!freq_table) {
- pr_err("%s: could not kzalloc frequency table\n", __func__);
- return;
- }
-
- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
- if (!(prcm->flags & cpu_mask))
- continue;
- if (prcm->xtal_speed != sclk->rate)
- continue;
-
- /* don't put bypass rates in table */
- if (prcm->dpll_speed == prcm->xtal_speed)
- continue;
-
- freq_table[i].index = i;
- freq_table[i].frequency = prcm->mpu_speed / 1000;
- i++;
- }
-
- freq_table[i].index = i;
- freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- *table = &freq_table[0];
-}
-
-void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- if (!cpu_is_omap24xx())
- return;
-
- kfree(freq_table);
-}
-
-#endif
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index f57ed5b..d9f4931 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -536,10 +536,5 @@
.clk_set_rate = omap2_clk_set_rate,
.clk_set_parent = omap2_clk_set_parent,
.clk_disable_unused = omap2_clk_disable_unused,
-#ifdef CONFIG_CPU_FREQ
- /* These will be removed when the OPP code is integrated */
- .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
- .clk_exit_cpufreq_table = omap2_clk_exit_cpufreq_table,
-#endif
};
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index b8c2a686..a1bb23a 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -146,14 +146,6 @@
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
-extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
-extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
-#else
-#define omap2_clk_init_cpufreq_table 0
-#define omap2_clk_exit_cpufreq_table 0
-#endif
-
extern const struct clkops clkops_omap2_iclk_dflt_wait;
extern const struct clkops clkops_omap2_iclk_dflt;
extern const struct clkops clkops_omap2_iclk_idle_only;
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
index 480fb8f..f4a626f7 100644
--- a/arch/arm/mach-omap2/clock3xxx_data.c
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
@@ -747,7 +747,7 @@
.parent = &dpll4_ck,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_TV_MASK,
+ .clksel_mask = OMAP3630_CLKSEL_TV_MASK,
.clksel = dpll4_clksel,
.clkdm_name = "dpll4_clkdm",
.recalc = &omap2_clksel_recalc,
@@ -832,7 +832,7 @@
.parent = &dpll4_ck,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_DSS1_MASK,
+ .clksel_mask = OMAP3630_CLKSEL_DSS1_MASK,
.clksel = dpll4_clksel,
.clkdm_name = "dpll4_clkdm",
.recalc = &omap2_clksel_recalc,
@@ -859,7 +859,7 @@
.parent = &dpll4_ck,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
- .clksel_mask = OMAP3430_CLKSEL_CAM_MASK,
+ .clksel_mask = OMAP3630_CLKSEL_CAM_MASK,
.clksel = dpll4_clksel,
.clkdm_name = "dpll4_clkdm",
.set_rate = &omap2_clksel_set_rate,
@@ -886,7 +886,7 @@
.parent = &dpll4_ck,
.init = &omap2_init_clksel_parent,
.clksel_reg = OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
- .clksel_mask = OMAP3430_DIV_DPLL4_MASK,
+ .clksel_mask = OMAP3630_DIV_DPLL4_MASK,
.clksel = dpll4_clksel,
.clkdm_name = "dpll4_clkdm",
.recalc = &omap2_clksel_recalc,
@@ -1394,6 +1394,7 @@
.name = "cpefuse_fck",
.ops = &clkops_omap2_dflt,
.parent = &sys_ck,
+ .clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
.enable_bit = OMAP3430ES2_EN_CPEFUSE_SHIFT,
.recalc = &followparent_recalc,
@@ -1403,6 +1404,7 @@
.name = "ts_fck",
.ops = &clkops_omap2_dflt,
.parent = &omap_32k_fck,
+ .clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
.enable_bit = OMAP3430ES2_EN_TS_SHIFT,
.recalc = &followparent_recalc,
@@ -1412,6 +1414,7 @@
.name = "usbtll_fck",
.ops = &clkops_omap2_dflt_wait,
.parent = &dpll5_m2_ck,
+ .clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
.enable_bit = OMAP3430ES2_EN_USBTLL_SHIFT,
.recalc = &followparent_recalc,
@@ -1617,6 +1620,7 @@
.name = "fshostusb_fck",
.ops = &clkops_omap2_dflt_wait,
.parent = &core_48m_fck,
+ .clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = OMAP3430ES1_EN_FSHOSTUSB_SHIFT,
.recalc = &followparent_recalc,
@@ -2043,6 +2047,7 @@
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
.enable_bit = OMAP3430_EN_OMAPCTRL_SHIFT,
.flags = ENABLE_ON_INIT,
+ .clkdm_name = "core_l4_clkdm",
.recalc = &followparent_recalc,
};
@@ -2094,6 +2099,7 @@
.clksel_reg = OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
.clksel_mask = OMAP3430ES1_CLKSEL_FSHOSTUSB_MASK,
.clksel = usb_l4_clksel,
+ .clkdm_name = "core_l4_clkdm",
.recalc = &omap2_clksel_recalc,
};
@@ -3467,8 +3473,8 @@
CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX),
CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX),
CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX),
- CLK("davinci_emac", "emac_clk", &emac_ick, CK_AM35XX),
- CLK("davinci_emac", "phy_clk", &emac_fck, CK_AM35XX),
+ CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX),
+ CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX),
CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX),
CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX),
CLK("musb-am35x", "ick", &hsotgusb_ick_am35xx, CK_AM35XX),
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index c03c110..fa6ea65 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -957,8 +957,8 @@
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
.autoidle_reg = OMAP4430_CM_AUTOIDLE_DPLL_USB,
.idlest_reg = OMAP4430_CM_IDLEST_DPLL_USB,
- .mult_mask = OMAP4430_DPLL_MULT_MASK,
- .div1_mask = OMAP4430_DPLL_DIV_MASK,
+ .mult_mask = OMAP4430_DPLL_MULT_USB_MASK,
+ .div1_mask = OMAP4430_DPLL_DIV_0_7_MASK,
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
@@ -978,6 +978,7 @@
.recalc = &omap3_dpll_recalc,
.round_rate = &omap2_dpll_round_rate,
.set_rate = &omap3_noncore_dpll_set_rate,
+ .clkdm_name = "l3_init_clkdm",
};
static struct clk dpll_usb_clkdcoldo_ck = {
diff --git a/arch/arm/mach-omap2/clockdomains44xx_data.c b/arch/arm/mach-omap2/clockdomains44xx_data.c
index 9299ac2..bd7ed13 100644
--- a/arch/arm/mach-omap2/clockdomains44xx_data.c
+++ b/arch/arm/mach-omap2/clockdomains44xx_data.c
@@ -390,7 +390,7 @@
.prcm_partition = OMAP4430_PRM_PARTITION,
.cm_inst = OMAP4430_PRM_EMU_CM_INST,
.clkdm_offs = OMAP4430_PRM_EMU_CM_EMU_CDOFFS,
- .flags = CLKDM_CAN_HWSUP,
+ .flags = CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_FORCE_WAKEUP,
};
static struct clockdomain l3_dma_44xx_clkdm = {
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
index 5e5880d..b6c77be 100644
--- a/arch/arm/mach-omap2/gpmc-smsc911x.c
+++ b/arch/arm/mach-omap2/gpmc-smsc911x.c
@@ -19,15 +19,11 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/smsc911x.h>
-#include <linux/regulator/fixed.h>
-#include <linux/regulator/machine.h>
#include <plat/board.h>
#include <plat/gpmc.h>
#include <plat/gpmc-smsc911x.h>
-static struct omap_smsc911x_platform_data *gpmc_cfg;
-
static struct resource gpmc_smsc911x_resources[] = {
[0] = {
.flags = IORESOURCE_MEM,
@@ -41,51 +37,6 @@
.phy_interface = PHY_INTERFACE_MODE_MII,
.irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
.irq_type = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
- .flags = SMSC911X_USE_16BIT,
-};
-
-static struct regulator_consumer_supply gpmc_smsc911x_supply[] = {
- REGULATOR_SUPPLY("vddvario", "smsc911x.0"),
- REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
-};
-
-/* Generic regulator definition to satisfy smsc911x */
-static struct regulator_init_data gpmc_smsc911x_reg_init_data = {
- .constraints = {
- .min_uV = 3300000,
- .max_uV = 3300000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(gpmc_smsc911x_supply),
- .consumer_supplies = gpmc_smsc911x_supply,
-};
-
-static struct fixed_voltage_config gpmc_smsc911x_fixed_reg_data = {
- .supply_name = "gpmc_smsc911x",
- .microvolts = 3300000,
- .gpio = -EINVAL,
- .startup_delay = 0,
- .enable_high = 0,
- .enabled_at_boot = 1,
- .init_data = &gpmc_smsc911x_reg_init_data,
-};
-
-/*
- * Platform device id of 42 is a temporary fix to avoid conflicts
- * with other reg-fixed-voltage devices. The real fix should
- * involve the driver core providing a way of dynamically
- * assigning a unique id on registration for platform devices
- * in the same name space.
- */
-static struct platform_device gpmc_smsc911x_regulator = {
- .name = "reg-fixed-voltage",
- .id = 42,
- .dev = {
- .platform_data = &gpmc_smsc911x_fixed_reg_data,
- },
};
/*
@@ -93,23 +44,12 @@
* assume that pin multiplexing is done in the board-*.c file,
* or in the bootloader.
*/
-void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
+void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *gpmc_cfg)
{
struct platform_device *pdev;
unsigned long cs_mem_base;
int ret;
- gpmc_cfg = board_data;
-
- if (!gpmc_cfg->id) {
- ret = platform_device_register(&gpmc_smsc911x_regulator);
- if (ret < 0) {
- pr_err("Unable to register smsc911x regulators: %d\n",
- ret);
- return;
- }
- }
-
if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
pr_err("Failed to request GPMC mem region\n");
return;
@@ -139,8 +79,7 @@
gpio_set_value(gpmc_cfg->gpio_reset, 1);
}
- if (gpmc_cfg->flags)
- gpmc_smsc911x_config.flags = gpmc_cfg->flags;
+ gpmc_smsc911x_config.flags = gpmc_cfg->flags ? : SMSC911X_USE_16BIT;
pdev = platform_device_register_resndata(NULL, "smsc911x", gpmc_cfg->id,
gpmc_smsc911x_resources, ARRAY_SIZE(gpmc_smsc911x_resources),
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 100db62..b0268ea 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -506,6 +506,13 @@
if (oh->dev_attr != NULL) {
mmc_dev_attr = oh->dev_attr;
mmc_data->controller_flags = mmc_dev_attr->flags;
+ /*
+ * erratum 2.1.1.128 doesn't apply if board has
+ * a transceiver is attached
+ */
+ if (hsmmcinfo->transceiver)
+ mmc_data->controller_flags &=
+ ~OMAP_HSMMC_BROKEN_MULTIBLOCK_READ;
}
pdev = platform_device_alloc(name, ctrl_nr - 1);
diff --git a/arch/arm/mach-omap2/include/mach/barriers.h b/arch/arm/mach-omap2/include/mach/barriers.h
index 4fa72c7..1c582a8 100644
--- a/arch/arm/mach-omap2/include/mach/barriers.h
+++ b/arch/arm/mach-omap2/include/mach/barriers.h
@@ -22,6 +22,8 @@
#ifndef __MACH_BARRIERS_H
#define __MACH_BARRIERS_H
+#include <asm/outercache.h>
+
extern void omap_bus_sync(void);
#define rmb() dsb()
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
index 1e2d332..c88420d 100644
--- a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
+++ b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
@@ -941,10 +941,10 @@
#define OMAP4_DSI2_LANEENABLE_MASK (0x7 << 29)
#define OMAP4_DSI1_LANEENABLE_SHIFT 24
#define OMAP4_DSI1_LANEENABLE_MASK (0x1f << 24)
-#define OMAP4_DSI2_PIPD_SHIFT 19
-#define OMAP4_DSI2_PIPD_MASK (0x1f << 19)
-#define OMAP4_DSI1_PIPD_SHIFT 14
-#define OMAP4_DSI1_PIPD_MASK (0x1f << 14)
+#define OMAP4_DSI1_PIPD_SHIFT 19
+#define OMAP4_DSI1_PIPD_MASK (0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT 14
+#define OMAP4_DSI2_PIPD_MASK (0x1f << 14)
/* CONTROL_MCBSPLP */
#define OMAP4_ALBCTRLRX_FSX_SHIFT 31
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index eba6cd3..7144ae6 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -1395,7 +1395,7 @@
*/
static int _ocp_softreset(struct omap_hwmod *oh)
{
- u32 v;
+ u32 v, softrst_mask;
int c = 0;
int ret = 0;
@@ -1422,16 +1422,21 @@
goto dis_opt_clks;
_write_sysconfig(v, oh);
+ if (oh->class->sysc->srst_udelay)
+ udelay(oh->class->sysc->srst_udelay);
+
if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
omap_test_timeout((omap_hwmod_read(oh,
oh->class->sysc->syss_offs)
& SYSS_RESETDONE_MASK),
MAX_MODULE_SOFTRESET_WAIT, c);
- else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+ else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+ softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
omap_test_timeout(!(omap_hwmod_read(oh,
oh->class->sysc->sysc_offs)
- & SYSC_TYPE2_SOFTRESET_MASK),
+ & softrst_mask),
MAX_MODULE_SOFTRESET_WAIT, c);
+ }
if (c == MAX_MODULE_SOFTRESET_WAIT)
pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
@@ -1477,6 +1482,11 @@
ret = (oh->class->reset) ? oh->class->reset(oh) : _ocp_softreset(oh);
+ if (oh->class->sysc) {
+ _update_sysc_cache(oh);
+ _enable_sysc(oh);
+ }
+
return ret;
}
@@ -1786,20 +1796,9 @@
return 0;
}
- if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+ if (!(oh->flags & HWMOD_INIT_NO_RESET))
_reset(oh);
- /*
- * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
- * The _enable() function should be split to
- * avoid the rewrite of the OCP_SYSCONFIG register.
- */
- if (oh->class->sysc) {
- _update_sysc_cache(oh);
- _enable_sysc(oh);
- }
- }
-
postsetup_state = oh->_postsetup_state;
if (postsetup_state == _HWMOD_STATE_UNKNOWN)
postsetup_state = _HWMOD_STATE_ENABLED;
@@ -2463,26 +2462,28 @@
* @oh: struct omap_hwmod *
*
* Sets the module OCP socket ENAWAKEUP bit to allow the module to
- * send wakeups to the PRCM. Eventually this should sets PRCM wakeup
- * registers to cause the PRCM to receive wakeup events from the
- * module. Does not set any wakeup routing registers beyond this
- * point - if the module is to wake up any other module or subsystem,
- * that must be set separately. Called by omap_device code. Returns
- * -EINVAL on error or 0 upon success.
+ * send wakeups to the PRCM, and enable I/O ring wakeup events for
+ * this IP block if it has dynamic mux entries. Eventually this
+ * should set PRCM wakeup registers to cause the PRCM to receive
+ * wakeup events from the module. Does not set any wakeup routing
+ * registers beyond this point - if the module is to wake up any other
+ * module or subsystem, that must be set separately. Called by
+ * omap_device code. Returns -EINVAL on error or 0 upon success.
*/
int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
{
unsigned long flags;
u32 v;
- if (!oh->class->sysc ||
- !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
- return -EINVAL;
-
spin_lock_irqsave(&oh->_lock, flags);
- v = oh->_sysc_cache;
- _enable_wakeup(oh, &v);
- _write_sysconfig(v, oh);
+
+ if (oh->class->sysc &&
+ (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
+ v = oh->_sysc_cache;
+ _enable_wakeup(oh, &v);
+ _write_sysconfig(v, oh);
+ }
+
_set_idle_ioring_wakeup(oh, true);
spin_unlock_irqrestore(&oh->_lock, flags);
@@ -2494,26 +2495,28 @@
* @oh: struct omap_hwmod *
*
* Clears the module OCP socket ENAWAKEUP bit to prevent the module
- * from sending wakeups to the PRCM. Eventually this should clear
- * PRCM wakeup registers to cause the PRCM to ignore wakeup events
- * from the module. Does not set any wakeup routing registers beyond
- * this point - if the module is to wake up any other module or
- * subsystem, that must be set separately. Called by omap_device
- * code. Returns -EINVAL on error or 0 upon success.
+ * from sending wakeups to the PRCM, and disable I/O ring wakeup
+ * events for this IP block if it has dynamic mux entries. Eventually
+ * this should clear PRCM wakeup registers to cause the PRCM to ignore
+ * wakeup events from the module. Does not set any wakeup routing
+ * registers beyond this point - if the module is to wake up any other
+ * module or subsystem, that must be set separately. Called by
+ * omap_device code. Returns -EINVAL on error or 0 upon success.
*/
int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
{
unsigned long flags;
u32 v;
- if (!oh->class->sysc ||
- !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
- return -EINVAL;
-
spin_lock_irqsave(&oh->_lock, flags);
- v = oh->_sysc_cache;
- _disable_wakeup(oh, &v);
- _write_sysconfig(v, oh);
+
+ if (oh->class->sysc &&
+ (oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP)) {
+ v = oh->_sysc_cache;
+ _disable_wakeup(oh, &v);
+ _write_sysconfig(v, oh);
+ }
+
_set_idle_ioring_wakeup(oh, false);
spin_unlock_irqrestore(&oh->_lock, flags);
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index a5409ce..a6bde34 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -1000,7 +1000,6 @@
.flags = OMAP_FIREWALL_L4,
}
},
- .flags = OCPIF_SWSUP_IDLE,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index c4f56cb..04a3885 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -1049,7 +1049,6 @@
.slave = &omap2430_dss_venc_hwmod,
.clk = "dss_ick",
.addr = omap2_dss_venc_addrs,
- .flags = OCPIF_SWSUP_IDLE,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 34b9766d..db86ce9 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1676,7 +1676,6 @@
.flags = OMAP_FIREWALL_L4,
}
},
- .flags = OCPIF_SWSUP_IDLE,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 08daa5e..6abc757 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2594,6 +2594,15 @@
static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
.rev_offs = 0x0000,
.sysc_offs = 0x0010,
+ /*
+ * ISS needs 100 OCP clk cycles delay after a softreset before
+ * accessing sysconfig again.
+ * The lowest frequency at the moment for L3 bus is 100 MHz, so
+ * 1usec delay is needed. Add an x2 margin to be safe (2 usecs).
+ *
+ * TODO: Indicate errata when available.
+ */
+ .srst_udelay = 2,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -2996,6 +3005,11 @@
&omap44xx_l4_abe__mcbsp1_dma,
};
+static struct omap_hwmod_opt_clk mcbsp1_opt_clks[] = {
+ { .role = "pad_fck", .clk = "pad_clks_ck" },
+ { .role = "prcm_clk", .clk = "mcbsp1_sync_mux_ck" },
+};
+
static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
.name = "mcbsp1",
.class = &omap44xx_mcbsp_hwmod_class,
@@ -3012,6 +3026,8 @@
},
.slaves = omap44xx_mcbsp1_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp1_slaves),
+ .opt_clks = mcbsp1_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(mcbsp1_opt_clks),
};
/* mcbsp2 */
@@ -3071,6 +3087,11 @@
&omap44xx_l4_abe__mcbsp2_dma,
};
+static struct omap_hwmod_opt_clk mcbsp2_opt_clks[] = {
+ { .role = "pad_fck", .clk = "pad_clks_ck" },
+ { .role = "prcm_clk", .clk = "mcbsp2_sync_mux_ck" },
+};
+
static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
.name = "mcbsp2",
.class = &omap44xx_mcbsp_hwmod_class,
@@ -3087,6 +3108,8 @@
},
.slaves = omap44xx_mcbsp2_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp2_slaves),
+ .opt_clks = mcbsp2_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(mcbsp2_opt_clks),
};
/* mcbsp3 */
@@ -3146,6 +3169,11 @@
&omap44xx_l4_abe__mcbsp3_dma,
};
+static struct omap_hwmod_opt_clk mcbsp3_opt_clks[] = {
+ { .role = "pad_fck", .clk = "pad_clks_ck" },
+ { .role = "prcm_clk", .clk = "mcbsp3_sync_mux_ck" },
+};
+
static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
.name = "mcbsp3",
.class = &omap44xx_mcbsp_hwmod_class,
@@ -3162,6 +3190,8 @@
},
.slaves = omap44xx_mcbsp3_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp3_slaves),
+ .opt_clks = mcbsp3_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(mcbsp3_opt_clks),
};
/* mcbsp4 */
@@ -3200,6 +3230,11 @@
&omap44xx_l4_per__mcbsp4,
};
+static struct omap_hwmod_opt_clk mcbsp4_opt_clks[] = {
+ { .role = "pad_fck", .clk = "pad_clks_ck" },
+ { .role = "prcm_clk", .clk = "mcbsp4_sync_mux_ck" },
+};
+
static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
.name = "mcbsp4",
.class = &omap44xx_mcbsp_hwmod_class,
@@ -3216,6 +3251,8 @@
},
.slaves = omap44xx_mcbsp4_slaves,
.slaves_cnt = ARRAY_SIZE(omap44xx_mcbsp4_slaves),
+ .opt_clks = mcbsp4_opt_clks,
+ .opt_clks_cnt = ARRAY_SIZE(mcbsp4_opt_clks),
};
/*
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index 9262a6b..de6d464 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -64,10 +64,10 @@
}
oh = omap_hwmod_lookup(opp_def->hwmod_name);
if (!oh || !oh->od) {
- pr_warn("%s: no hwmod or odev for %s, [%d] "
+ pr_debug("%s: no hwmod or odev for %s, [%d] "
"cannot add OPPs.\n", __func__,
opp_def->hwmod_name, i);
- return -EINVAL;
+ continue;
}
dev = &oh->od->pdev->dev;
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 238defc..703bd10 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -153,8 +153,7 @@
pwrdm_set_next_pwrst(mpu_pwrdm, mpu_next_state);
/* Following is for error tracking, it should not happen */
if (ret) {
- printk(KERN_ERR "save_secure_sram() returns %08x\n",
- ret);
+ pr_err("save_secure_sram() returns %08x\n", ret);
while (1)
;
}
@@ -289,7 +288,7 @@
break;
default:
/* Invalid state */
- printk(KERN_ERR "Invalid mpu state in sram_idle\n");
+ pr_err("Invalid mpu state in sram_idle\n");
return;
}
@@ -439,18 +438,17 @@
list_for_each_entry(pwrst, &pwrst_list, node) {
state = pwrdm_read_prev_pwrst(pwrst->pwrdm);
if (state > pwrst->next_state) {
- printk(KERN_INFO "Powerdomain (%s) didn't enter "
- "target state %d\n",
+ pr_info("Powerdomain (%s) didn't enter "
+ "target state %d\n",
pwrst->pwrdm->name, pwrst->next_state);
ret = -1;
}
omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
}
if (ret)
- printk(KERN_ERR "Could not enter target state in pm_suspend\n");
+ pr_err("Could not enter target state in pm_suspend\n");
else
- printk(KERN_INFO "Successfully put all powerdomains "
- "to target state\n");
+ pr_info("Successfully put all powerdomains to target state\n");
return ret;
}
@@ -734,21 +732,22 @@
if (ret) {
pr_err("pm: Failed to request pm_io irq\n");
- goto err1;
+ goto err2;
}
ret = pwrdm_for_each(pwrdms_setup, NULL);
if (ret) {
- printk(KERN_ERR "Failed to setup powerdomains\n");
- goto err2;
+ pr_err("Failed to setup powerdomains\n");
+ goto err3;
}
(void) clkdm_for_each(omap_pm_clkdms_setup, NULL);
mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
if (mpu_pwrdm == NULL) {
- printk(KERN_ERR "Failed to get mpu_pwrdm\n");
- goto err2;
+ pr_err("Failed to get mpu_pwrdm\n");
+ ret = -EINVAL;
+ goto err3;
}
neon_pwrdm = pwrdm_lookup("neon_pwrdm");
@@ -781,8 +780,8 @@
omap3_secure_ram_storage =
kmalloc(0x803F, GFP_KERNEL);
if (!omap3_secure_ram_storage)
- printk(KERN_ERR "Memory allocation failed when"
- "allocating for secure sram context\n");
+ pr_err("Memory allocation failed when "
+ "allocating for secure sram context\n");
local_irq_disable();
local_fiq_disable();
@@ -796,14 +795,17 @@
}
omap3_save_scratchpad_contents();
-err1:
return ret;
-err2:
- free_irq(INT_34XX_PRCM_MPU_IRQ, NULL);
+
+err3:
list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) {
list_del(&pwrst->node);
kfree(pwrst);
}
+ free_irq(omap_prcm_event_to_irq("io"), omap3_pm_init);
+err2:
+ free_irq(omap_prcm_event_to_irq("wkup"), NULL);
+err1:
return ret;
}
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index 9ccaadc..8856253 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -144,7 +144,7 @@
static int __init omap4_pm_init(void)
{
int ret;
- struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm;
+ struct clockdomain *emif_clkdm, *mpuss_clkdm, *l3_1_clkdm, *l4wkup;
struct clockdomain *ducati_clkdm, *l3_2_clkdm, *l4_per_clkdm;
if (!cpu_is_omap44xx())
@@ -168,14 +168,19 @@
* MPUSS -> L4_PER/L3_* and DUCATI -> L3_* doesn't work as
* expected. The hardware recommendation is to enable static
* dependencies for these to avoid system lock ups or random crashes.
+ * The L4 wakeup depedency is added to workaround the OCP sync hardware
+ * BUG with 32K synctimer which lead to incorrect timer value read
+ * from the 32K counter. The BUG applies for GPTIMER1 and WDT2 which
+ * are part of L4 wakeup clockdomain.
*/
mpuss_clkdm = clkdm_lookup("mpuss_clkdm");
emif_clkdm = clkdm_lookup("l3_emif_clkdm");
l3_1_clkdm = clkdm_lookup("l3_1_clkdm");
l3_2_clkdm = clkdm_lookup("l3_2_clkdm");
l4_per_clkdm = clkdm_lookup("l4_per_clkdm");
+ l4wkup = clkdm_lookup("l4_wkup_clkdm");
ducati_clkdm = clkdm_lookup("ducati_clkdm");
- if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) ||
+ if ((!mpuss_clkdm) || (!emif_clkdm) || (!l3_1_clkdm) || (!l4wkup) ||
(!l3_2_clkdm) || (!ducati_clkdm) || (!l4_per_clkdm))
goto err2;
@@ -183,6 +188,7 @@
ret |= clkdm_add_wkdep(mpuss_clkdm, l3_1_clkdm);
ret |= clkdm_add_wkdep(mpuss_clkdm, l3_2_clkdm);
ret |= clkdm_add_wkdep(mpuss_clkdm, l4_per_clkdm);
+ ret |= clkdm_add_wkdep(mpuss_clkdm, l4wkup);
ret |= clkdm_add_wkdep(ducati_clkdm, l3_1_clkdm);
ret |= clkdm_add_wkdep(ducati_clkdm, l3_2_clkdm);
if (ret) {
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 8a18d1b..96ad3dbe 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -972,7 +972,13 @@
int pwrdm_state_switch(struct powerdomain *pwrdm)
{
- return _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+ int ret;
+
+ ret = pwrdm_wait_transition(pwrdm);
+ if (!ret)
+ ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
+
+ return ret;
}
int pwrdm_clkdm_state_switch(struct clockdomain *clkdm)
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index eac623c..f106d21 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -147,8 +147,9 @@
u32 mask, st;
/* XXX read mask from RAM? */
- mask = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqen_offs);
- st = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, irqst_offs);
+ mask = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
+ irqen_offs);
+ st = omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST, irqst_offs);
return mask & st;
}
@@ -180,7 +181,7 @@
*/
void omap44xx_prm_ocp_barrier(void)
{
- omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_REVISION_PRM_OFFSET);
}
@@ -198,19 +199,19 @@
void omap44xx_prm_save_and_clear_irqen(u32 *saved_mask)
{
saved_mask[0] =
- omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQSTATUS_MPU_OFFSET);
saved_mask[1] =
- omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET);
- omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
- omap4_prm_write_inst_reg(0, OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_write_inst_reg(0, OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
/* OCP barrier */
- omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_read_inst_reg(OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_REVISION_PRM_OFFSET);
}
@@ -226,9 +227,9 @@
*/
void omap44xx_prm_restore_irqen(u32 *saved_mask)
{
- omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_write_inst_reg(saved_mask[0], OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_OFFSET);
- omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_DEVICE_INST,
+ omap4_prm_write_inst_reg(saved_mask[1], OMAP4430_PRM_OCP_SOCKET_INST,
OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
}
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 873b51d..d28f848 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -290,7 +290,7 @@
goto err;
}
- for (i = 0; i <= irq_setup->nr_regs; i++) {
+ for (i = 0; i < irq_setup->nr_regs; i++) {
gc = irq_alloc_generic_chip("PRCM", 1,
irq_setup->base_irq + i * 32, prm_base,
handle_level_irq);
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 0cdd359..9fc2f44 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -108,8 +108,14 @@
static void omap_uart_set_smartidle(struct platform_device *pdev)
{
struct omap_device *od = to_omap_device(pdev);
+ u8 idlemode;
- omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_SMART);
+ if (od->hwmods[0]->class->sysc->idlemodes & SIDLE_SMART_WKUP)
+ idlemode = HWMOD_IDLEMODE_SMART_WKUP;
+ else
+ idlemode = HWMOD_IDLEMODE_SMART;
+
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], idlemode);
}
#else
@@ -120,124 +126,8 @@
#endif /* CONFIG_PM */
#ifdef CONFIG_OMAP_MUX
-static struct omap_device_pad default_uart1_pads[] __initdata = {
- {
- .name = "uart1_cts.uart1_cts",
- .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- },
- {
- .name = "uart1_rts.uart1_rts",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart1_tx.uart1_tx",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart1_rx.uart1_rx",
- .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
- .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- },
-};
-
-static struct omap_device_pad default_uart2_pads[] __initdata = {
- {
- .name = "uart2_cts.uart2_cts",
- .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- },
- {
- .name = "uart2_rts.uart2_rts",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart2_tx.uart2_tx",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart2_rx.uart2_rx",
- .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
- .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- },
-};
-
-static struct omap_device_pad default_uart3_pads[] __initdata = {
- {
- .name = "uart3_cts_rctx.uart3_cts_rctx",
- .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
- },
- {
- .name = "uart3_rts_sd.uart3_rts_sd",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart3_tx_irtx.uart3_tx_irtx",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart3_rx_irrx.uart3_rx_irrx",
- .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
- .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
- .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
- },
-};
-
-static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {
- {
- .name = "gpmc_wait2.uart4_tx",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "gpmc_wait3.uart4_rx",
- .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
- .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
- .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
- },
-};
-
-static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {
- {
- .name = "uart4_tx.uart4_tx",
- .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
- },
- {
- .name = "uart4_rx.uart4_rx",
- .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
- .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
- .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
- },
-};
-
static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
{
- switch (bdata->id) {
- case 0:
- bdata->pads = default_uart1_pads;
- bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads);
- break;
- case 1:
- bdata->pads = default_uart2_pads;
- bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads);
- break;
- case 2:
- bdata->pads = default_uart3_pads;
- bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads);
- break;
- case 3:
- if (cpu_is_omap44xx()) {
- bdata->pads = default_omap4_uart4_pads;
- bdata->pads_cnt =
- ARRAY_SIZE(default_omap4_uart4_pads);
- } else if (cpu_is_omap3630()) {
- bdata->pads = default_omap36xx_uart4_pads;
- bdata->pads_cnt =
- ARRAY_SIZE(default_omap36xx_uart4_pads);
- }
- break;
- default:
- break;
- }
}
#else
static void omap_serial_fill_default_pads(struct omap_board_data *bdata) {}
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index 4b57757..7a7b893 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -37,6 +37,16 @@
.flags = I2C_CLIENT_WAKE,
};
+static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
+ {
+ .addr = 0x48,
+ .flags = I2C_CLIENT_WAKE,
+ },
+ {
+ I2C_BOARD_INFO("twl6040", 0x4b),
+ },
+};
+
void __init omap_pmic_init(int bus, u32 clkrate,
const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data)
@@ -49,14 +59,31 @@
omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
}
+void __init omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data,
+ struct twl6040_platform_data *twl6040_data, int twl6040_irq)
+{
+ /* PMIC part*/
+ strncpy(omap4_i2c1_board_info[0].type, pmic_type,
+ sizeof(omap4_i2c1_board_info[0].type));
+ omap4_i2c1_board_info[0].irq = OMAP44XX_IRQ_SYS_1N;
+ omap4_i2c1_board_info[0].platform_data = pmic_data;
+
+ /* TWL6040 audio IC part */
+ omap4_i2c1_board_info[1].irq = twl6040_irq;
+ omap4_i2c1_board_info[1].platform_data = twl6040_data;
+
+ omap_register_i2c_bus(1, 400, omap4_i2c1_board_info, 2);
+
+}
+
void __init omap_pmic_late_init(void)
{
/* Init the OMAP TWL parameters (if PMIC has been registerd) */
- if (!pmic_i2c_board_info.irq)
- return;
-
- omap3_twl_init();
- omap4_twl_init();
+ if (pmic_i2c_board_info.irq)
+ omap3_twl_init();
+ if (omap4_i2c1_board_info[0].irq)
+ omap4_twl_init();
}
#if defined(CONFIG_ARCH_OMAP3)
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index 275dde8..0962748 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -29,6 +29,7 @@
struct twl4030_platform_data;
+struct twl6040_platform_data;
void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
struct twl4030_platform_data *pmic_data);
@@ -46,12 +47,9 @@
omap_pmic_init(1, 2600, pmic_type, INT_34XX_SYS_NIRQ, pmic_data);
}
-static inline void omap4_pmic_init(const char *pmic_type,
- struct twl4030_platform_data *pmic_data)
-{
- /* Phoenix Audio IC needs I2C1 to start with 400 KHz or less */
- omap_pmic_init(1, 400, pmic_type, OMAP44XX_IRQ_SYS_1N, pmic_data);
-}
+void omap4_pmic_init(const char *pmic_type,
+ struct twl4030_platform_data *pmic_data,
+ struct twl6040_platform_data *audio_data, int twl6040_irq);
void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags);
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index f51348d..dde8a11 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -54,7 +54,7 @@
/*
* setup_ehci_io_mux - initialize IO pad mux for USBHOST
*/
-static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static void __init setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
switch (port_mode[0]) {
case OMAP_EHCI_PORT_MODE_PHY:
@@ -197,7 +197,8 @@
return;
}
-static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static
+void __init setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
switch (port_mode[0]) {
case OMAP_EHCI_PORT_MODE_PHY:
@@ -315,7 +316,7 @@
}
}
-static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static void __init setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
switch (port_mode[0]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
@@ -412,7 +413,8 @@
}
}
-static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+static
+void __init setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
{
switch (port_mode[0]) {
case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
diff --git a/arch/arm/mach-orion5x/mpp.h b/arch/arm/mach-orion5x/mpp.h
index eac6897..db70e79 100644
--- a/arch/arm/mach-orion5x/mpp.h
+++ b/arch/arm/mach-orion5x/mpp.h
@@ -65,8 +65,8 @@
#define MPP8_GIGE MPP(8, 0x1, 0, 0, 1, 1, 1)
#define MPP9_UNUSED MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GPIO MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GIGE MPP(9, 0x1, 1, 1, 1, 1, 1)
+#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1, 1, 1)
+#define MPP9_GIGE MPP(9, 0x1, 0, 0, 1, 1, 1)
#define MPP10_UNUSED MPP(10, 0x0, 0, 0, 1, 1, 1)
#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1, 1, 1)
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 109ccd2..fe2d1f8 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -113,6 +113,7 @@
select IWMMXT
select PXA25x
select MIGHT_HAVE_PCI
+ select NEED_MACH_IO_H if PCI
config MACH_EM_X270
bool "CompuLab EM-x270 platform"
diff --git a/arch/arm/mach-pxa/include/mach/io.h b/arch/arm/mach-pxa/include/mach/io.h
new file mode 100644
index 0000000..cd78b7f
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/io.h
@@ -0,0 +1,17 @@
+/*
+ * arch/arm/mach-pxa/include/mach/io.h
+ *
+ * Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a) __typesafe_io(a)
+
+#endif
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
index c54cef2..cbf51ae 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa2xx.h
@@ -17,6 +17,7 @@
*
* bit 23 - Input/Output (PXA2xx specific)
* bit 24 - Wakeup Enable(PXA2xx specific)
+ * bit 25 - Keep Output (PXA2xx specific)
*/
#define MFP_DIR_IN (0x0 << 23)
@@ -25,6 +26,12 @@
#define MFP_DIR(x) (((x) >> 23) & 0x1)
#define MFP_LPM_CAN_WAKEUP (0x1 << 24)
+
+/*
+ * MFP_LPM_KEEP_OUTPUT must be specified for pins that need to
+ * retain their last output level (low or high).
+ * Note: MFP_LPM_KEEP_OUTPUT has no effect on pins configured for input.
+ */
#define MFP_LPM_KEEP_OUTPUT (0x1 << 25)
#define WAKEUP_ON_EDGE_RISE (MFP_LPM_CAN_WAKEUP | MFP_LPM_EDGE_RISE)
diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
index b0a8428..ef0426a 100644
--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
+++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
@@ -33,6 +33,8 @@
#define BANK_OFF(n) (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
#define GPLR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5))
#define GPDR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x0c)
+#define GPSR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x18)
+#define GPCR(x) __REG2(0x40E00000, BANK_OFF((x) >> 5) + 0x24)
#define PWER_WE35 (1 << 24)
@@ -348,6 +350,7 @@
#ifdef CONFIG_PM
static unsigned long saved_gafr[2][4];
static unsigned long saved_gpdr[4];
+static unsigned long saved_gplr[4];
static unsigned long saved_pgsr[4];
static int pxa2xx_mfp_suspend(void)
@@ -366,14 +369,26 @@
}
for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) {
-
saved_gafr[0][i] = GAFR_L(i);
saved_gafr[1][i] = GAFR_U(i);
saved_gpdr[i] = GPDR(i * 32);
+ saved_gplr[i] = GPLR(i * 32);
saved_pgsr[i] = PGSR(i);
- GPDR(i * 32) = gpdr_lpm[i];
+ GPSR(i * 32) = PGSR(i);
+ GPCR(i * 32) = ~PGSR(i);
}
+
+ /* set GPDR bits taking into account MFP_LPM_KEEP_OUTPUT */
+ for (i = 0; i < pxa_last_gpio; i++) {
+ if ((gpdr_lpm[gpio_to_bank(i)] & GPIO_bit(i)) ||
+ ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) &&
+ (saved_gpdr[gpio_to_bank(i)] & GPIO_bit(i))))
+ GPDR(i) |= GPIO_bit(i);
+ else
+ GPDR(i) &= ~GPIO_bit(i);
+ }
+
return 0;
}
@@ -384,6 +399,8 @@
for (i = 0; i <= gpio_to_bank(pxa_last_gpio); i++) {
GAFR_L(i) = saved_gafr[0][i];
GAFR_U(i) = saved_gafr[1][i];
+ GPSR(i * 32) = saved_gplr[i];
+ GPCR(i * 32) = ~saved_gplr[i];
GPDR(i * 32) = saved_gpdr[i];
PGSR(i) = saved_pgsr[i];
}
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 6bce78e..4726c24 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -421,8 +421,11 @@
pxa_register_device(&pxa27x_device_i2c_power, info);
}
+static struct pxa_gpio_platform_data pxa27x_gpio_info __initdata = {
+ .gpio_set_wake = gpio_set_wake,
+};
+
static struct platform_device *devices[] __initdata = {
- &pxa_device_gpio,
&pxa27x_device_udc,
&pxa_device_pmu,
&pxa_device_i2s,
@@ -458,6 +461,7 @@
register_syscore_ops(&pxa2xx_mfp_syscore_ops);
register_syscore_ops(&pxa2xx_clock_syscore_ops);
+ pxa_register_device(&pxa_device_gpio, &pxa27x_gpio_info);
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
}
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-s3c24xx/Kconfig
index 0f3a327..b34287a 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-s3c24xx/Kconfig
@@ -111,10 +111,6 @@
help
Compile in platform device definition for Samsung TouchScreen.
-# cpu-specific sections
-
-if CPU_S3C2410
-
config S3C2410_DMA
bool
depends on S3C24XX_DMA && (CPU_S3C2410 || CPU_S3C2442)
@@ -127,6 +123,10 @@
help
Power Management code common to S3C2410 and better
+# cpu-specific sections
+
+if CPU_S3C2410
+
config S3C24XX_SIMTEC_NOR
bool
help
diff --git a/arch/arm/mach-s3c24xx/common.h b/arch/arm/mach-s3c24xx/common.h
new file mode 100644
index 0000000..c2f596e
--- /dev/null
+++ b/arch/arm/mach-s3c24xx/common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Common Header for S3C24XX SoCs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H
+#define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__
+
+void s3c2410_restart(char mode, const char *cmd);
+void s3c244x_restart(char mode, const char *cmd);
+
+#endif /* __ARCH_ARM_MACH_S3C24XX_COMMON_H */
diff --git a/arch/arm/mach-s5pv210/dma.c b/arch/arm/mach-s5pv210/dma.c
index 86ce62f..b8337e2 100644
--- a/arch/arm/mach-s5pv210/dma.c
+++ b/arch/arm/mach-s5pv210/dma.c
@@ -33,8 +33,6 @@
#include <mach/irqs.h>
#include <mach/dma.h>
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
static u8 pdma0_peri[] = {
DMACH_UART0_RX,
DMACH_UART0_TX,
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index a9ea64e..48d018f 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -484,8 +484,8 @@
.gpio_defaults[8] = 0x0100,
.gpio_defaults[9] = 0x0100,
.gpio_defaults[10] = 0x0100,
- .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
- .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+ .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */
+ .ldo[1] = { 0, &wm8994_ldo2_data },
};
/* GPIO I2C PMIC */
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 2cf5ed7..3239566 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -25,6 +25,7 @@
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/gpio.h>
+#include <linux/mmc/host.h>
#include <linux/interrupt.h>
#include <asm/hardware/vic.h>
@@ -674,8 +675,8 @@
.gpio_defaults[8] = 0x0100,
.gpio_defaults[9] = 0x0100,
.gpio_defaults[10] = 0x0100,
- .ldo[0] = { S5PV210_MP03(6), NULL, &wm8994_ldo1_data }, /* XM0FRNB_2 */
- .ldo[1] = { 0, NULL, &wm8994_ldo2_data },
+ .ldo[0] = { S5PV210_MP03(6), &wm8994_ldo1_data }, /* XM0FRNB_2 */
+ .ldo[1] = { 0, &wm8994_ldo2_data },
};
/* GPIO I2C PMIC */
@@ -765,6 +766,7 @@
/* MoviNAND */
static struct s3c_sdhci_platdata goni_hsmmc0_data __initdata = {
.max_width = 4,
+ .host_caps2 = MMC_CAP2_BROKEN_VOLTAGE,
.cd_type = S3C_SDHCI_CD_PERMANENT,
};
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 48885b7..c7f418b 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -313,6 +313,10 @@
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
+
+#ifdef CONFIG_BACKLIGHT_LOCOMO
+ .lcd_power = locomolcd_power
+#endif
};
static void __init collie_init(void)
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 7c524b4..16be4c5 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -306,7 +306,7 @@
}
static struct resource sa1100_rtc_resources[] = {
- DEFINE_RES_MEM(0x90010000, 0x9001003f),
+ DEFINE_RES_MEM(0x90010000, 0x40),
DEFINE_RES_IRQ_NAMED(IRQ_RTC1Hz, "rtc 1Hz"),
DEFINE_RES_IRQ_NAMED(IRQ_RTCAlrm, "rtc alarm"),
};
diff --git a/arch/arm/mach-sa1100/include/mach/collie.h b/arch/arm/mach-sa1100/include/mach/collie.h
index 52acda7..f33679d 100644
--- a/arch/arm/mach-sa1100/include/mach/collie.h
+++ b/arch/arm/mach-sa1100/include/mach/collie.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-sa1100/include/mach/collie.h
*
- * This file contains the hardware specific definitions for Assabet
+ * This file contains the hardware specific definitions for Collie
* Only include this file from SA1100-specific files.
*
* ChangeLog:
@@ -13,6 +13,7 @@
#ifndef __ASM_ARCH_COLLIE_H
#define __ASM_ARCH_COLLIE_H
+extern void locomolcd_power(int on);
#define COLLIE_SCOOP_GPIO_BASE (GPIO_MAX + 1)
#define COLLIE_GPIO_CHARGE_ON (COLLIE_SCOOP_GPIO_BASE + 0)
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 1621ad0..3333974 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -1667,8 +1667,10 @@
for (i = 0; i < U300_VIC_IRQS_END; i++)
set_bit(i, (unsigned long *) &mask[0]);
- vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]);
- vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]);
+ vic_init((void __iomem *) U300_INTCON0_VBASE, IRQ_U300_INTCON0_START,
+ mask[0], mask[0]);
+ vic_init((void __iomem *) U300_INTCON1_VBASE, IRQ_U300_INTCON1_START,
+ mask[1], mask[1]);
}
diff --git a/arch/arm/mach-u300/i2c.c b/arch/arm/mach-u300/i2c.c
index a38f802..cb04bd6 100644
--- a/arch/arm/mach-u300/i2c.c
+++ b/arch/arm/mach-u300/i2c.c
@@ -146,9 +146,6 @@
.min_uV = 1800000,
.max_uV = 1800000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
.always_on = 1,
.boot_on = 1,
},
@@ -160,9 +157,6 @@
.min_uV = 2500000,
.max_uV = 2500000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
- .valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
.always_on = 1,
.boot_on = 1,
},
@@ -230,8 +224,7 @@
.max_uV = 1800000,
.valid_modes_mask = REGULATOR_MODE_NORMAL,
.valid_ops_mask =
- REGULATOR_CHANGE_VOLTAGE |
- REGULATOR_CHANGE_STATUS,
+ REGULATOR_CHANGE_VOLTAGE,
.always_on = 1,
.boot_on = 1,
},
diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h
index ee78a26..ec09c1e 100644
--- a/arch/arm/mach-u300/include/mach/irqs.h
+++ b/arch/arm/mach-u300/include/mach/irqs.h
@@ -12,101 +12,101 @@
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
-#define IRQ_U300_INTCON0_START 0
-#define IRQ_U300_INTCON1_START 32
+#define IRQ_U300_INTCON0_START 1
+#define IRQ_U300_INTCON1_START 33
/* These are on INTCON0 - 30 lines */
-#define IRQ_U300_IRQ0_EXT 0
-#define IRQ_U300_IRQ1_EXT 1
-#define IRQ_U300_DMA 2
-#define IRQ_U300_VIDEO_ENC_0 3
-#define IRQ_U300_VIDEO_ENC_1 4
-#define IRQ_U300_AAIF_RX 5
-#define IRQ_U300_AAIF_TX 6
-#define IRQ_U300_AAIF_VGPIO 7
-#define IRQ_U300_AAIF_WAKEUP 8
-#define IRQ_U300_PCM_I2S0_FRAME 9
-#define IRQ_U300_PCM_I2S0_FIFO 10
-#define IRQ_U300_PCM_I2S1_FRAME 11
-#define IRQ_U300_PCM_I2S1_FIFO 12
-#define IRQ_U300_XGAM_GAMCON 13
-#define IRQ_U300_XGAM_CDI 14
-#define IRQ_U300_XGAM_CDICON 15
+#define IRQ_U300_IRQ0_EXT 1
+#define IRQ_U300_IRQ1_EXT 2
+#define IRQ_U300_DMA 3
+#define IRQ_U300_VIDEO_ENC_0 4
+#define IRQ_U300_VIDEO_ENC_1 5
+#define IRQ_U300_AAIF_RX 6
+#define IRQ_U300_AAIF_TX 7
+#define IRQ_U300_AAIF_VGPIO 8
+#define IRQ_U300_AAIF_WAKEUP 9
+#define IRQ_U300_PCM_I2S0_FRAME 10
+#define IRQ_U300_PCM_I2S0_FIFO 11
+#define IRQ_U300_PCM_I2S1_FRAME 12
+#define IRQ_U300_PCM_I2S1_FIFO 13
+#define IRQ_U300_XGAM_GAMCON 14
+#define IRQ_U300_XGAM_CDI 15
+#define IRQ_U300_XGAM_CDICON 16
#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
/* MMIACC not used on the DB3210 or DB3350 chips */
-#define IRQ_U300_XGAM_MMIACC 16
+#define IRQ_U300_XGAM_MMIACC 17
#endif
-#define IRQ_U300_XGAM_PDI 17
-#define IRQ_U300_XGAM_PDICON 18
-#define IRQ_U300_XGAM_GAMEACC 19
-#define IRQ_U300_XGAM_MCIDCT 20
-#define IRQ_U300_APEX 21
-#define IRQ_U300_UART0 22
-#define IRQ_U300_SPI 23
-#define IRQ_U300_TIMER_APP_OS 24
-#define IRQ_U300_TIMER_APP_DD 25
-#define IRQ_U300_TIMER_APP_GP1 26
-#define IRQ_U300_TIMER_APP_GP2 27
-#define IRQ_U300_TIMER_OS 28
-#define IRQ_U300_TIMER_MS 29
-#define IRQ_U300_KEYPAD_KEYBF 30
-#define IRQ_U300_KEYPAD_KEYBR 31
+#define IRQ_U300_XGAM_PDI 18
+#define IRQ_U300_XGAM_PDICON 19
+#define IRQ_U300_XGAM_GAMEACC 20
+#define IRQ_U300_XGAM_MCIDCT 21
+#define IRQ_U300_APEX 22
+#define IRQ_U300_UART0 23
+#define IRQ_U300_SPI 24
+#define IRQ_U300_TIMER_APP_OS 25
+#define IRQ_U300_TIMER_APP_DD 26
+#define IRQ_U300_TIMER_APP_GP1 27
+#define IRQ_U300_TIMER_APP_GP2 28
+#define IRQ_U300_TIMER_OS 29
+#define IRQ_U300_TIMER_MS 30
+#define IRQ_U300_KEYPAD_KEYBF 31
+#define IRQ_U300_KEYPAD_KEYBR 32
/* These are on INTCON1 - 32 lines */
-#define IRQ_U300_GPIO_PORT0 32
-#define IRQ_U300_GPIO_PORT1 33
-#define IRQ_U300_GPIO_PORT2 34
+#define IRQ_U300_GPIO_PORT0 33
+#define IRQ_U300_GPIO_PORT1 34
+#define IRQ_U300_GPIO_PORT2 35
#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) || \
defined(CONFIG_MACH_U300_BS335)
/* These are for DB3150, DB3200 and DB3350 */
-#define IRQ_U300_WDOG 35
-#define IRQ_U300_EVHIST 36
-#define IRQ_U300_MSPRO 37
-#define IRQ_U300_MMCSD_MCIINTR0 38
-#define IRQ_U300_MMCSD_MCIINTR1 39
-#define IRQ_U300_I2C0 40
-#define IRQ_U300_I2C1 41
-#define IRQ_U300_RTC 42
-#define IRQ_U300_NFIF 43
-#define IRQ_U300_NFIF2 44
+#define IRQ_U300_WDOG 36
+#define IRQ_U300_EVHIST 37
+#define IRQ_U300_MSPRO 38
+#define IRQ_U300_MMCSD_MCIINTR0 39
+#define IRQ_U300_MMCSD_MCIINTR1 40
+#define IRQ_U300_I2C0 41
+#define IRQ_U300_I2C1 42
+#define IRQ_U300_RTC 43
+#define IRQ_U300_NFIF 44
+#define IRQ_U300_NFIF2 45
#endif
/* DB3150 and DB3200 have only 45 IRQs */
#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330)
-#define U300_VIC_IRQS_END 45
+#define U300_VIC_IRQS_END 46
#endif
/* The DB3350-specific interrupt lines */
#ifdef CONFIG_MACH_U300_BS335
-#define IRQ_U300_ISP_F0 45
-#define IRQ_U300_ISP_F1 46
-#define IRQ_U300_ISP_F2 47
-#define IRQ_U300_ISP_F3 48
-#define IRQ_U300_ISP_F4 49
-#define IRQ_U300_GPIO_PORT3 50
-#define IRQ_U300_SYSCON_PLL_LOCK 51
-#define IRQ_U300_UART1 52
-#define IRQ_U300_GPIO_PORT4 53
-#define IRQ_U300_GPIO_PORT5 54
-#define IRQ_U300_GPIO_PORT6 55
-#define U300_VIC_IRQS_END 56
+#define IRQ_U300_ISP_F0 46
+#define IRQ_U300_ISP_F1 47
+#define IRQ_U300_ISP_F2 48
+#define IRQ_U300_ISP_F3 49
+#define IRQ_U300_ISP_F4 50
+#define IRQ_U300_GPIO_PORT3 51
+#define IRQ_U300_SYSCON_PLL_LOCK 52
+#define IRQ_U300_UART1 53
+#define IRQ_U300_GPIO_PORT4 54
+#define IRQ_U300_GPIO_PORT5 55
+#define IRQ_U300_GPIO_PORT6 56
+#define U300_VIC_IRQS_END 57
#endif
/* The DB3210-specific interrupt lines */
#ifdef CONFIG_MACH_U300_BS365
-#define IRQ_U300_GPIO_PORT3 35
-#define IRQ_U300_GPIO_PORT4 36
-#define IRQ_U300_WDOG 37
-#define IRQ_U300_EVHIST 38
-#define IRQ_U300_MSPRO 39
-#define IRQ_U300_MMCSD_MCIINTR0 40
-#define IRQ_U300_MMCSD_MCIINTR1 41
-#define IRQ_U300_I2C0 42
-#define IRQ_U300_I2C1 43
-#define IRQ_U300_RTC 44
-#define IRQ_U300_NFIF 45
-#define IRQ_U300_NFIF2 46
-#define IRQ_U300_SYSCON_PLL_LOCK 47
-#define U300_VIC_IRQS_END 48
+#define IRQ_U300_GPIO_PORT3 36
+#define IRQ_U300_GPIO_PORT4 37
+#define IRQ_U300_WDOG 38
+#define IRQ_U300_EVHIST 39
+#define IRQ_U300_MSPRO 40
+#define IRQ_U300_MMCSD_MCIINTR0 41
+#define IRQ_U300_MMCSD_MCIINTR1 42
+#define IRQ_U300_I2C0 43
+#define IRQ_U300_I2C1 44
+#define IRQ_U300_RTC 45
+#define IRQ_U300_NFIF 46
+#define IRQ_U300_NFIF2 47
+#define IRQ_U300_SYSCON_PLL_LOCK 48
+#define U300_VIC_IRQS_END 49
#endif
/* Maximum 8*7 GPIO lines */
@@ -117,6 +117,6 @@
#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END)
#endif
-#define NR_IRQS (IRQ_U300_GPIO_END)
+#define NR_IRQS (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
#endif
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 880d02e..ef7099e 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -17,6 +17,7 @@
config UX500_SOC_DB8500
bool
select MFD_DB8500_PRCMU
+ select REGULATOR
select REGULATOR_DB8500_PRCMU
select CPU_FREQ_TABLE if CPU_FREQ
diff --git a/arch/arm/mach-ux500/mbox-db5500.c b/arch/arm/mach-ux500/mbox-db5500.c
index 2b2d51c..0127490 100644
--- a/arch/arm/mach-ux500/mbox-db5500.c
+++ b/arch/arm/mach-ux500/mbox-db5500.c
@@ -168,7 +168,7 @@
return sprintf(buf, "0x%X\n", mbox_value);
}
-static DEVICE_ATTR(fifo, S_IWUGO | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
+static DEVICE_ATTR(fifo, S_IWUSR | S_IRUGO, mbox_read_fifo, mbox_write_fifo);
static int mbox_show(struct seq_file *s, void *data)
{
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index d2058ef..eff5842 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -99,7 +99,7 @@
*/
write_pen_release(cpu_logical_map(cpu));
- gic_raise_softirq(cpumask_of(cpu), 1);
+ smp_send_reschedule(cpu);
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
index a6e23f4..d2268be8 100644
--- a/arch/arm/mach-versatile/pci.c
+++ b/arch/arm/mach-versatile/pci.c
@@ -190,7 +190,7 @@
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
};
-static int __init pci_versatile_setup_resources(struct list_head *resources)
+static int __init pci_versatile_setup_resources(struct pci_sys_data *sys)
{
int ret = 0;
@@ -218,9 +218,9 @@
* the mem resource for this bus
* the prefetch mem resource for this bus
*/
- pci_add_resource_offset(resources, &io_mem, sys->io_offset);
- pci_add_resource_offset(resources, &non_mem, sys->mem_offset);
- pci_add_resource_offset(resources, &pre_mem, sys->mem_offset);
+ pci_add_resource_offset(&sys->resources, &io_mem, sys->io_offset);
+ pci_add_resource_offset(&sys->resources, &non_mem, sys->mem_offset);
+ pci_add_resource_offset(&sys->resources, &pre_mem, sys->mem_offset);
goto out;
@@ -249,7 +249,7 @@
if (nr == 0) {
sys->mem_offset = 0;
- ret = pci_versatile_setup_resources(&sys->resources);
+ ret = pci_versatile_setup_resources(sys);
if (ret < 0) {
printk("pci_versatile_setup: resources... oops?\n");
goto out;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 7edef91..7c8a7d8 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -723,7 +723,7 @@
bool "Select the High exception vector"
help
Say Y here to select high exception vector(0xFFFF0000~).
- The exception vector can be vary depending on the platform
+ The exception vector can vary depending on the platform
design in nommu mode. If your platform needs to select
high exception vector, say Y.
Otherwise or if you are unsure, say N, and the low exception
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index ff1f7cc..8074199 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -26,18 +26,23 @@
mrc p15, 0, r1, c5, c0, 0 @ get FSR
mrc p15, 0, r0, c6, c0, 0 @ get FAR
/*
- * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR (erratum 326103).
- * The test below covers all the write situations, including Java bytecodes
+ * Faulty SWP instruction on 1136 doesn't set bit 11 in DFSR.
*/
- bic r1, r1, #1 << 11 @ clear bit 11 of FSR
- tst r5, #PSR_J_BIT @ Java?
+#ifdef CONFIG_ARM_ERRATA_326103
+ ldr ip, =0x4107b36
+ mrc p15, 0, r3, c0, c0, 0 @ get processor id
+ teq ip, r3, lsr #4 @ r0 ARM1136?
bne do_DataAbort
- do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3
- ldreq r3, [r4] @ read aborted ARM instruction
+ tst r5, #PSR_J_BIT @ Java?
+ tsteq r5, #PSR_T_BIT @ Thumb?
+ bne do_DataAbort
+ bic r1, r1, #1 << 11 @ clear bit 11 of FSR
+ ldr r3, [r4] @ read aborted ARM instruction
#ifdef CONFIG_CPU_ENDIAN_BE8
- reveq r3, r3
+ rev r3, r3
#endif
do_ldrd_abort tmp=ip, insn=r3
tst r3, #1 << 20 @ L = 0 -> write
orreq r1, r1, #1 << 11 @ yes.
+#endif
b do_DataAbort
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index a53fd2a..2a8e380 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -32,6 +32,7 @@
static DEFINE_RAW_SPINLOCK(l2x0_lock);
static u32 l2x0_way_mask; /* Bitmask of active ways */
static u32 l2x0_size;
+static unsigned long sync_reg_offset = L2X0_CACHE_SYNC;
struct l2x0_regs l2x0_saved_regs;
@@ -61,12 +62,7 @@
{
void __iomem *base = l2x0_base;
-#ifdef CONFIG_PL310_ERRATA_753970
- /* write to an unmmapped register */
- writel_relaxed(0, base + L2X0_DUMMY_REG);
-#else
- writel_relaxed(0, base + L2X0_CACHE_SYNC);
-#endif
+ writel_relaxed(0, base + sync_reg_offset);
cache_wait(base + L2X0_CACHE_SYNC, 1);
}
@@ -85,10 +81,13 @@
}
#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
+static inline void debug_writel(unsigned long val)
+{
+ if (outer_cache.set_debug)
+ outer_cache.set_debug(val);
+}
-#define debug_writel(val) outer_cache.set_debug(val)
-
-static void l2x0_set_debug(unsigned long val)
+static void pl310_set_debug(unsigned long val)
{
writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
}
@@ -98,7 +97,7 @@
{
}
-#define l2x0_set_debug NULL
+#define pl310_set_debug NULL
#endif
#ifdef CONFIG_PL310_ERRATA_588369
@@ -331,6 +330,11 @@
else
ways = 8;
type = "L310";
+#ifdef CONFIG_PL310_ERRATA_753970
+ /* Unmapped register. */
+ sync_reg_offset = L2X0_DUMMY_REG;
+#endif
+ outer_cache.set_debug = pl310_set_debug;
break;
case L2X0_CACHE_ID_PART_L210:
ways = (aux >> 13) & 0xf;
@@ -379,7 +383,6 @@
outer_cache.flush_all = l2x0_flush_all;
outer_cache.inv_all = l2x0_inv_all;
outer_cache.disable = l2x0_disable;
- outer_cache.set_debug = l2x0_set_debug;
printk(KERN_INFO "%s cache controller enabled\n", type);
printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 9055b5a..f074675 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -320,7 +320,7 @@
*/
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
- if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (!(fault & VM_FAULT_ERROR) && flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR) {
tsk->maj_flt++;
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1,
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 595079f..8f5813b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -293,11 +293,11 @@
#endif
#ifndef CONFIG_SPARSEMEM
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
{
}
#else
-static void arm_memory_present(void)
+static void __init arm_memory_present(void)
{
struct memblock_region *reg;
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index b86f893..2c7cf2f 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -618,8 +618,8 @@
}
}
-static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
- unsigned long phys, const struct mem_type *type)
+static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
+ unsigned long end, unsigned long phys, const struct mem_type *type)
{
pud_t *pud = pud_offset(pgd, addr);
unsigned long next;
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index 6486d2f..d51225f 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -13,6 +13,7 @@
#include <asm/sections.h>
#include <asm/page.h>
#include <asm/setup.h>
+#include <asm/traps.h>
#include <asm/mach/arch.h>
#include "mm.h"
@@ -39,6 +40,7 @@
*/
void __init paging_init(struct machine_desc *mdesc)
{
+ early_trap_init((void *)CONFIG_VECTORS_BASE);
bootmem_init();
}
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index f1c8486..c2e2b66 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -255,6 +255,18 @@
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
#endif
+#ifndef CONFIG_ARM_THUMBEE
+ mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE
+ and r0, r0, #(0xf << 12) @ ThumbEE enabled field
+ teq r0, #(1 << 12) @ check if ThumbEE is present
+ bne 1f
+ mov r5, #0
+ mcr p14, 6, r5, c1, c0, 0 @ Initialize TEEHBR to 0
+ mrc p14, 6, r0, c0, c0, 0 @ load TEECR
+ orr r0, r0, #1 @ set the 1st bit in order to
+ mcr p14, 6, r0, c0, c0, 0 @ stop userspace TEEHBR access
+1:
+#endif
adr r5, v7_crval
ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8
diff --git a/arch/arm/plat-mxc/3ds_debugboard.c b/arch/arm/plat-mxc/3ds_debugboard.c
index d1e31fa..5cac2c5 100644
--- a/arch/arm/plat-mxc/3ds_debugboard.c
+++ b/arch/arm/plat-mxc/3ds_debugboard.c
@@ -80,7 +80,7 @@
static struct platform_device smsc_lan9217_device = {
.name = "smsc911x",
- .id = 0,
+ .id = -1,
.dev = {
.platform_data = &smsc911x_config,
},
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index ce1e9b9..ad95c7a 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -17,6 +17,7 @@
select IRQ_DOMAIN
select HAVE_IDE
select NEED_MACH_MEMORY_H
+ select NEED_MACH_IO_H if PCCARD
help
"Systems based on omap7xx, omap15xx or omap16xx"
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 56b6f8b..62ec5c4 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -398,32 +398,6 @@
.ops = &clkops_null,
};
-#ifdef CONFIG_CPU_FREQ
-void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- unsigned long flags;
-
- if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
- return;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- arch_clock->clk_init_cpufreq_table(table);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-
-void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
-{
- unsigned long flags;
-
- if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
- return;
-
- spin_lock_irqsave(&clockfw_lock, flags);
- arch_clock->clk_exit_cpufreq_table(table);
- spin_unlock_irqrestore(&clockfw_lock, flags);
-}
-#endif
-
/*
*
*/
@@ -441,6 +415,8 @@
return 0;
pr_info("clock: disabling unused clocks to save power\n");
+
+ spin_lock_irqsave(&clockfw_lock, flags);
list_for_each_entry(ck, &clocks, node) {
if (ck->ops == &clkops_null)
continue;
@@ -448,10 +424,9 @@
if (ck->usecount > 0 || !ck->enable_reg)
continue;
- spin_lock_irqsave(&clockfw_lock, flags);
arch_clock->clk_disable_unused(ck);
- spin_unlock_irqrestore(&clockfw_lock, flags);
}
+ spin_unlock_irqrestore(&clockfw_lock, flags);
return 0;
}
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c
index ecdb3da..c58d896 100644
--- a/arch/arm/plat-omap/dma.c
+++ b/arch/arm/plat-omap/dma.c
@@ -916,6 +916,13 @@
l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
l |= OMAP_DMA_CCR_EN;
+ /*
+ * As dma_write() uses IO accessors which are weakly ordered, there
+ * is no guarantee that data in coherent DMA memory will be visible
+ * to the DMA device. Add a memory barrier here to ensure that any
+ * such data is visible prior to enabling DMA.
+ */
+ mb();
p->dma_write(l, CCR, lch);
dma_chan[lch].flags |= OMAP_DMA_ACTIVE;
@@ -965,6 +972,13 @@
p->dma_write(l, CCR, lch);
}
+ /*
+ * Ensure that data transferred by DMA is visible to any access
+ * after DMA has been disabled. This is important for coherent
+ * DMA regions.
+ */
+ mb();
+
if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
int next_lch, cur_lch = lch;
char dma_chan_link_map[dma_lch_count];
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index 240a7b9..d0ef57c 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -272,8 +272,6 @@
#endif
};
-struct cpufreq_frequency_table;
-
struct clk_functions {
int (*clk_enable)(struct clk *clk);
void (*clk_disable)(struct clk *clk);
@@ -283,10 +281,6 @@
void (*clk_allow_idle)(struct clk *clk);
void (*clk_deny_idle)(struct clk *clk);
void (*clk_disable_unused)(struct clk *clk);
-#ifdef CONFIG_CPU_FREQ
- void (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **);
- void (*clk_exit_cpufreq_table)(struct cpufreq_frequency_table **);
-#endif
};
extern int mpurate;
@@ -301,10 +295,6 @@
extern unsigned long followparent_recalc(struct clk *clk);
extern void clk_enable_init_clocks(void);
unsigned long omap_fixed_divisor_recalc(struct clk *clk);
-#ifdef CONFIG_CPU_FREQ
-extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
-extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
-#endif
extern struct clk *omap_clk_get_by_name(const char *name);
extern int omap_clk_enable_autoidle_all(void);
extern int omap_clk_disable_autoidle_all(void);
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 9e8e63d..3f26db4 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -47,17 +47,17 @@
* with the original PRCM protocol defined for OMAP2420
*/
#define SYSC_TYPE1_MIDLEMODE_SHIFT 12
-#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_MIDLEMODE_SHIFT)
+#define SYSC_TYPE1_MIDLEMODE_MASK (0x3 << SYSC_TYPE1_MIDLEMODE_SHIFT)
#define SYSC_TYPE1_CLOCKACTIVITY_SHIFT 8
-#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_CLOCKACTIVITY_SHIFT)
+#define SYSC_TYPE1_CLOCKACTIVITY_MASK (0x3 << SYSC_TYPE1_CLOCKACTIVITY_SHIFT)
#define SYSC_TYPE1_SIDLEMODE_SHIFT 3
-#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_SIDLEMODE_SHIFT)
+#define SYSC_TYPE1_SIDLEMODE_MASK (0x3 << SYSC_TYPE1_SIDLEMODE_SHIFT)
#define SYSC_TYPE1_ENAWAKEUP_SHIFT 2
-#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_ENAWAKEUP_SHIFT)
+#define SYSC_TYPE1_ENAWAKEUP_MASK (1 << SYSC_TYPE1_ENAWAKEUP_SHIFT)
#define SYSC_TYPE1_SOFTRESET_SHIFT 1
-#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_SOFTRESET_SHIFT)
+#define SYSC_TYPE1_SOFTRESET_MASK (1 << SYSC_TYPE1_SOFTRESET_SHIFT)
#define SYSC_TYPE1_AUTOIDLE_SHIFT 0
-#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_AUTOIDLE_SHIFT)
+#define SYSC_TYPE1_AUTOIDLE_MASK (1 << SYSC_TYPE1_AUTOIDLE_SHIFT)
/*
* OCP SYSCONFIG bit shifts/masks TYPE2. These are for IPs compliant
@@ -305,6 +305,7 @@
* @rev_offs: IP block revision register offset (from module base addr)
* @sysc_offs: OCP_SYSCONFIG register offset (from module base addr)
* @syss_offs: OCP_SYSSTATUS register offset (from module base addr)
+ * @srst_udelay: Delay needed after doing a softreset in usecs
* @idlemodes: One or more of {SIDLE,MSTANDBY}_{OFF,FORCE,SMART}
* @sysc_flags: SYS{C,S}_HAS* flags indicating SYSCONFIG bits supported
* @clockact: the default value of the module CLOCKACTIVITY bits
@@ -330,9 +331,10 @@
u16 sysc_offs;
u16 syss_offs;
u16 sysc_flags;
+ struct omap_hwmod_sysc_fields *sysc_fields;
+ u8 srst_udelay;
u8 idlemodes;
u8 clockact;
- struct omap_hwmod_sysc_fields *sysc_fields;
};
/**
diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c
index eec98af..f9a8c53 100644
--- a/arch/arm/plat-omap/sram.c
+++ b/arch/arm/plat-omap/sram.c
@@ -348,7 +348,6 @@
sdrc_actim_ctrl_b_1, sdrc_mr_1);
}
-#ifdef CONFIG_PM
void omap3_sram_restore_context(void)
{
omap_sram_ceil = omap_sram_base + omap_sram_size;
@@ -358,17 +357,18 @@
omap3_sram_configure_core_dpll_sz);
omap_push_sram_idle();
}
-#endif /* CONFIG_PM */
-
-#endif /* CONFIG_ARCH_OMAP3 */
static inline int omap34xx_sram_init(void)
{
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
omap3_sram_restore_context();
-#endif
return 0;
}
+#else
+static inline int omap34xx_sram_init(void)
+{
+ return 0;
+}
+#endif /* CONFIG_ARCH_OMAP3 */
static inline int am33xx_sram_init(void)
{
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 71553f4..a0ffc77d 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -302,6 +302,7 @@
config SAMSUNG_PM_DEBUG
bool "S3C2410 PM Suspend debug"
depends on PM
+ select DEBUG_LL
help
Say Y here if you want verbose debugging from the PM Suspend and
Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
diff --git a/arch/arm/plat-samsung/include/plat/sdhci.h b/arch/arm/plat-samsung/include/plat/sdhci.h
index 317e246..e834c5e 100644
--- a/arch/arm/plat-samsung/include/plat/sdhci.h
+++ b/arch/arm/plat-samsung/include/plat/sdhci.h
@@ -18,6 +18,8 @@
#ifndef __PLAT_S3C_SDHCI_H
#define __PLAT_S3C_SDHCI_H __FILE__
+#include <plat/devs.h>
+
struct platform_device;
struct mmc_host;
struct mmc_card;
@@ -356,4 +358,30 @@
#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
+static inline void s3c_sdhci_setname(int id, char *name)
+{
+ switch (id) {
+#ifdef CONFIG_S3C_DEV_HSMMC
+ case 0:
+ s3c_device_hsmmc0.name = name;
+ break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC1
+ case 1:
+ s3c_device_hsmmc1.name = name;
+ break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC2
+ case 2:
+ s3c_device_hsmmc2.name = name;
+ break;
+#endif
+#ifdef CONFIG_S3C_DEV_HSMMC3
+ case 3:
+ s3c_device_hsmmc3.name = name;
+ break;
+#endif
+ }
+}
+
#endif /* __PLAT_S3C_SDHCI_H */
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 858748e..bc683b8 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/user.h>
#include <asm/cp15.h>
#include <asm/cputype.h>
@@ -529,6 +531,103 @@
}
/*
+ * Save the current VFP state into the provided structures and prepare
+ * for entry into a new function (signal handler).
+ */
+int vfp_preserve_user_clear_hwstate(struct user_vfp __user *ufp,
+ struct user_vfp_exc __user *ufp_exc)
+{
+ struct thread_info *thread = current_thread_info();
+ struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
+ int err = 0;
+
+ /* Ensure that the saved hwstate is up-to-date. */
+ vfp_sync_hwstate(thread);
+
+ /*
+ * Copy the floating point registers. There can be unused
+ * registers see asm/hwcap.h for details.
+ */
+ err |= __copy_to_user(&ufp->fpregs, &hwstate->fpregs,
+ sizeof(hwstate->fpregs));
+ /*
+ * Copy the status and control register.
+ */
+ __put_user_error(hwstate->fpscr, &ufp->fpscr, err);
+
+ /*
+ * Copy the exception registers.
+ */
+ __put_user_error(hwstate->fpexc, &ufp_exc->fpexc, err);
+ __put_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
+ __put_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
+
+ if (err)
+ return -EFAULT;
+
+ /* Ensure that VFP is disabled. */
+ vfp_flush_hwstate(thread);
+
+ /*
+ * As per the PCS, clear the length and stride bits for function
+ * entry.
+ */
+ hwstate->fpscr &= ~(FPSCR_LENGTH_MASK | FPSCR_STRIDE_MASK);
+
+ /*
+ * Disable VFP in the hwstate so that we can detect if it gets
+ * used.
+ */
+ hwstate->fpexc &= ~FPEXC_EN;
+ return 0;
+}
+
+/* Sanitise and restore the current VFP state from the provided structures. */
+int vfp_restore_user_hwstate(struct user_vfp __user *ufp,
+ struct user_vfp_exc __user *ufp_exc)
+{
+ struct thread_info *thread = current_thread_info();
+ struct vfp_hard_struct *hwstate = &thread->vfpstate.hard;
+ unsigned long fpexc;
+ int err = 0;
+
+ /*
+ * If VFP has been used, then disable it to avoid corrupting
+ * the new thread state.
+ */
+ if (hwstate->fpexc & FPEXC_EN)
+ vfp_flush_hwstate(thread);
+
+ /*
+ * Copy the floating point registers. There can be unused
+ * registers see asm/hwcap.h for details.
+ */
+ err |= __copy_from_user(&hwstate->fpregs, &ufp->fpregs,
+ sizeof(hwstate->fpregs));
+ /*
+ * Copy the status and control register.
+ */
+ __get_user_error(hwstate->fpscr, &ufp->fpscr, err);
+
+ /*
+ * Sanitise and restore the exception registers.
+ */
+ __get_user_error(fpexc, &ufp_exc->fpexc, err);
+
+ /* Ensure the VFP is enabled. */
+ fpexc |= FPEXC_EN;
+
+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
+ hwstate->fpexc = fpexc;
+
+ __get_user_error(hwstate->fpinst, &ufp_exc->fpinst, err);
+ __get_user_error(hwstate->fpinst2, &ufp_exc->fpinst2, err);
+
+ return err ? -EFAULT : 0;
+}
+
+/*
* VFP hardware can lose all context when a CPU goes offline.
* As we will be running in SMP mode with CPU hotplug, we will save the
* hardware state at every thread switch. We clear our held state when
diff --git a/arch/avr32/include/asm/barrier.h b/arch/avr32/include/asm/barrier.h
index 808001c..0961275 100644
--- a/arch/avr32/include/asm/barrier.h
+++ b/arch/avr32/include/asm/barrier.h
@@ -8,6 +8,8 @@
#ifndef __ASM_AVR32_BARRIER_H
#define __ASM_AVR32_BARRIER_H
+#define nop() asm volatile("nop")
+
#define mb() asm volatile("" : : : "memory")
#define rmb() mb()
#define wmb() asm volatile("sync 0" : : : "memory")
diff --git a/arch/avr32/include/asm/special_insns.h b/arch/avr32/include/asm/special_insns.h
deleted file mode 100644
index f922218..0000000
--- a/arch/avr32/include/asm/special_insns.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef __ASM_AVR32_SPECIAL_INSNS_H
-#define __ASM_AVR32_SPECIAL_INSNS_H
-
-#define nop() asm volatile("nop")
-
-#endif /* __ASM_AVR32_SPECIAL_INSNS_H */
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index 7173386..70742ec9 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -7,7 +7,7 @@
#include <linux/types.h>
#include <linux/serial.h>
#include <linux/platform_data/macb.h>
-#include <linux/platform_data/atmel_nand.h>
+#include <linux/platform_data/atmel.h>
#define GPIO_PIN_NONE (-1)
diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
index c1269a1..373a690 100644
--- a/arch/blackfin/Kconfig
+++ b/arch/blackfin/Kconfig
@@ -823,7 +823,7 @@
bool "Locate cacheline_aligned data to L1 Data Memory"
default y if !BF54x
default n if BF54x
- depends on !SMP && !BF531
+ depends on !SMP && !BF531 && !CRC32
help
If enabled, cacheline_aligned data is linked
into L1 data memory. (less latency)
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index 9ccc18a..90b1753 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -147,6 +147,7 @@
CONFIG_USB_MON=y
CONFIG_USB_MUSB_HDRC=y
CONFIG_USB_MUSB_BLACKFIN=y
+CONFIG_MUSB_PIO_ONLY=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_RTC_CLASS=y
diff --git a/arch/blackfin/include/asm/cmpxchg.h b/arch/blackfin/include/asm/cmpxchg.h
index ba2484f..c05868c 100644
--- a/arch/blackfin/include/asm/cmpxchg.h
+++ b/arch/blackfin/include/asm/cmpxchg.h
@@ -122,7 +122,8 @@
(unsigned long)(n), sizeof(*(ptr))))
#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#include <asm-generic/cmpxchg.h>
+#define cmpxchg(ptr, o, n) cmpxchg_local((ptr), (o), (n))
+#define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n))
#endif /* !CONFIG_SMP */
diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h
index 5a25856..12d3571 100644
--- a/arch/blackfin/include/asm/gpio.h
+++ b/arch/blackfin/include/asm/gpio.h
@@ -244,16 +244,26 @@
return -EINVAL;
}
-static inline int gpio_get_value(unsigned gpio)
+static inline int __gpio_get_value(unsigned gpio)
{
return bfin_gpio_get_value(gpio);
}
-static inline void gpio_set_value(unsigned gpio, int value)
+static inline void __gpio_set_value(unsigned gpio, int value)
{
return bfin_gpio_set_value(gpio, value);
}
+static inline int gpio_get_value(unsigned gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ return __gpio_set_value(gpio, value);
+}
+
static inline int gpio_to_irq(unsigned gpio)
{
if (likely(gpio < MAX_BLACKFIN_GPIOS))
diff --git a/arch/blackfin/mach-bf538/boards/ezkit.c b/arch/blackfin/mach-bf538/boards/ezkit.c
index 1633a6f..85038f54 100644
--- a/arch/blackfin/mach-bf538/boards/ezkit.c
+++ b/arch/blackfin/mach-bf538/boards/ezkit.c
@@ -38,7 +38,7 @@
.name = "rtc-bfin",
.id = -1,
};
-#endif
+#endif /* CONFIG_RTC_DRV_BFIN */
#if defined(CONFIG_SERIAL_BFIN) || defined(CONFIG_SERIAL_BFIN_MODULE)
#ifdef CONFIG_SERIAL_BFIN_UART0
@@ -100,7 +100,7 @@
.platform_data = &bfin_uart0_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART0 */
#ifdef CONFIG_SERIAL_BFIN_UART1
static struct resource bfin_uart1_resources[] = {
{
@@ -148,7 +148,7 @@
.platform_data = &bfin_uart1_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART1 */
#ifdef CONFIG_SERIAL_BFIN_UART2
static struct resource bfin_uart2_resources[] = {
{
@@ -196,8 +196,8 @@
.platform_data = &bfin_uart2_peripherals, /* Passed to driver */
},
};
-#endif
-#endif
+#endif /* CONFIG_SERIAL_BFIN_UART2 */
+#endif /* CONFIG_SERIAL_BFIN */
#if defined(CONFIG_BFIN_SIR) || defined(CONFIG_BFIN_SIR_MODULE)
#ifdef CONFIG_BFIN_SIR0
@@ -224,7 +224,7 @@
.num_resources = ARRAY_SIZE(bfin_sir0_resources),
.resource = bfin_sir0_resources,
};
-#endif
+#endif /* CONFIG_BFIN_SIR0 */
#ifdef CONFIG_BFIN_SIR1
static struct resource bfin_sir1_resources[] = {
{
@@ -249,7 +249,7 @@
.num_resources = ARRAY_SIZE(bfin_sir1_resources),
.resource = bfin_sir1_resources,
};
-#endif
+#endif /* CONFIG_BFIN_SIR1 */
#ifdef CONFIG_BFIN_SIR2
static struct resource bfin_sir2_resources[] = {
{
@@ -274,8 +274,8 @@
.num_resources = ARRAY_SIZE(bfin_sir2_resources),
.resource = bfin_sir2_resources,
};
-#endif
-#endif
+#endif /* CONFIG_BFIN_SIR2 */
+#endif /* CONFIG_BFIN_SIR */
#if defined(CONFIG_SERIAL_BFIN_SPORT) || defined(CONFIG_SERIAL_BFIN_SPORT_MODULE)
#ifdef CONFIG_SERIAL_BFIN_SPORT0_UART
@@ -311,7 +311,7 @@
.platform_data = &bfin_sport0_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT0_UART */
#ifdef CONFIG_SERIAL_BFIN_SPORT1_UART
static struct resource bfin_sport1_uart_resources[] = {
{
@@ -345,7 +345,7 @@
.platform_data = &bfin_sport1_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT1_UART */
#ifdef CONFIG_SERIAL_BFIN_SPORT2_UART
static struct resource bfin_sport2_uart_resources[] = {
{
@@ -379,7 +379,7 @@
.platform_data = &bfin_sport2_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT2_UART */
#ifdef CONFIG_SERIAL_BFIN_SPORT3_UART
static struct resource bfin_sport3_uart_resources[] = {
{
@@ -413,8 +413,8 @@
.platform_data = &bfin_sport3_peripherals, /* Passed to driver */
},
};
-#endif
-#endif
+#endif /* CONFIG_SERIAL_BFIN_SPORT3_UART */
+#endif /* CONFIG_SERIAL_BFIN_SPORT */
#if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
static unsigned short bfin_can_peripherals[] = {
@@ -452,7 +452,7 @@
.platform_data = &bfin_can_peripherals, /* Passed to driver */
},
};
-#endif
+#endif /* CONFIG_CAN_BFIN */
/*
* USB-LAN EzExtender board
@@ -488,7 +488,7 @@
.platform_data = &smc91x_info,
},
};
-#endif
+#endif /* CONFIG_SMC91X */
#if defined(CONFIG_SPI_BFIN5XX) || defined(CONFIG_SPI_BFIN5XX_MODULE)
/* all SPI peripherals info goes here */
@@ -518,7 +518,8 @@
static struct bfin5xx_spi_chip spi_flash_chip_info = {
.enable_dma = 0, /* use dma transfer with this chip*/
};
-#endif
+#endif /* CONFIG_MTD_M25P80 */
+#endif /* CONFIG_SPI_BFIN5XX */
#if defined(CONFIG_TOUCHSCREEN_AD7879) || defined(CONFIG_TOUCHSCREEN_AD7879_MODULE)
#include <linux/spi/ad7879.h>
@@ -535,7 +536,7 @@
.gpio_export = 1, /* Export GPIO to gpiolib */
.gpio_base = -1, /* Dynamic allocation */
};
-#endif
+#endif /* CONFIG_TOUCHSCREEN_AD7879 */
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
#include <asm/bfin-lq035q1.h>
@@ -564,7 +565,7 @@
.platform_data = &bfin_lq035q1_data,
},
};
-#endif
+#endif /* CONFIG_FB_BFIN_LQ035Q1 */
static struct spi_board_info bf538_spi_board_info[] __initdata = {
#if defined(CONFIG_MTD_M25P80) \
@@ -579,7 +580,7 @@
.controller_data = &spi_flash_chip_info,
.mode = SPI_MODE_3,
},
-#endif
+#endif /* CONFIG_MTD_M25P80 */
#if defined(CONFIG_TOUCHSCREEN_AD7879_SPI) || defined(CONFIG_TOUCHSCREEN_AD7879_SPI_MODULE)
{
.modalias = "ad7879",
@@ -590,7 +591,7 @@
.chip_select = 1,
.mode = SPI_CPHA | SPI_CPOL,
},
-#endif
+#endif /* CONFIG_TOUCHSCREEN_AD7879_SPI */
#if defined(CONFIG_FB_BFIN_LQ035Q1) || defined(CONFIG_FB_BFIN_LQ035Q1_MODULE)
{
.modalias = "bfin-lq035q1-spi",
@@ -599,7 +600,7 @@
.chip_select = 2,
.mode = SPI_CPHA | SPI_CPOL,
},
-#endif
+#endif /* CONFIG_FB_BFIN_LQ035Q1 */
#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
{
.modalias = "spidev",
@@ -607,7 +608,7 @@
.bus_num = 0,
.chip_select = 1,
},
-#endif
+#endif /* CONFIG_SPI_SPIDEV */
};
/* SPI (0) */
@@ -716,8 +717,6 @@
},
};
-#endif /* spi master and devices */
-
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE)
static struct resource bfin_twi0_resource[] = {
[0] = {
@@ -759,8 +758,8 @@
.num_resources = ARRAY_SIZE(bfin_twi1_resource),
.resource = bfin_twi1_resource,
};
-#endif
-#endif
+#endif /* CONFIG_BF542 */
+#endif /* CONFIG_I2C_BLACKFIN_TWI */
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
#include <linux/gpio_keys.h>
diff --git a/arch/c6x/include/asm/irq.h b/arch/c6x/include/asm/irq.h
index f13b78d..ab4577f 100644
--- a/arch/c6x/include/asm/irq.h
+++ b/arch/c6x/include/asm/irq.h
@@ -42,10 +42,6 @@
/* This number is used when no interrupt has been assigned */
#define NO_IRQ 0
-struct irq_data;
-extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
-extern irq_hw_number_t virq_to_hw(unsigned int virq);
-
extern void __init init_pic_c64xplus(void);
extern void init_IRQ(void);
diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c
index 65b8ddf..c90fb5e 100644
--- a/arch/c6x/kernel/irq.c
+++ b/arch/c6x/kernel/irq.c
@@ -130,16 +130,3 @@
seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
return 0;
}
-
-irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
-{
- return d->hwirq;
-}
-EXPORT_SYMBOL_GPL(irqd_to_hwirq);
-
-irq_hw_number_t virq_to_hw(unsigned int virq)
-{
- struct irq_data *irq_data = irq_get_irq_data(virq);
- return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;
-}
-EXPORT_SYMBOL_GPL(virq_to_hw);
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c
index 304f675..3b5a050 100644
--- a/arch/c6x/kernel/signal.c
+++ b/arch/c6x/kernel/signal.c
@@ -85,10 +85,7 @@
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -279,15 +276,8 @@
/* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret == 0) {
- spin_lock_irq(¤t->sighand->siglock);
- sigorsets(¤t->blocked, ¤t->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(¤t->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);
return ret;
}
diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c
index 41098a3..4f8d8bc 100644
--- a/arch/frv/mb93090-mb00/pci-dma.c
+++ b/arch/frv/mb93090-mb00/pci-dma.c
@@ -13,6 +13,7 @@
#include <linux/dma-mapping.h>
#include <linux/list.h>
#include <linux/pci.h>
+#include <linux/export.h>
#include <linux/highmem.h>
#include <linux/scatterlist.h>
#include <asm/io.h>
diff --git a/arch/hexagon/include/asm/dma-mapping.h b/arch/hexagon/include/asm/dma-mapping.h
index 448b224..233ed3d 100644
--- a/arch/hexagon/include/asm/dma-mapping.h
+++ b/arch/hexagon/include/asm/dma-mapping.h
@@ -71,29 +71,35 @@
return (dma_addr == bad_dma_address);
}
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
void *ret;
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
- ret = ops->alloc_coherent(dev, size, dma_handle, flag);
+ ret = ops->alloc(dev, size, dma_handle, flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
return ret;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
- dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
}
diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c
index e711ace..0f2367c 100644
--- a/arch/hexagon/kernel/dma.c
+++ b/arch/hexagon/kernel/dma.c
@@ -22,6 +22,7 @@
#include <linux/bootmem.h>
#include <linux/genalloc.h>
#include <asm/dma-mapping.h>
+#include <linux/module.h>
struct dma_map_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
@@ -54,7 +55,8 @@
/* Allocates from a pool of uncached memory that was reserved at boot time */
void *hexagon_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag)
+ dma_addr_t *dma_addr, gfp_t flag,
+ struct dma_attrs *attrs)
{
void *ret;
@@ -81,7 +83,7 @@
}
static void hexagon_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr)
+ dma_addr_t dma_addr, struct dma_attrs *attrs)
{
gen_pool_free(coherent_pool, (unsigned long) vaddr, size);
}
@@ -202,8 +204,8 @@
}
struct dma_map_ops hexagon_dma_ops = {
- .alloc_coherent = hexagon_dma_alloc_coherent,
- .free_coherent = hexagon_free_coherent,
+ .alloc = hexagon_dma_alloc_coherent,
+ .free = hexagon_free_coherent,
.map_sg = hexagon_map_sg,
.map_page = hexagon_map_page,
.sync_single_for_cpu = hexagon_sync_single_for_cpu,
diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c
index 18c4f0b..ff02821 100644
--- a/arch/hexagon/kernel/process.c
+++ b/arch/hexagon/kernel/process.c
@@ -1,7 +1,7 @@
/*
* Process creation support for Hexagon
*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -88,7 +88,7 @@
void cpu_idle(void)
{
while (1) {
- tick_nohz_stop_sched_tick(1);
+ tick_nohz_idle_enter();
local_irq_disable();
while (!need_resched()) {
idle_sleep();
@@ -97,7 +97,7 @@
local_irq_disable();
}
local_irq_enable();
- tick_nohz_restart_sched_tick();
+ tick_nohz_idle_exit();
schedule();
}
}
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index 32342de..96c3b2c 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -28,6 +28,7 @@
#include <linux/ptrace.h>
#include <linux/regset.h>
#include <linux/user.h>
+#include <linux/elf.h>
#include <asm/user.h>
diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c
index 15d1fd2..1298141 100644
--- a/arch/hexagon/kernel/smp.c
+++ b/arch/hexagon/kernel/smp.c
@@ -1,7 +1,7 @@
/*
* SMP support for Hexagon
*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -28,6 +28,7 @@
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
+#include <linux/cpu.h>
#include <asm/time.h> /* timer_interrupt */
#include <asm/hexagon_vm.h>
@@ -35,7 +36,7 @@
#define BASE_IPI_IRQ 26
/*
- * cpu_possible_map needs to be filled out prior to setup_per_cpu_areas
+ * cpu_possible_mask needs to be filled out prior to setup_per_cpu_areas
* (which is prior to any of our smp_prepare_cpu crap), in order to set
* up the... per_cpu areas.
*/
@@ -177,7 +178,12 @@
printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu);
+ notify_cpu_starting(cpu);
+
+ ipi_call_lock();
set_cpu_online(cpu, true);
+ ipi_call_unlock();
+
local_irq_enable();
cpu_idle();
@@ -208,7 +214,7 @@
stack_start = ((void *) thread) + THREAD_SIZE;
__vmstart(start_secondary, stack_start);
- while (!cpu_isset(cpu, cpu_online_map))
+ while (!cpu_online(cpu))
barrier();
return 0;
@@ -229,7 +235,7 @@
/* Right now, let's just fake it. */
for (i = 0; i < max_cpus; i++)
- cpu_set(i, cpu_present_map);
+ set_cpu_present(i, true);
/* Also need to register the interrupts for IPI */
if (max_cpus > 1)
@@ -269,5 +275,5 @@
int i;
for (i = 0; i < NR_CPUS; i++)
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
}
diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c
index 6bee15c..5d9b33b 100644
--- a/arch/hexagon/kernel/time.c
+++ b/arch/hexagon/kernel/time.c
@@ -28,6 +28,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <linux/module.h>
#include <asm/timer-regs.h>
#include <asm/hexagon_vm.h>
diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c
index f212a45..5d39f42 100644
--- a/arch/hexagon/kernel/vdso.c
+++ b/arch/hexagon/kernel/vdso.c
@@ -21,6 +21,7 @@
#include <linux/err.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
+#include <linux/binfmts.h>
#include <asm/vdso.h>
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index f6ea3a3..bcda5b2 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -1129,7 +1129,8 @@
* See Documentation/DMA-API-HOWTO.txt
*/
static void *
-sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flags)
+sba_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t flags, struct dma_attrs *attrs)
{
struct ioc *ioc;
void *addr;
@@ -1191,8 +1192,8 @@
*
* See Documentation/DMA-API-HOWTO.txt
*/
-static void sba_free_coherent (struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+static void sba_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL);
free_pages((unsigned long) vaddr, get_order(size));
@@ -2212,8 +2213,8 @@
__setup("sbapagesize=",sba_page_override);
struct dma_map_ops sba_dma_ops = {
- .alloc_coherent = sba_alloc_coherent,
- .free_coherent = sba_free_coherent,
+ .alloc = sba_alloc_coherent,
+ .free = sba_free_coherent,
.map_page = sba_map_page,
.unmap_page = sba_unmap_page,
.map_sg = sba_map_sg_attrs,
diff --git a/arch/ia64/include/asm/cmpxchg.h b/arch/ia64/include/asm/cmpxchg.h
index 4c96187..4f37dbb 100644
--- a/arch/ia64/include/asm/cmpxchg.h
+++ b/arch/ia64/include/asm/cmpxchg.h
@@ -1 +1,147 @@
-#include <asm/intrinsics.h>
+#ifndef _ASM_IA64_CMPXCHG_H
+#define _ASM_IA64_CMPXCHG_H
+
+/*
+ * Compare/Exchange, forked from asm/intrinsics.h
+ * which was:
+ *
+ * Copyright (C) 2002-2003 Hewlett-Packard Co
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+/* include compiler specific intrinsics */
+#include <asm/ia64regs.h>
+#ifdef __INTEL_COMPILER
+# include <asm/intel_intrin.h>
+#else
+# include <asm/gcc_intrin.h>
+#endif
+
+/*
+ * This function doesn't exist, so you'll get a linker error if
+ * something tries to do an invalid xchg().
+ */
+extern void ia64_xchg_called_with_bad_pointer(void);
+
+#define __xchg(x, ptr, size) \
+({ \
+ unsigned long __xchg_result; \
+ \
+ switch (size) { \
+ case 1: \
+ __xchg_result = ia64_xchg1((__u8 *)ptr, x); \
+ break; \
+ \
+ case 2: \
+ __xchg_result = ia64_xchg2((__u16 *)ptr, x); \
+ break; \
+ \
+ case 4: \
+ __xchg_result = ia64_xchg4((__u32 *)ptr, x); \
+ break; \
+ \
+ case 8: \
+ __xchg_result = ia64_xchg8((__u64 *)ptr, x); \
+ break; \
+ default: \
+ ia64_xchg_called_with_bad_pointer(); \
+ } \
+ __xchg_result; \
+})
+
+#define xchg(ptr, x) \
+((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
+
+/*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+/*
+ * This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg().
+ */
+extern long ia64_cmpxchg_called_with_bad_pointer(void);
+
+#define ia64_cmpxchg(sem, ptr, old, new, size) \
+({ \
+ __u64 _o_, _r_; \
+ \
+ switch (size) { \
+ case 1: \
+ _o_ = (__u8) (long) (old); \
+ break; \
+ case 2: \
+ _o_ = (__u16) (long) (old); \
+ break; \
+ case 4: \
+ _o_ = (__u32) (long) (old); \
+ break; \
+ case 8: \
+ _o_ = (__u64) (long) (old); \
+ break; \
+ default: \
+ break; \
+ } \
+ switch (size) { \
+ case 1: \
+ _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_); \
+ break; \
+ \
+ case 2: \
+ _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_); \
+ break; \
+ \
+ case 4: \
+ _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_); \
+ break; \
+ \
+ case 8: \
+ _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_); \
+ break; \
+ \
+ default: \
+ _r_ = ia64_cmpxchg_called_with_bad_pointer(); \
+ break; \
+ } \
+ (__typeof__(old)) _r_; \
+})
+
+#define cmpxchg_acq(ptr, o, n) \
+ ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr)))
+#define cmpxchg_rel(ptr, o, n) \
+ ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr)))
+
+/* for compatibility with other platforms: */
+#define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
+#define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
+
+#define cmpxchg_local cmpxchg
+#define cmpxchg64_local cmpxchg64
+
+#ifdef CONFIG_IA64_DEBUG_CMPXCHG
+# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128;
+# define CMPXCHG_BUGCHECK(v) \
+do { \
+ if (_cmpxchg_bugcheck_count-- <= 0) { \
+ void *ip; \
+ extern int printk(const char *fmt, ...); \
+ ip = (void *) ia64_getreg(_IA64_REG_IP); \
+ printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v));\
+ break; \
+ } \
+} while (0)
+#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
+# define CMPXCHG_BUGCHECK_DECL
+# define CMPXCHG_BUGCHECK(v)
+#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_IA64_CMPXCHG_H */
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index 4336d08..4f5e814 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -23,23 +23,29 @@
extern void machvec_dma_sync_sg(struct device *, struct scatterlist *, int,
enum dma_data_direction);
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *daddr, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *daddr, gfp_t gfp,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = platform_dma_get_ops(dev);
void *caddr;
- caddr = ops->alloc_coherent(dev, size, daddr, gfp);
+ caddr = ops->alloc(dev, size, daddr, gfp, attrs);
debug_dma_alloc_coherent(dev, size, *daddr, caddr);
return caddr;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *caddr, dma_addr_t daddr)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *caddr, dma_addr_t daddr,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = platform_dma_get_ops(dev);
debug_dma_free_coherent(dev, size, caddr, daddr);
- ops->free_coherent(dev, size, caddr, daddr);
+ ops->free(dev, size, caddr, daddr, attrs);
}
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index 0ab82cc..d2bf1fd 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -106,15 +106,16 @@
return -EFAULT;
{
- register unsigned long r8 __asm ("r8") = 0;
+ register unsigned long r8 __asm ("r8");
unsigned long prev;
__asm__ __volatile__(
" mf;; \n"
- " mov ar.ccv=%3;; \n"
- "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n"
+ " mov %0=r0 \n"
+ " mov ar.ccv=%4;; \n"
+ "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n"
" .xdata4 \"__ex_table\", 1b-., 2f-. \n"
"[2:]"
- : "=r" (prev)
+ : "=r" (r8), "=r" (prev)
: "r" (uaddr), "r" (newval),
"rO" ((long) (unsigned) oldval)
: "memory");
diff --git a/arch/ia64/include/asm/intrinsics.h b/arch/ia64/include/asm/intrinsics.h
index e4076b5..d129e36 100644
--- a/arch/ia64/include/asm/intrinsics.h
+++ b/arch/ia64/include/asm/intrinsics.h
@@ -18,6 +18,7 @@
#else
# include <asm/gcc_intrin.h>
#endif
+#include <asm/cmpxchg.h>
#define ia64_native_get_psr_i() (ia64_native_getreg(_IA64_REG_PSR) & IA64_PSR_I)
@@ -81,119 +82,6 @@
#define ia64_fetch_and_add(i,v) (ia64_fetchadd(i, v, rel) + (i)) /* return new value */
-/*
- * This function doesn't exist, so you'll get a linker error if
- * something tries to do an invalid xchg().
- */
-extern void ia64_xchg_called_with_bad_pointer (void);
-
-#define __xchg(x,ptr,size) \
-({ \
- unsigned long __xchg_result; \
- \
- switch (size) { \
- case 1: \
- __xchg_result = ia64_xchg1((__u8 *)ptr, x); \
- break; \
- \
- case 2: \
- __xchg_result = ia64_xchg2((__u16 *)ptr, x); \
- break; \
- \
- case 4: \
- __xchg_result = ia64_xchg4((__u32 *)ptr, x); \
- break; \
- \
- case 8: \
- __xchg_result = ia64_xchg8((__u64 *)ptr, x); \
- break; \
- default: \
- ia64_xchg_called_with_bad_pointer(); \
- } \
- __xchg_result; \
-})
-
-#define xchg(ptr,x) \
- ((__typeof__(*(ptr))) __xchg ((unsigned long) (x), (ptr), sizeof(*(ptr))))
-
-/*
- * Atomic compare and exchange. Compare OLD with MEM, if identical,
- * store NEW in MEM. Return the initial value in MEM. Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-/*
- * This function doesn't exist, so you'll get a linker error
- * if something tries to do an invalid cmpxchg().
- */
-extern long ia64_cmpxchg_called_with_bad_pointer (void);
-
-#define ia64_cmpxchg(sem,ptr,old,new,size) \
-({ \
- __u64 _o_, _r_; \
- \
- switch (size) { \
- case 1: _o_ = (__u8 ) (long) (old); break; \
- case 2: _o_ = (__u16) (long) (old); break; \
- case 4: _o_ = (__u32) (long) (old); break; \
- case 8: _o_ = (__u64) (long) (old); break; \
- default: break; \
- } \
- switch (size) { \
- case 1: \
- _r_ = ia64_cmpxchg1_##sem((__u8 *) ptr, new, _o_); \
- break; \
- \
- case 2: \
- _r_ = ia64_cmpxchg2_##sem((__u16 *) ptr, new, _o_); \
- break; \
- \
- case 4: \
- _r_ = ia64_cmpxchg4_##sem((__u32 *) ptr, new, _o_); \
- break; \
- \
- case 8: \
- _r_ = ia64_cmpxchg8_##sem((__u64 *) ptr, new, _o_); \
- break; \
- \
- default: \
- _r_ = ia64_cmpxchg_called_with_bad_pointer(); \
- break; \
- } \
- (__typeof__(old)) _r_; \
-})
-
-#define cmpxchg_acq(ptr, o, n) \
- ia64_cmpxchg(acq, (ptr), (o), (n), sizeof(*(ptr)))
-#define cmpxchg_rel(ptr, o, n) \
- ia64_cmpxchg(rel, (ptr), (o), (n), sizeof(*(ptr)))
-
-/* for compatibility with other platforms: */
-#define cmpxchg(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-#define cmpxchg64(ptr, o, n) cmpxchg_acq((ptr), (o), (n))
-
-#define cmpxchg_local cmpxchg
-#define cmpxchg64_local cmpxchg64
-
-#ifdef CONFIG_IA64_DEBUG_CMPXCHG
-# define CMPXCHG_BUGCHECK_DECL int _cmpxchg_bugcheck_count = 128;
-# define CMPXCHG_BUGCHECK(v) \
- do { \
- if (_cmpxchg_bugcheck_count-- <= 0) { \
- void *ip; \
- extern int printk(const char *fmt, ...); \
- ip = (void *) ia64_getreg(_IA64_REG_IP); \
- printk("CMPXCHG_BUGCHECK: stuck at %p on word %p\n", ip, (v)); \
- break; \
- } \
- } while (0)
-#else /* !CONFIG_IA64_DEBUG_CMPXCHG */
-# define CMPXCHG_BUGCHECK_DECL
-# define CMPXCHG_BUGCHECK(v)
-#endif /* !CONFIG_IA64_DEBUG_CMPXCHG */
-
#endif
#ifdef __KERNEL__
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index ac795d3..6f38b61 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -839,7 +839,7 @@
early_param("additional_cpus", setup_additional_cpus);
/*
- * cpu_possible_map should be static, it cannot change as CPUs
+ * cpu_possible_mask should be static, it cannot change as CPUs
* are onlined, or offlined. The reason is per-cpu data-structures
* are allocated by some modules at init time, and dont expect to
* do this dynamically on cpu arrival/departure.
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index d9485d9..939260a 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -15,16 +15,24 @@
EXPORT_SYMBOL(swiotlb);
static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
gfp |= GFP_DMA;
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
}
+static void ia64_swiotlb_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
+{
+ swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
struct dma_map_ops swiotlb_dma_ops = {
- .alloc_coherent = ia64_swiotlb_alloc_coherent,
- .free_coherent = swiotlb_free_coherent,
+ .alloc = ia64_swiotlb_alloc_coherent,
+ .free = ia64_swiotlb_free_coherent,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = swiotlb_map_sg_attrs,
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 9d0fd7d..f00ba02 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -604,12 +604,6 @@
spin_unlock(&(x)->ctx_lock);
}
-static inline unsigned int
-pfm_do_munmap(struct mm_struct *mm, unsigned long addr, size_t len, int acct)
-{
- return do_munmap(mm, addr, len);
-}
-
static inline unsigned long
pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec)
{
@@ -1458,8 +1452,9 @@
* a PROTECT_CTX() section.
*/
static int
-pfm_remove_smpl_mapping(struct task_struct *task, void *vaddr, unsigned long size)
+pfm_remove_smpl_mapping(void *vaddr, unsigned long size)
{
+ struct task_struct *task = current;
int r;
/* sanity checks */
@@ -1473,13 +1468,8 @@
/*
* does the actual unmapping
*/
- down_write(&task->mm->mmap_sem);
+ r = vm_munmap((unsigned long)vaddr, size);
- DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size));
-
- r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0);
-
- up_write(&task->mm->mmap_sem);
if (r !=0) {
printk(KERN_ERR "perfmon: [%d] unable to unmap sampling buffer @%p size=%lu\n", task_pid_nr(task), vaddr, size);
}
@@ -1945,7 +1935,7 @@
* because some VM function reenables interrupts.
*
*/
- if (smpl_buf_vaddr) pfm_remove_smpl_mapping(current, smpl_buf_vaddr, smpl_buf_size);
+ if (smpl_buf_vaddr) pfm_remove_smpl_mapping(smpl_buf_vaddr, smpl_buf_size);
return 0;
}
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index f5104b7..463fb3b 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1174,7 +1174,7 @@
bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
{
- return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
+ return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
}
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c
index a9d310d..3290d6e 100644
--- a/arch/ia64/sn/pci/pci_dma.c
+++ b/arch/ia64/sn/pci/pci_dma.c
@@ -76,7 +76,8 @@
* more information.
*/
static void *sn_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t flags)
+ dma_addr_t * dma_handle, gfp_t flags,
+ struct dma_attrs *attrs)
{
void *cpuaddr;
unsigned long phys_addr;
@@ -137,7 +138,7 @@
* any associated IOMMU mappings.
*/
static void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
- dma_addr_t dma_handle)
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
@@ -466,8 +467,8 @@
}
static struct dma_map_ops sn_dma_ops = {
- .alloc_coherent = sn_dma_alloc_coherent,
- .free_coherent = sn_dma_free_coherent,
+ .alloc = sn_dma_alloc_coherent,
+ .free = sn_dma_free_coherent,
.map_page = sn_dma_map_page,
.unmap_page = sn_dma_unmap_page,
.map_sg = sn_dma_map_sg,
diff --git a/arch/m68k/configs/m5275evb_defconfig b/arch/m68k/configs/m5275evb_defconfig
index 33c32ae..a1230e8 100644
--- a/arch/m68k/configs/m5275evb_defconfig
+++ b/arch/m68k/configs/m5275evb_defconfig
@@ -49,7 +49,6 @@
CONFIG_NETDEVICES=y
CONFIG_NET_ETHERNET=y
CONFIG_FEC=y
-CONFIG_FEC2=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_PPP=y
diff --git a/arch/m68k/include/asm/atomic.h b/arch/m68k/include/asm/atomic.h
index 336e617..f4e32de 100644
--- a/arch/m68k/include/asm/atomic.h
+++ b/arch/m68k/include/asm/atomic.h
@@ -3,6 +3,7 @@
#include <linux/types.h>
#include <linux/irqflags.h>
+#include <asm/cmpxchg.h>
/*
* Atomic operations that C can't guarantee us. Useful for
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 96fa6ed..d9f62e0 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -980,6 +980,9 @@
{
u8 *swim_base;
+ if (!MACH_IS_MAC)
+ return -ENODEV;
+
/*
* Serial devices
*/
diff --git a/arch/m68k/platform/527x/config.c b/arch/m68k/platform/527x/config.c
index 7ed848c..f91a532 100644
--- a/arch/m68k/platform/527x/config.c
+++ b/arch/m68k/platform/527x/config.c
@@ -74,9 +74,7 @@
writew(par | 0xf00, MCF_IPSBAR + 0x100082);
v = readb(MCF_IPSBAR + 0x100078);
writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
-#endif
-#ifdef CONFIG_FEC2
/* Set multi-function pins to ethernet mode for fec1 */
par = readw(MCF_IPSBAR + 0x100082);
writew(par | 0xa0, MCF_IPSBAR + 0x100082);
diff --git a/arch/m68k/platform/68EZ328/Makefile b/arch/m68k/platform/68EZ328/Makefile
index ee97735..b44d799 100644
--- a/arch/m68k/platform/68EZ328/Makefile
+++ b/arch/m68k/platform/68EZ328/Makefile
@@ -3,9 +3,3 @@
#
obj-y := config.o
-
-extra-y := bootlogo.rh
-
-$(obj)/bootlogo.rh: $(src)/bootlogo.h
- perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
- > $(obj)/bootlogo.rh
diff --git a/arch/m68k/platform/68VZ328/Makefile b/arch/m68k/platform/68VZ328/Makefile
index 447ffa0f..a49d75e 100644
--- a/arch/m68k/platform/68VZ328/Makefile
+++ b/arch/m68k/platform/68VZ328/Makefile
@@ -3,14 +3,9 @@
#
obj-y := config.o
-logo-$(UCDIMM) := bootlogo.rh
-logo-$(DRAGEN2) := screen.h
-extra-y := $(logo-y)
-
-$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
- perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh
+extra-$(DRAGEN2):= screen.h
$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
-clean-files := $(obj)/screen.h $(obj)/bootlogo.rh
+clean-files := $(obj)/screen.h
diff --git a/arch/m68k/platform/68EZ328/bootlogo.h b/arch/m68k/platform/68VZ328/bootlogo.h
similarity index 99%
rename from arch/m68k/platform/68EZ328/bootlogo.h
rename to arch/m68k/platform/68VZ328/bootlogo.h
index e842bda..b38e2b2 100644
--- a/arch/m68k/platform/68EZ328/bootlogo.h
+++ b/arch/m68k/platform/68VZ328/bootlogo.h
@@ -1,6 +1,6 @@
#define splash_width 640
#define splash_height 480
-static unsigned char splash_bits[] = {
+unsigned char __attribute__ ((aligned(16))) bootlogo_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/arch/m68k/platform/coldfire/device.c b/arch/m68k/platform/coldfire/device.c
index fa50c48..7af9736 100644
--- a/arch/m68k/platform/coldfire/device.c
+++ b/arch/m68k/platform/coldfire/device.c
@@ -114,7 +114,7 @@
static struct platform_device mcf_fec1 = {
.name = "fec",
- .id = 0,
+ .id = 1,
.num_resources = ARRAY_SIZE(mcf_fec1_resources),
.resource = mcf_fec1_resources,
};
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 512adb6..8a1ce32 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -334,6 +334,9 @@
{
struct platform_device *pdev;
+ if (!MACH_IS_Q40)
+ return -ENODEV;
+
pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
diff --git a/arch/microblaze/include/asm/cmpxchg.h b/arch/microblaze/include/asm/cmpxchg.h
index 0094859a..538afc0 100644
--- a/arch/microblaze/include/asm/cmpxchg.h
+++ b/arch/microblaze/include/asm/cmpxchg.h
@@ -1,6 +1,8 @@
#ifndef _ASM_MICROBLAZE_CMPXCHG_H
#define _ASM_MICROBLAZE_CMPXCHG_H
+#include <linux/irqflags.h>
+
void __bad_xchg(volatile void *ptr, int size);
static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
diff --git a/arch/microblaze/include/asm/dma-mapping.h b/arch/microblaze/include/asm/dma-mapping.h
index 3a3e5b8..01d2282 100644
--- a/arch/microblaze/include/asm/dma-mapping.h
+++ b/arch/microblaze/include/asm/dma-mapping.h
@@ -123,28 +123,34 @@
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
void *memory;
BUG_ON(!ops);
- memory = ops->alloc_coherent(dev, size, dma_handle, flag);
+ memory = ops->alloc(dev, size, dma_handle, flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
return memory;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d, s, c, h, NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
BUG_ON(!ops);
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
}
static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
diff --git a/arch/microblaze/include/asm/futex.h b/arch/microblaze/include/asm/futex.h
index b0526d2..ff8cde1 100644
--- a/arch/microblaze/include/asm/futex.h
+++ b/arch/microblaze/include/asm/futex.h
@@ -24,7 +24,7 @@
.word 1b,4b,2b,4b; \
.previous;" \
: "=&r" (oldval), "=&r" (ret) \
- : "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
+ : "r" (uaddr), "i" (-EFAULT), "r" (oparg) \
); \
})
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h
index 510a8e1..bffb545 100644
--- a/arch/microblaze/include/asm/processor.h
+++ b/arch/microblaze/include/asm/processor.h
@@ -31,6 +31,8 @@
/* Do necessary setup to start up a newly executed thread. */
void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp);
+extern void ret_from_fork(void);
+
# endif /* __ASSEMBLY__ */
# ifndef CONFIG_MMU
@@ -143,8 +145,6 @@
unsigned long get_wchan(struct task_struct *p);
-extern void ret_from_fork(void);
-
/* The size allocated for kernel stacks. This _must_ be a power of two! */
# define KERNEL_STACK_SIZE 0x2000
diff --git a/arch/microblaze/kernel/dma.c b/arch/microblaze/kernel/dma.c
index 65a4af4..a2bfa2c 100644
--- a/arch/microblaze/kernel/dma.c
+++ b/arch/microblaze/kernel/dma.c
@@ -33,7 +33,8 @@
#define NOT_COHERENT_CACHE
static void *dma_direct_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
#ifdef NOT_COHERENT_CACHE
return consistent_alloc(flag, size, dma_handle);
@@ -57,7 +58,8 @@
}
static void dma_direct_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
#ifdef NOT_COHERENT_CACHE
consistent_free(size, vaddr);
@@ -176,8 +178,8 @@
}
struct dma_map_ops dma_direct_ops = {
- .alloc_coherent = dma_direct_alloc_coherent,
- .free_coherent = dma_direct_free_coherent,
+ .alloc = dma_direct_alloc_coherent,
+ .free = dma_direct_free_coherent,
.map_sg = dma_direct_map_sg,
.unmap_sg = dma_direct_unmap_sg,
.dma_supported = dma_direct_dma_supported,
diff --git a/arch/microblaze/kernel/early_printk.c b/arch/microblaze/kernel/early_printk.c
index ec48587..aba1f9a9 100644
--- a/arch/microblaze/kernel/early_printk.c
+++ b/arch/microblaze/kernel/early_printk.c
@@ -176,6 +176,7 @@
base_addr = (u32) ioremap(base_addr, PAGE_SIZE);
printk(KERN_CONT "0x%x\n", base_addr);
+#ifdef CONFIG_MMU
/*
* Early console is on the top of skipped TLB entries
* decrease tlb_skip size ensure that hardcoded TLB entry will be
@@ -189,6 +190,7 @@
* cmp rX, orig_base_addr
*/
tlb_skip -= 1;
+#endif
}
void __init disable_early_printk(void)
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index 71af974..16d8dfd 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -206,6 +206,7 @@
}
arch_initcall(microblaze_debugfs_init);
+# ifdef CONFIG_MMU
static int __init debugfs_tlb(void)
{
struct dentry *d;
@@ -218,6 +219,7 @@
return -ENOMEM;
}
device_initcall(debugfs_tlb);
+# endif
#endif
static int dflt_bus_notify(struct notifier_block *nb,
diff --git a/arch/microblaze/kernel/unwind.c b/arch/microblaze/kernel/unwind.c
index 9781a52..6be4ae3 100644
--- a/arch/microblaze/kernel/unwind.c
+++ b/arch/microblaze/kernel/unwind.c
@@ -24,6 +24,7 @@
#include <asm/sections.h>
#include <asm/exceptions.h>
#include <asm/unwind.h>
+#include <asm/switch_to.h>
struct stack_trace;
diff --git a/arch/microblaze/lib/uaccess_old.S b/arch/microblaze/lib/uaccess_old.S
index f037266..f085995 100644
--- a/arch/microblaze/lib/uaccess_old.S
+++ b/arch/microblaze/lib/uaccess_old.S
@@ -122,22 +122,22 @@
15: swi r24, r5, 0x0018 + offset; \
16: swi r25, r5, 0x001C + offset; \
.section __ex_table,"a"; \
- .word 1b, 0f; \
- .word 2b, 0f; \
- .word 3b, 0f; \
- .word 4b, 0f; \
- .word 5b, 0f; \
- .word 6b, 0f; \
- .word 7b, 0f; \
- .word 8b, 0f; \
- .word 9b, 0f; \
- .word 10b, 0f; \
- .word 11b, 0f; \
- .word 12b, 0f; \
- .word 13b, 0f; \
- .word 14b, 0f; \
- .word 15b, 0f; \
- .word 16b, 0f; \
+ .word 1b, 33f; \
+ .word 2b, 33f; \
+ .word 3b, 33f; \
+ .word 4b, 33f; \
+ .word 5b, 33f; \
+ .word 6b, 33f; \
+ .word 7b, 33f; \
+ .word 8b, 33f; \
+ .word 9b, 33f; \
+ .word 10b, 33f; \
+ .word 11b, 33f; \
+ .word 12b, 33f; \
+ .word 13b, 33f; \
+ .word 14b, 33f; \
+ .word 15b, 33f; \
+ .word 16b, 33f; \
.text
#define COPY_80(offset) \
@@ -190,14 +190,17 @@
.align 4 /* Alignment is important to keep icache happy */
page: /* Create room on stack and save registers for storign values */
- addik r1, r1, -32
- swi r19, r1, 4
- swi r20, r1, 8
- swi r21, r1, 12
- swi r22, r1, 16
- swi r23, r1, 20
- swi r24, r1, 24
- swi r25, r1, 28
+ addik r1, r1, -40
+ swi r5, r1, 0
+ swi r6, r1, 4
+ swi r7, r1, 8
+ swi r19, r1, 12
+ swi r20, r1, 16
+ swi r21, r1, 20
+ swi r22, r1, 24
+ swi r23, r1, 28
+ swi r24, r1, 32
+ swi r25, r1, 36
loop: /* r4, r19, r20, r21, r22, r23, r24, r25 are used for storing values */
/* Loop unrolling to get performance boost */
COPY_80(0x000);
@@ -205,21 +208,44 @@
COPY_80(0x100);
COPY_80(0x180);
/* copy loop */
- addik r6, r6, 0x200
- addik r7, r7, -0x200
- bneid r7, loop
- addik r5, r5, 0x200
+ addik r6, r6, 0x200
+ addik r7, r7, -0x200
+ bneid r7, loop
+ addik r5, r5, 0x200
+
/* Restore register content */
- lwi r19, r1, 4
- lwi r20, r1, 8
- lwi r21, r1, 12
- lwi r22, r1, 16
- lwi r23, r1, 20
- lwi r24, r1, 24
- lwi r25, r1, 28
- addik r1, r1, 32
+ lwi r5, r1, 0
+ lwi r6, r1, 4
+ lwi r7, r1, 8
+ lwi r19, r1, 12
+ lwi r20, r1, 16
+ lwi r21, r1, 20
+ lwi r22, r1, 24
+ lwi r23, r1, 28
+ lwi r24, r1, 32
+ lwi r25, r1, 36
+ addik r1, r1, 40
/* return back */
+ addik r3, r0, 0
+ rtsd r15, 8
+ nop
+
+/* Fault case - return temp count */
+33:
addik r3, r7, 0
+ /* Restore register content */
+ lwi r5, r1, 0
+ lwi r6, r1, 4
+ lwi r7, r1, 8
+ lwi r19, r1, 12
+ lwi r20, r1, 16
+ lwi r21, r1, 20
+ lwi r22, r1, 24
+ lwi r23, r1, 28
+ lwi r24, r1, 32
+ lwi r25, r1, 36
+ addik r1, r1, 40
+ /* return back */
rtsd r15, 8
nop
diff --git a/arch/mips/ath79/dev-wmac.c b/arch/mips/ath79/dev-wmac.c
index e215070..9c717bf 100644
--- a/arch/mips/ath79/dev-wmac.c
+++ b/arch/mips/ath79/dev-wmac.c
@@ -58,8 +58,8 @@
static int ar933x_wmac_reset(void)
{
- ath79_device_reset_clear(AR933X_RESET_WMAC);
ath79_device_reset_set(AR933X_RESET_WMAC);
+ ath79_device_reset_clear(AR933X_RESET_WMAC);
return 0;
}
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
index b6bb92c..41dd0088 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -157,7 +157,7 @@
}
static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
void *ret;
@@ -192,7 +192,7 @@
}
static void octeon_dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs)
{
int order = get_order(size);
@@ -240,8 +240,8 @@
static struct octeon_dma_map_ops octeon_linear_dma_map_ops = {
.dma_map_ops = {
- .alloc_coherent = octeon_dma_alloc_coherent,
- .free_coherent = octeon_dma_free_coherent,
+ .alloc = octeon_dma_alloc_coherent,
+ .free = octeon_dma_free_coherent,
.map_page = octeon_dma_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = octeon_dma_map_sg,
@@ -325,8 +325,8 @@
#ifdef CONFIG_PCI
static struct octeon_dma_map_ops _octeon_pci_dma_map_ops = {
.dma_map_ops = {
- .alloc_coherent = octeon_dma_alloc_coherent,
- .free_coherent = octeon_dma_free_coherent,
+ .alloc = octeon_dma_alloc_coherent,
+ .free = octeon_dma_free_coherent,
.map_page = octeon_dma_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = octeon_dma_map_sg,
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index c3e2b85..97e7ce9 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -78,7 +78,7 @@
}
/**
- * Detect available CPUs, populate cpu_possible_map
+ * Detect available CPUs, populate cpu_possible_mask
*/
static void octeon_smp_hotplug_setup(void)
{
@@ -268,7 +268,7 @@
spin_lock(&smp_reserve_lock);
- cpu_clear(cpu, cpu_online_map);
+ set_cpu_online(cpu, false);
cpu_clear(cpu, cpu_callin_map);
local_irq_disable();
fixup_irqs();
diff --git a/arch/mips/include/asm/dma-mapping.h b/arch/mips/include/asm/dma-mapping.h
index 7aa37dd..be39a12 100644
--- a/arch/mips/include/asm/dma-mapping.h
+++ b/arch/mips/include/asm/dma-mapping.h
@@ -57,25 +57,31 @@
extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction);
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
void *ret;
struct dma_map_ops *ops = get_dma_ops(dev);
- ret = ops->alloc_coherent(dev, size, dma_handle, gfp);
+ ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
return ret;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
- ops->free_coherent(dev, size, vaddr, dma_handle);
+ ops->free(dev, size, vaddr, dma_handle, attrs);
debug_dma_free_coherent(dev, size, vaddr, dma_handle);
}
diff --git a/arch/mips/include/asm/mach-jz4740/irq.h b/arch/mips/include/asm/mach-jz4740/irq.h
index a865c98..5ad1a9c 100644
--- a/arch/mips/include/asm/mach-jz4740/irq.h
+++ b/arch/mips/include/asm/mach-jz4740/irq.h
@@ -45,7 +45,7 @@
#define JZ4740_IRQ_LCD JZ4740_IRQ(30)
/* 2nd-level interrupts */
-#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (X))
+#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (x))
#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x))
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index 73c0d45..9b02cfb 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -37,12 +37,6 @@
write_c0_xcontext((unsigned long) smp_processor_id() << 51); \
} while (0)
-
-static inline unsigned long get_current_pgd(void)
-{
- return PHYS_TO_XKSEG_CACHED((read_c0_context() >> 11) & ~0xfffUL);
-}
-
#else /* CONFIG_MIPS_PGD_C0_CONTEXT: using pgd_current*/
/*
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 802e616..33f63ba 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -173,7 +173,7 @@
if (retval)
goto out_unlock;
- cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+ cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask);
out_unlock:
read_unlock(&tasklist_lock);
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index e309665..f8b2c59 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -25,7 +25,7 @@
int i;
#ifdef CONFIG_SMP
- if (!cpu_isset(n, cpu_online_map))
+ if (!cpu_online(n))
return 0;
#endif
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 185ca00..d5a338a 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -257,11 +257,8 @@
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&newset);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -286,11 +283,8 @@
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&newset);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -362,10 +356,7 @@
goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = blocked;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&blocked);
sig = restore_sigcontext(®s, &frame->sf_sc);
if (sig < 0)
@@ -401,10 +392,7 @@
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext);
if (sig < 0)
@@ -580,12 +568,7 @@
if (ret)
return ret;
- spin_lock_irq(¤t->sighand->siglock);
- sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(¤t->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ block_sigmask(ka, sig);
return ret;
}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 06b5da3..ac3b8d8 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -290,11 +290,8 @@
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&newset);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -318,11 +315,8 @@
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&newset);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -488,10 +482,7 @@
goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = blocked;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&blocked);
sig = restore_sigcontext32(®s, &frame->sf_sc);
if (sig < 0)
@@ -529,10 +520,7 @@
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext);
if (sig < 0)
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index ae29e89..86eb4b0 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -93,11 +93,8 @@
sigset_from_compat(&newset, &uset);
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&newset);
current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -121,10 +118,7 @@
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(¤t->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
+ set_current_blocked(&set);
sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext);
if (sig < 0)
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index ca67356..3046e29 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -317,7 +317,7 @@
pr_info("SMP: CPU%d is offline\n", cpu);
- cpu_clear(cpu, cpu_online_map);
+ set_cpu_online(cpu, false);
cpu_clear(cpu, cpu_callin_map);
local_flush_tlb_all();
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 9c1cce9..ba9376bf 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -148,7 +148,7 @@
/*
* Remove this CPU:
*/
- cpu_clear(smp_processor_id(), cpu_online_map);
+ set_cpu_online(smp_processor_id(), false);
for (;;) {
if (cpu_wait)
(*cpu_wait)(); /* Wait if available. */
@@ -174,7 +174,7 @@
mp_ops->prepare_cpus(max_cpus);
set_cpu_sibling_map(0);
#ifndef CONFIG_HOTPLUG_CPU
- init_cpu_present(&cpu_possible_map);
+ init_cpu_present(cpu_possible_mask);
#endif
}
@@ -248,7 +248,7 @@
while (!cpu_isset(cpu, cpu_callin_map))
udelay(100);
- cpu_set(cpu, cpu_online_map);
+ set_cpu_online(cpu, true);
return 0;
}
@@ -320,13 +320,12 @@
if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
smp_on_other_tlbs(flush_tlb_mm_ipi, mm);
} else {
- cpumask_t mask = cpu_online_map;
unsigned int cpu;
- cpu_clear(smp_processor_id(), mask);
- for_each_cpu_mask(cpu, mask)
- if (cpu_context(cpu, mm))
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id() && cpu_context(cpu, mm))
cpu_context(cpu, mm) = 0;
+ }
}
local_flush_tlb_mm(mm);
@@ -360,13 +359,12 @@
smp_on_other_tlbs(flush_tlb_range_ipi, &fd);
} else {
- cpumask_t mask = cpu_online_map;
unsigned int cpu;
- cpu_clear(smp_processor_id(), mask);
- for_each_cpu_mask(cpu, mask)
- if (cpu_context(cpu, mm))
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id() && cpu_context(cpu, mm))
cpu_context(cpu, mm) = 0;
+ }
}
local_flush_tlb_range(vma, start, end);
preempt_enable();
@@ -407,13 +405,12 @@
smp_on_other_tlbs(flush_tlb_page_ipi, &fd);
} else {
- cpumask_t mask = cpu_online_map;
unsigned int cpu;
- cpu_clear(smp_processor_id(), mask);
- for_each_cpu_mask(cpu, mask)
- if (cpu_context(cpu, vma->vm_mm))
+ for_each_online_cpu(cpu) {
+ if (cpu != smp_processor_id() && cpu_context(cpu, vma->vm_mm))
cpu_context(cpu, vma->vm_mm) = 0;
+ }
}
local_flush_tlb_page(vma, page);
preempt_enable();
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index c4f75bb..f5dd38f 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -291,7 +291,7 @@
* possibly leave some TCs/VPEs as "slave" processors.
*
* Use c0_MVPConf0 to find out how many TCs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
*/
int __init smtc_build_cpu_map(int start_cpu_slot)
diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index 1f9ca07..47037ec 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -80,9 +80,9 @@
if (vma)
mask = *mm_cpumask(vma->vm_mm);
else
- mask = cpu_online_map;
- cpu_clear(cpu, mask);
- for_each_cpu_mask(cpu, mask)
+ mask = *cpu_online_mask;
+ cpumask_clear_cpu(cpu, &mask);
+ for_each_cpu(cpu, &mask)
octeon_send_ipi_single(cpu, SMP_ICACHE_FLUSH);
preempt_enable();
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
index 4608491..3fab204 100644
--- a/arch/mips/mm/dma-default.c
+++ b/arch/mips/mm/dma-default.c
@@ -98,7 +98,7 @@
EXPORT_SYMBOL(dma_alloc_noncoherent);
static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t * dma_handle, gfp_t gfp)
+ dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
void *ret;
@@ -132,7 +132,7 @@
EXPORT_SYMBOL(dma_free_noncoherent);
static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
unsigned long addr = (unsigned long) vaddr;
int order = get_order(size);
@@ -323,8 +323,8 @@
EXPORT_SYMBOL(dma_cache_sync);
static struct dma_map_ops mips_default_dma_map_ops = {
- .alloc_coherent = mips_dma_alloc_coherent,
- .free_coherent = mips_dma_free_coherent,
+ .alloc = mips_dma_alloc_coherent,
+ .free = mips_dma_free_coherent,
.map_page = mips_dma_map_page,
.unmap_page = mips_dma_unmap_page,
.map_sg = mips_dma_map_sg,
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index db17f49..fab316d 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -165,7 +165,7 @@
cpu_set(boot_cpu, phys_cpu_present_map);
__cpu_number_map[boot_cpu] = 0;
__cpu_logical_map[0] = boot_cpu;
- cpu_set(0, cpu_possible_map);
+ set_cpu_possible(0, true);
num_cpus = 1;
for (i = 0; i < NR_CPUS; i++) {
@@ -177,14 +177,14 @@
cpu_set(i, phys_cpu_present_map);
__cpu_number_map[i] = num_cpus;
__cpu_logical_map[num_cpus] = i;
- cpu_set(num_cpus, cpu_possible_map);
+ set_cpu_possible(num_cpus, true);
++num_cpus;
}
}
pr_info("Phys CPU present map: %lx, possible map %lx\n",
(unsigned long)phys_cpu_present_map.bits[0],
- (unsigned long)cpu_possible_map.bits[0]);
+ (unsigned long)cpumask_bits(cpu_possible_mask)[0]);
pr_info("Detected %i Slave CPU(s)\n", num_cpus);
nlm_set_nmi_handler(nlm_boot_secondary_cpus);
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c
index 2608752..b71fae2 100644
--- a/arch/mips/pmc-sierra/yosemite/smp.c
+++ b/arch/mips/pmc-sierra/yosemite/smp.c
@@ -146,7 +146,7 @@
}
/*
- * Detect available CPUs, populate cpu_possible_map before smp_init
+ * Detect available CPUs, populate cpu_possible_mask before smp_init
*
* We don't want to start the secondary CPU yet nor do we have a nice probing
* feature in PMON so we just assume presence of the secondary core.
@@ -155,10 +155,10 @@
{
int i;
- cpus_clear(cpu_possible_map);
+ init_cpu_possible(cpu_none_mask);
for (i = 0; i < 2; i++) {
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
__cpu_number_map[i] = i;
__cpu_logical_map[i] = i;
}
@@ -169,7 +169,7 @@
/*
* Be paranoid. Enable the IPI only if we're really about to go SMP.
*/
- if (cpus_weight(cpu_possible_map))
+ if (num_possible_cpus())
set_c0_status(STATUSF_IP5);
}
diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c
index c6851df..735b43b 100644
--- a/arch/mips/sgi-ip27/ip27-smp.c
+++ b/arch/mips/sgi-ip27/ip27-smp.c
@@ -76,7 +76,7 @@
/* Only let it join in if it's marked enabled */
if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
(tot_cpus_found != NR_CPUS)) {
- cpu_set(cpuid, cpu_possible_map);
+ set_cpu_possible(cpuid, true);
alloc_cpupda(cpuid, tot_cpus_found);
cpus_found++;
tot_cpus_found++;
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index d667875..de88e22 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -138,7 +138,7 @@
/*
* Use CFE to find out how many CPUs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
* XXXKW will the boot CPU ever not be physical 0?
*
* Common setup before any secondaries are started
@@ -147,14 +147,13 @@
{
int i, num;
- cpus_clear(cpu_possible_map);
- cpu_set(0, cpu_possible_map);
+ init_cpu_possible(cpumask_of(0));
__cpu_number_map[0] = 0;
__cpu_logical_map[0] = 0;
for (i = 1, num = 0; i < NR_CPUS; i++) {
if (cfe_cpu_stop(i) == 0) {
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index 38e7f6b..285cfef 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -126,7 +126,7 @@
/*
* Use CFE to find out how many CPUs are available, setting up
- * cpu_possible_map and the logical/physical mappings.
+ * cpu_possible_mask and the logical/physical mappings.
* XXXKW will the boot CPU ever not be physical 0?
*
* Common setup before any secondaries are started
@@ -135,14 +135,13 @@
{
int i, num;
- cpus_clear(cpu_possible_map);
- cpu_set(0, cpu_possible_map);
+ init_cpu_possible(cpumask_of(0));
__cpu_number_map[0] = 0;
__cpu_logical_map[0] = 0;
for (i = 1, num = 0; i < NR_CPUS; i++) {
if (cfe_cpu_stop(i) == 0) {
- cpu_set(i, cpu_possible_map);
+ set_cpu_possible(i, true);
__cpu_number_map[i] = ++num;
__cpu_logical_map[num] = i;
}
diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h
index 3ae5607..6c6defc 100644
--- a/arch/parisc/include/asm/atomic.h
+++ b/arch/parisc/include/asm/atomic.h
@@ -6,6 +6,7 @@
#define _ASM_PARISC_ATOMIC_H_
#include <linux/types.h>
+#include <asm/cmpxchg.h>
/*
* Atomic operations that C can't guarantee us. Useful for
@@ -48,112 +49,6 @@
# define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
#endif
-/* This should get optimized out since it's never called.
-** Or get a link error if xchg is used "wrong".
-*/
-extern void __xchg_called_with_bad_pointer(void);
-
-
-/* __xchg32/64 defined in arch/parisc/lib/bitops.c */
-extern unsigned long __xchg8(char, char *);
-extern unsigned long __xchg32(int, int *);
-#ifdef CONFIG_64BIT
-extern unsigned long __xchg64(unsigned long, unsigned long *);
-#endif
-
-/* optimizer better get rid of switch since size is a constant */
-static __inline__ unsigned long
-__xchg(unsigned long x, __volatile__ void * ptr, int size)
-{
- switch(size) {
-#ifdef CONFIG_64BIT
- case 8: return __xchg64(x,(unsigned long *) ptr);
-#endif
- case 4: return __xchg32((int) x, (int *) ptr);
- case 1: return __xchg8((char) x, (char *) ptr);
- }
- __xchg_called_with_bad_pointer();
- return x;
-}
-
-
-/*
-** REVISIT - Abandoned use of LDCW in xchg() for now:
-** o need to test sizeof(*ptr) to avoid clearing adjacent bytes
-** o and while we are at it, could CONFIG_64BIT code use LDCD too?
-**
-** if (__builtin_constant_p(x) && (x == NULL))
-** if (((unsigned long)p & 0xf) == 0)
-** return __ldcw(p);
-*/
-#define xchg(ptr,x) \
- ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
-
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-/* bug catcher for when unsupported size is used - won't link */
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
-extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old, unsigned int new_);
-extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new_);
-
-/* don't worry...optimizer will get rid of most of this */
-static __inline__ unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
-{
- switch(size) {
-#ifdef CONFIG_64BIT
- case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
-#endif
- case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int) old, (unsigned int) new_);
- }
- __cmpxchg_called_with_bad_pointer();
- return old;
-}
-
-#define cmpxchg(ptr,o,n) \
- ({ \
- __typeof__(*(ptr)) _o_ = (o); \
- __typeof__(*(ptr)) _n_ = (n); \
- (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
- (unsigned long)_n_, sizeof(*(ptr))); \
- })
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
- unsigned long old,
- unsigned long new_, int size)
-{
- switch (size) {
-#ifdef CONFIG_64BIT
- case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
-#endif
- case 4: return __cmpxchg_u32(ptr, old, new_);
- default:
- return __cmpxchg_local_generic(ptr, old, new_, size);
- }
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n) \
- ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
- (unsigned long)(n), sizeof(*(ptr))))
-#ifdef CONFIG_64BIT
-#define cmpxchg64_local(ptr, o, n) \
- ({ \
- BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
- cmpxchg_local((ptr), (o), (n)); \
- })
-#else
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#endif
-
/*
* Note that we need not lock read accesses - aligned word writes/reads
* are atomic, so a reader never sees inconsistent values.
diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h
new file mode 100644
index 0000000..dbd1335
--- /dev/null
+++ b/arch/parisc/include/asm/cmpxchg.h
@@ -0,0 +1,116 @@
+/*
+ * forked from parisc asm/atomic.h which was:
+ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
+ * Copyright (C) 2006 Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef _ASM_PARISC_CMPXCHG_H_
+#define _ASM_PARISC_CMPXCHG_H_
+
+/* This should get optimized out since it's never called.
+** Or get a link error if xchg is used "wrong".
+*/
+extern void __xchg_called_with_bad_pointer(void);
+
+/* __xchg32/64 defined in arch/parisc/lib/bitops.c */
+extern unsigned long __xchg8(char, char *);
+extern unsigned long __xchg32(int, int *);
+#ifdef CONFIG_64BIT
+extern unsigned long __xchg64(unsigned long, unsigned long *);
+#endif
+
+/* optimizer better get rid of switch since size is a constant */
+static inline unsigned long
+__xchg(unsigned long x, __volatile__ void *ptr, int size)
+{
+ switch (size) {
+#ifdef CONFIG_64BIT
+ case 8: return __xchg64(x, (unsigned long *) ptr);
+#endif
+ case 4: return __xchg32((int) x, (int *) ptr);
+ case 1: return __xchg8((char) x, (char *) ptr);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+/*
+** REVISIT - Abandoned use of LDCW in xchg() for now:
+** o need to test sizeof(*ptr) to avoid clearing adjacent bytes
+** o and while we are at it, could CONFIG_64BIT code use LDCD too?
+**
+** if (__builtin_constant_p(x) && (x == NULL))
+** if (((unsigned long)p & 0xf) == 0)
+** return __ldcw(p);
+*/
+#define xchg(ptr, x) \
+ ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+/* bug catcher for when unsupported size is used - won't link */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+/* __cmpxchg_u32/u64 defined in arch/parisc/lib/bitops.c */
+extern unsigned long __cmpxchg_u32(volatile unsigned int *m, unsigned int old,
+ unsigned int new_);
+extern unsigned long __cmpxchg_u64(volatile unsigned long *ptr,
+ unsigned long old, unsigned long new_);
+
+/* don't worry...optimizer will get rid of most of this */
+static inline unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size)
+{
+ switch (size) {
+#ifdef CONFIG_64BIT
+ case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+#endif
+ case 4: return __cmpxchg_u32((unsigned int *)ptr,
+ (unsigned int)old, (unsigned int)new_);
+ }
+ __cmpxchg_called_with_bad_pointer();
+ return old;
+}
+
+#define cmpxchg(ptr, o, n) \
+({ \
+ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof(*(ptr))); \
+})
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(volatile void *ptr,
+ unsigned long old,
+ unsigned long new_, int size)
+{
+ switch (size) {
+#ifdef CONFIG_64BIT
+ case 8: return __cmpxchg_u64((unsigned long *)ptr, old, new_);
+#endif
+ case 4: return __cmpxchg_u32(ptr, old, new_);
+ default:
+ return __cmpxchg_local_generic(ptr, old, new_, size);
+ }
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n) \
+ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \
+ (unsigned long)(n), sizeof(*(ptr))))
+#ifdef CONFIG_64BIT
+#define cmpxchg64_local(ptr, o, n) \
+({ \
+ BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
+ cmpxchg_local((ptr), (o), (n)); \
+})
+#else
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
+#endif /* _ASM_PARISC_CMPXCHG_H_ */
diff --git a/arch/parisc/kernel/pdc_cons.c b/arch/parisc/kernel/pdc_cons.c
index 4f00459..0b33933 100644
--- a/arch/parisc/kernel/pdc_cons.c
+++ b/arch/parisc/kernel/pdc_cons.c
@@ -104,7 +104,7 @@
static void pdc_console_tty_close(struct tty_struct *tty, struct file *filp)
{
- if (!tty->count) {
+ if (tty->count == 1) {
del_timer_sync(&pdc_console_timer);
tty_port_tty_set(&tty_port, NULL);
}
diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi
new file mode 100644
index 0000000..1cf0b77
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi
@@ -0,0 +1,43 @@
+/*
+ * PQ3 MPIC Message (Group B) device tree stub [ controller @ offset 0x42400 ]
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+message@42400 {
+ compatible = "fsl,mpic-v3.1-msgr";
+ reg = <0x42400 0x200>;
+ interrupts = <
+ 0xb4 2 0 0
+ 0xb5 2 0 0
+ 0xb6 2 0 0
+ 0xb7 2 0 0>;
+};
diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
index fdedf7b..71c30eb 100644
--- a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
+++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi
@@ -53,6 +53,16 @@
3 0 3 0>;
};
+message@41400 {
+ compatible = "fsl,mpic-v3.1-msgr";
+ reg = <0x41400 0x200>;
+ interrupts = <
+ 0xb0 2 0 0
+ 0xb1 2 0 0
+ 0xb2 2 0 0
+ 0xb3 2 0 0>;
+};
+
msi@41600 {
compatible = "fsl,mpic-msi";
reg = <0x41600 0x80>;
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc.dtsi b/arch/powerpc/boot/dts/p1020mbg-pc.dtsi
new file mode 100644
index 0000000..a24699c
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020mbg-pc.dtsi
@@ -0,0 +1,151 @@
+/*
+ * P1020 MBG-PC Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ partition@0 {
+ /* 128KB for DTB Image */
+ reg = <0x0 0x00020000>;
+ label = "NOR DTB Image";
+ };
+
+ partition@20000 {
+ /* 3.875 MB for Linux Kernel Image */
+ reg = <0x00020000 0x003e0000>;
+ label = "NOR Linux Kernel Image";
+ };
+
+ partition@400000 {
+ /* 58MB for Root file System */
+ reg = <0x00400000 0x03a00000>;
+ label = "NOR Root File System";
+ };
+
+ partition@3e00000 {
+ /* This location must not be altered */
+ /* 1M for Vitesse 7385 Switch firmware */
+ reg = <0x3e00000 0x00100000>;
+ label = "NOR Vitesse-7385 Firmware";
+ read-only;
+ };
+
+ partition@3f00000 {
+ /* This location must not be altered */
+ /* 512KB for u-boot Bootloader Image */
+ /* 512KB for u-boot Environment Variables */
+ reg = <0x03f00000 0x00100000>;
+ label = "NOR U-Boot Image";
+ read-only;
+ };
+ };
+
+ L2switch@2,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "vitesse-7385";
+ reg = <0x2 0x0 0x20000>;
+ };
+};
+
+&soc {
+ i2c@3000 {
+ rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
+ };
+
+ mdio@24000 {
+ phy0: ethernet-phy@0 {
+ interrupts = <3 1 0 0>;
+ reg = <0x0>;
+ };
+ phy1: ethernet-phy@1 {
+ interrupts = <2 1 0 0>;
+ reg = <0x1>;
+ };
+ };
+
+ mdio@25000 {
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@26000 {
+ tbi2: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet0: ethernet@b0000 {
+ fixed-link = <1 1 1000 0 0>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet1: ethernet@b1000 {
+ phy-handle = <&phy0>;
+ tbi-handle = <&tbi1>;
+ phy-connection-type = "sgmii";
+ };
+
+ enet2: ethernet@b2000 {
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ usb@22000 {
+ phy_type = "ulpi";
+ };
+
+ /* USB2 is shared with localbus, so it must be disabled
+ by default. We can't put 'status = "disabled";' here
+ since U-Boot doesn't clear the status property when
+ it enables USB2. OTOH, U-Boot does create a new node
+ when there isn't any. So, just comment it out.
+ */
+ usb@23000 {
+ status = "disabled";
+ phy_type = "ulpi";
+ };
+};
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts
new file mode 100644
index 0000000..ab8f076
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020mbg-pc_32b.dts
@@ -0,0 +1,89 @@
+/*
+ * P1020 MBG-PC Device Tree Source (32-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+ model = "fsl,P1020MBG-PC";
+ compatible = "fsl,P1020MBG-PC";
+
+ memory {
+ device_type = "memory";
+ };
+
+ lbc: localbus@ffe05000 {
+ reg = <0x0 0xffe05000 0x0 0x1000>;
+
+ /* NOR and L2 switch */
+ ranges = <0x0 0x0 0x0 0xec000000 0x04000000
+ 0x1 0x0 0x0 0xffa00000 0x00040000
+ 0x2 0x0 0x0 0xffb00000 0x00020000>;
+ };
+
+ soc: soc@ffe00000 {
+ ranges = <0x0 0x0 0xffe00000 0x100000>;
+ };
+
+ pci0: pcie@ffe09000 {
+ reg = <0x0 0xffe09000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ffe0a000 {
+ reg = <0x0 0xffe0a000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
+
+/include/ "p1020mbg-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts b/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts
new file mode 100644
index 0000000..9e9f401
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020mbg-pc_36b.dts
@@ -0,0 +1,89 @@
+/*
+ * P1020 MBG-PC Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+ model = "fsl,P1020MBG-PC";
+ compatible = "fsl,P1020MBG-PC";
+
+ memory {
+ device_type = "memory";
+ };
+
+ lbc: localbus@fffe05000 {
+ reg = <0xf 0xffe05000 0x0 0x1000>;
+
+ /* NOR and L2 switch */
+ ranges = <0x0 0x0 0xf 0xec000000 0x04000000
+ 0x1 0x0 0xf 0xffa00000 0x00040000
+ 0x2 0x0 0xf 0xffb00000 0x00020000>;
+ };
+
+ soc: soc@fffe00000 {
+ ranges = <0x0 0xf 0xffe00000 0x100000>;
+ };
+
+ pci0: pcie@fffe09000 {
+ reg = <0xf 0xffe09000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@fffe0a000 {
+ reg = <0xf 0xffe0a000 0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
+
+/include/ "p1020mbg-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020utm-pc.dtsi b/arch/powerpc/boot/dts/p1020utm-pc.dtsi
new file mode 100644
index 0000000..7ea85ea
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020utm-pc.dtsi
@@ -0,0 +1,140 @@
+/*
+ * P1020 UTM-PC Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+ nor@0,0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "cfi-flash";
+ reg = <0x0 0x0 0x2000000>;
+ bank-width = <2>;
+ device-width = <1>;
+
+ partition@0 {
+ /* 256KB for DTB Image */
+ reg = <0x0 0x00040000>;
+ label = "NOR DTB Image";
+ };
+
+ partition@40000 {
+ /* 3.75 MB for Linux Kernel Image */
+ reg = <0x00040000 0x003c0000>;
+ label = "NOR Linux Kernel Image";
+ };
+
+ partition@400000 {
+ /* 27MB for Root file System */
+ reg = <0x00400000 0x01b00000>;
+ label = "NOR Root File System";
+ };
+
+ partition@1f00000 {
+ /* This location must not be altered */
+ /* 512KB for u-boot Bootloader Image */
+ /* 512KB for u-boot Environment Variables */
+ reg = <0x01f00000 0x00100000>;
+ label = "NOR U-Boot Image";
+ read-only;
+ };
+ };
+};
+
+&soc {
+ i2c@3000 {
+ rtc@68 {
+ compatible = "dallas,ds1339";
+ reg = <0x68>;
+ };
+ };
+
+ mdio@24000 {
+ phy0: ethernet-phy@0 {
+ interrupts = <3 1 0 0>;
+ reg = <0x0>;
+ };
+ phy1: ethernet-phy@1 {
+ interrupts = <2 1 0 0>;
+ reg = <0x1>;
+ };
+ phy2: ethernet-phy@2 {
+ interrupts = <1 1 0 0>;
+ reg = <0x2>;
+ };
+ };
+
+ mdio@25000 {
+ tbi1: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ mdio@26000 {
+ tbi2: tbi-phy@11 {
+ reg = <0x11>;
+ device_type = "tbi-phy";
+ };
+ };
+
+ enet0: ethernet@b0000 {
+ phy-handle = <&phy2>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ enet1: ethernet@b1000 {
+ phy-handle = <&phy0>;
+ tbi-handle = <&tbi1>;
+ phy-connection-type = "sgmii";
+ };
+
+ enet2: ethernet@b2000 {
+ phy-handle = <&phy1>;
+ phy-connection-type = "rgmii-id";
+ };
+
+ usb@22000 {
+ phy_type = "ulpi";
+ };
+
+ /* USB2 is shared with localbus, so it must be disabled
+ by default. We can't put 'status = "disabled";' here
+ since U-Boot doesn't clear the status property when
+ it enables USB2. OTOH, U-Boot does create a new node
+ when there isn't any. So, just comment it out.
+ */
+ usb@23000 {
+ status = "disabled";
+ phy_type = "ulpi";
+ };
+};
diff --git a/arch/powerpc/boot/dts/p1020utm-pc_32b.dts b/arch/powerpc/boot/dts/p1020utm-pc_32b.dts
new file mode 100644
index 0000000..4bfdd89
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020utm-pc_32b.dts
@@ -0,0 +1,89 @@
+/*
+ * P1020 UTM-PC Device Tree Source (32-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+ model = "fsl,P1020UTM-PC";
+ compatible = "fsl,P1020UTM-PC";
+
+ memory {
+ device_type = "memory";
+ };
+
+ lbc: localbus@ffe05000 {
+ reg = <0x0 0xffe05000 0x0 0x1000>;
+
+ /* NOR */
+ ranges = <0x0 0x0 0x0 0xec000000 0x02000000
+ 0x1 0x0 0x0 0xffa00000 0x00040000
+ 0x2 0x0 0x0 0xffb00000 0x00020000>;
+ };
+
+ soc: soc@ffe00000 {
+ ranges = <0x0 0x0 0xffe00000 0x100000>;
+ };
+
+ pci0: pcie@ffe09000 {
+ reg = <0x0 0xffe09000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@ffe0a000 {
+ reg = <0x0 0xffe0a000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
+
+/include/ "p1020utm-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1020utm-pc_36b.dts b/arch/powerpc/boot/dts/p1020utm-pc_36b.dts
new file mode 100644
index 0000000..abec535
--- /dev/null
+++ b/arch/powerpc/boot/dts/p1020utm-pc_36b.dts
@@ -0,0 +1,89 @@
+/*
+ * P1020 UTM-PC Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Freescale Semiconductor nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+ model = "fsl,P1020UTM-PC";
+ compatible = "fsl,P1020UTM-PC";
+
+ memory {
+ device_type = "memory";
+ };
+
+ lbc: localbus@fffe05000 {
+ reg = <0xf 0xffe05000 0x0 0x1000>;
+
+ /* NOR */
+ ranges = <0x0 0x0 0xf 0xec000000 0x02000000
+ 0x1 0x0 0xf 0xffa00000 0x00040000
+ 0x2 0x0 0xf 0xffb00000 0x00020000>;
+ };
+
+ soc: soc@fffe00000 {
+ ranges = <0x0 0xf 0xffe00000 0x100000>;
+ };
+
+ pci0: pcie@fffe09000 {
+ reg = <0xf 0xffe09000 0x0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+
+ pci1: pcie@fffe0a000 {
+ reg = <0xf 0xffe0a000 0 0x1000>;
+ ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+ pcie@0 {
+ ranges = <0x2000000 0x0 0xe0000000
+ 0x2000000 0x0 0xe0000000
+ 0x0 0x20000000
+
+ 0x1000000 0x0 0x0
+ 0x1000000 0x0 0x0
+ 0x0 0x100000>;
+ };
+ };
+};
+
+/include/ "p1020utm-pc.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p2041rdb.dts b/arch/powerpc/boot/dts/p2041rdb.dts
index 4f957db..2852139 100644
--- a/arch/powerpc/boot/dts/p2041rdb.dts
+++ b/arch/powerpc/boot/dts/p2041rdb.dts
@@ -135,7 +135,6 @@
reg = <0xf 0xfe200000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- fsl,msi = <&msi0>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -151,7 +150,6 @@
reg = <0xf 0xfe201000 0 0x1000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- fsl,msi = <&msi1>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -167,7 +165,6 @@
reg = <0xf 0xfe202000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
diff --git a/arch/powerpc/boot/dts/p3041ds.dts b/arch/powerpc/boot/dts/p3041ds.dts
index f469145..22a215e 100644
--- a/arch/powerpc/boot/dts/p3041ds.dts
+++ b/arch/powerpc/boot/dts/p3041ds.dts
@@ -173,7 +173,6 @@
reg = <0xf 0xfe200000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- fsl,msi = <&msi0>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -189,7 +188,6 @@
reg = <0xf 0xfe201000 0 0x1000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- fsl,msi = <&msi1>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -205,7 +203,6 @@
reg = <0xf 0xfe202000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -221,7 +218,6 @@
reg = <0xf 0xfe203000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
diff --git a/arch/powerpc/boot/dts/p3060qds.dts b/arch/powerpc/boot/dts/p3060qds.dts
index 529042e..9ae875c 100644
--- a/arch/powerpc/boot/dts/p3060qds.dts
+++ b/arch/powerpc/boot/dts/p3060qds.dts
@@ -212,7 +212,6 @@
reg = <0xf 0xfe200000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- fsl,msi = <&msi0>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -228,7 +227,6 @@
reg = <0xf 0xfe201000 0 0x1000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- fsl,msi = <&msi1>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts
index 6d60e54..3e20460 100644
--- a/arch/powerpc/boot/dts/p4080ds.dts
+++ b/arch/powerpc/boot/dts/p4080ds.dts
@@ -141,7 +141,6 @@
reg = <0xf 0xfe200000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- fsl,msi = <&msi0>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -157,7 +156,6 @@
reg = <0xf 0xfe201000 0 0x1000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- fsl,msi = <&msi1>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -173,7 +171,6 @@
reg = <0xf 0xfe202000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
diff --git a/arch/powerpc/boot/dts/p5020ds.dts b/arch/powerpc/boot/dts/p5020ds.dts
index 1c25068..27c07ed 100644
--- a/arch/powerpc/boot/dts/p5020ds.dts
+++ b/arch/powerpc/boot/dts/p5020ds.dts
@@ -173,7 +173,6 @@
reg = <0xf 0xfe200000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
- fsl,msi = <&msi0>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -189,7 +188,6 @@
reg = <0xf 0xfe201000 0 0x1000>;
ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
- fsl,msi = <&msi1>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -205,7 +203,6 @@
reg = <0xf 0xfe202000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
@@ -221,7 +218,6 @@
reg = <0xf 0xfe203000 0 0x1000>;
ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000
0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>;
- fsl,msi = <&msi2>;
pcie@0 {
ranges = <0x02000000 0 0xe0000000
0x02000000 0 0xe0000000
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index f8aef20..91db656 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -116,6 +116,7 @@
CONFIG_HW_RANDOM=y
CONFIG_NVRAM=y
CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
CONFIG_SPI=y
CONFIG_SPI_GPIO=y
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 82b13bf..6798343 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -71,6 +71,8 @@
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y
CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MPC=y
# CONFIG_HWMON is not set
CONFIG_VIDEO_OUTPUT_CONTROL=y
# CONFIG_HID_SUPPORT is not set
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index cc87a84..d6b6df5 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -117,6 +117,7 @@
CONFIG_SERIAL_QE=m
CONFIG_NVRAM=y
CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
CONFIG_I2C_CPM=m
CONFIG_I2C_MPC=y
CONFIG_SPI=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 48d6682..5b0e292 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -119,6 +119,7 @@
CONFIG_SERIAL_QE=m
CONFIG_NVRAM=y
CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
CONFIG_I2C_CPM=m
CONFIG_I2C_MPC=y
CONFIG_SPI=y
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index dd70fac..62678e3 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -22,9 +22,11 @@
/* Some dma direct funcs must be visible for use in other dma_ops */
extern void *dma_direct_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs);
extern void dma_direct_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs);
#ifdef CONFIG_NOT_COHERENT_CACHE
@@ -130,23 +132,29 @@
extern int dma_set_mask(struct device *dev, u64 dma_mask);
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
void *cpu_addr;
BUG_ON(!dma_ops);
- cpu_addr = dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+ cpu_addr = dma_ops->alloc(dev, size, dma_handle, flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
return cpu_addr;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
@@ -154,7 +162,7 @@
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
diff --git a/arch/powerpc/include/asm/epapr_hcalls.h b/arch/powerpc/include/asm/epapr_hcalls.h
index f3b0c2c..976835d 100644
--- a/arch/powerpc/include/asm/epapr_hcalls.h
+++ b/arch/powerpc/include/asm/epapr_hcalls.h
@@ -134,10 +134,15 @@
* whether they will be clobbered.
*
* Note that r11 can be used as an output parameter.
+ *
+ * The "memory" clobber is only necessary for hcalls where the Hypervisor
+ * will read or write guest memory. However, we add it to all hcalls because
+ * the impact is minimal, and we want to ensure that it's present for the
+ * hcalls that need it.
*/
/* List of common clobbered registers. Do not use this macro. */
-#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc"
+#define EV_HCALL_CLOBBERS "r0", "r12", "xer", "ctr", "lr", "cc", "memory"
#define EV_HCALL_CLOBBERS8 EV_HCALL_CLOBBERS
#define EV_HCALL_CLOBBERS7 EV_HCALL_CLOBBERS8, "r10"
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 548da3a..d58fc4e 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -288,13 +288,6 @@
/* Exception addition: Hard disable interrupts */
#define DISABLE_INTS SOFT_DISABLE_INTS(r10,r11)
-/* Exception addition: Keep interrupt state */
-#define ENABLE_INTS \
- ld r11,PACAKMSR(r13); \
- ld r12,_MSR(r1); \
- rlwimi r11,r12,0,MSR_EE; \
- mtmsrd r11,1
-
#define ADD_NVGPRS \
bl .save_nvgprs
diff --git a/arch/powerpc/include/asm/fsl_guts.h b/arch/powerpc/include/asm/fsl_guts.h
index ce04530..aa4c488 100644
--- a/arch/powerpc/include/asm/fsl_guts.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -16,15 +16,6 @@
#define __ASM_POWERPC_FSL_GUTS_H__
#ifdef __KERNEL__
-/*
- * These #ifdefs are safe because it's not possible to build a kernel that
- * runs on e500 and e600 cores.
- */
-
-#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx)
-#error Only 85xx and 86xx SOCs are supported
-#endif
-
/**
* Global Utility Registers.
*
@@ -36,11 +27,7 @@
* different names. In these cases, one name is chosen to avoid extraneous
* #ifdefs.
*/
-#ifdef CONFIG_PPC_85xx
-struct ccsr_guts_85xx {
-#else
-struct ccsr_guts_86xx {
-#endif
+struct ccsr_guts {
__be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */
__be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */
__be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */
@@ -77,11 +64,8 @@
u8 res0a8[0xb0 - 0xa8];
__be32 rstcr; /* 0x.00b0 - Reset Control Register */
u8 res0b4[0xc0 - 0xb4];
-#ifdef CONFIG_PPC_85xx
- __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */
-#else
- __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
-#endif
+ __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register
+ Called 'elbcvselcr' on 86xx SOCs */
u8 res0c4[0x224 - 0xc4];
__be32 iodelay1; /* 0x.0224 - IO delay control register 1 */
__be32 iodelay2; /* 0x.0228 - IO delay control register 2 */
@@ -136,7 +120,7 @@
* ch: The channel on the DMA controller (0, 1, 2, or 3)
* device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
*/
-static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
+static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
unsigned int co, unsigned int ch, unsigned int device)
{
unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -172,7 +156,7 @@
* ch: The channel on the DMA controller (0, 1, 2, or 3)
* value: the new value for the bit (0 or 1)
*/
-static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,
+static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
unsigned int co, unsigned int ch, unsigned int value)
{
if ((ch == 0) || (ch == 3)) {
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
index cf417e51..0e40843 100644
--- a/arch/powerpc/include/asm/irq.h
+++ b/arch/powerpc/include/asm/irq.h
@@ -18,10 +18,6 @@
#include <linux/atomic.h>
-/* Define a way to iterate across irqs. */
-#define for_each_irq(i) \
- for ((i) = 0; (i) < NR_IRQS; ++(i))
-
extern atomic_t ppc_n_lost_interrupts;
/* This number is used when no interrupt has been assigned */
@@ -33,8 +29,6 @@
/* Same thing, used by the generic IRQ code */
#define NR_IRQS_LEGACY NUM_ISA_INTERRUPTS
-struct irq_data;
-extern irq_hw_number_t irqd_to_hwirq(struct irq_data *d);
extern irq_hw_number_t virq_to_hw(unsigned int virq);
/**
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index c65b929..c9f698a 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -275,9 +275,6 @@
unsigned int isu_mask;
/* Number of sources */
unsigned int num_sources;
- /* default senses array */
- unsigned char *senses;
- unsigned int senses_count;
/* vector numbers used for internal sources (ipi/timers) */
unsigned int ipi_vecs[4];
@@ -415,21 +412,6 @@
extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num,
phys_addr_t phys_addr);
-/* Set default sense codes
- *
- * @mpic: controller
- * @senses: array of sense codes
- * @count: size of above array
- *
- * Optionally provide an array (indexed on hardware interrupt numbers
- * for this MPIC) of default sense codes for the chip. Those are linux
- * sense codes IRQ_TYPE_*
- *
- * The driver gets ownership of the pointer, don't dispose of it or
- * anything like that. __init only.
- */
-extern void mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count);
-
/* Initialize the controller. After this has been called, none of the above
* should be called again for this mpic
diff --git a/arch/powerpc/include/asm/mpic_msgr.h b/arch/powerpc/include/asm/mpic_msgr.h
index 3ec37dc..326d33c 100644
--- a/arch/powerpc/include/asm/mpic_msgr.h
+++ b/arch/powerpc/include/asm/mpic_msgr.h
@@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
+#include <asm/smp.h>
struct mpic_msgr {
u32 __iomem *base;
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h
index b86faa9..8a97aa7 100644
--- a/arch/powerpc/include/asm/reg_booke.h
+++ b/arch/powerpc/include/asm/reg_booke.h
@@ -15,11 +15,6 @@
#ifndef __ASM_POWERPC_REG_BOOKE_H__
#define __ASM_POWERPC_REG_BOOKE_H__
-#ifdef CONFIG_BOOKE_WDT
-extern u32 booke_wdt_enabled;
-extern u32 booke_wdt_period;
-#endif /* CONFIG_BOOKE_WDT */
-
/* Machine State Register (MSR) Fields */
#define MSR_GS (1<<28) /* Guest state */
#define MSR_UCLE (1<<26) /* User-mode cache lock enable */
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 3f6464b..bcfdcd2 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -17,7 +17,8 @@
* to the dma address (mapping) of the first page.
*/
static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
return iommu_alloc_coherent(dev, get_iommu_table_base(dev), size,
dma_handle, dev->coherent_dma_mask, flag,
@@ -25,7 +26,8 @@
}
static void dma_iommu_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
iommu_free_coherent(get_iommu_table_base(dev), size, vaddr, dma_handle);
}
@@ -105,8 +107,8 @@
}
struct dma_map_ops dma_iommu_ops = {
- .alloc_coherent = dma_iommu_alloc_coherent,
- .free_coherent = dma_iommu_free_coherent,
+ .alloc = dma_iommu_alloc_coherent,
+ .free = dma_iommu_free_coherent,
.map_sg = dma_iommu_map_sg,
.unmap_sg = dma_iommu_unmap_sg,
.dma_supported = dma_iommu_dma_supported,
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 1ebc918..4ab88da 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -47,8 +47,8 @@
* for everything else.
*/
struct dma_map_ops swiotlb_dma_ops = {
- .alloc_coherent = dma_direct_alloc_coherent,
- .free_coherent = dma_direct_free_coherent,
+ .alloc = dma_direct_alloc_coherent,
+ .free = dma_direct_free_coherent,
.map_sg = swiotlb_map_sg_attrs,
.unmap_sg = swiotlb_unmap_sg_attrs,
.dma_supported = swiotlb_dma_supported,
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 7d0233c..b1ec983 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -26,7 +26,8 @@
void *dma_direct_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
void *ret;
#ifdef CONFIG_NOT_COHERENT_CACHE
@@ -54,7 +55,8 @@
}
void dma_direct_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
#ifdef CONFIG_NOT_COHERENT_CACHE
__dma_free_coherent(size, vaddr);
@@ -150,8 +152,8 @@
#endif
struct dma_map_ops dma_direct_ops = {
- .alloc_coherent = dma_direct_alloc_coherent,
- .free_coherent = dma_direct_free_coherent,
+ .alloc = dma_direct_alloc_coherent,
+ .free = dma_direct_free_coherent,
.map_sg = dma_direct_map_sg,
.unmap_sg = dma_direct_unmap_sg,
.dma_supported = dma_direct_dma_supported,
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 3e57a00..ba3aeb4 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -206,40 +206,43 @@
andi. r10,r10,MSR_EE /* Did EE change? */
beq 1f
- /* Save handler and return address into the 2 unused words
- * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything
- * else can be recovered from the pt_regs except r3 which for
- * normal interrupts has been set to pt_regs and for syscalls
- * is an argument, so we temporarily use ORIG_GPR3 to save it
- */
- stw r9,8(r1)
- stw r11,12(r1)
- stw r3,ORIG_GPR3(r1)
/*
* The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
* If from user mode there is only one stack frame on the stack, and
* accessing CALLER_ADDR1 will cause oops. So we need create a dummy
* stack frame to make trace_hardirqs_off happy.
+ *
+ * This is handy because we also need to save a bunch of GPRs,
+ * r3 can be different from GPR3(r1) at this point, r9 and r11
+ * contains the old MSR and handler address respectively,
+ * r4 & r5 can contain page fault arguments that need to be passed
+ * along as well. r12, CCR, CTR, XER etc... are left clobbered as
+ * they aren't useful past this point (aren't syscall arguments),
+ * the rest is restored from the exception frame.
*/
+ stwu r1,-32(r1)
+ stw r9,8(r1)
+ stw r11,12(r1)
+ stw r3,16(r1)
+ stw r4,20(r1)
+ stw r5,24(r1)
andi. r12,r12,MSR_PR
- beq 11f
- stwu r1,-16(r1)
+ b 11f
bl trace_hardirqs_off
- addi r1,r1,16
b 12f
-
11:
bl trace_hardirqs_off
12:
+ lwz r5,24(r1)
+ lwz r4,20(r1)
+ lwz r3,16(r1)
+ lwz r11,12(r1)
+ lwz r9,8(r1)
+ addi r1,r1,32
lwz r0,GPR0(r1)
- lwz r3,ORIG_GPR3(r1)
- lwz r4,GPR4(r1)
- lwz r5,GPR5(r1)
lwz r6,GPR6(r1)
lwz r7,GPR7(r1)
lwz r8,GPR8(r1)
- lwz r9,8(r1)
- lwz r11,12(r1)
1: mtctr r11
mtlr r9
bctr /* jump to handler */
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index f8a7a1a..fc60150 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -767,16 +767,6 @@
SOFT_DISABLE_INTS(r3,r4)
1: bl .preempt_schedule_irq
- /* Hard-disable interrupts again (and update PACA) */
-#ifdef CONFIG_PPC_BOOK3E
- wrteei 0
-#else
- ld r10,PACAKMSR(r13) /* Get kernel MSR without EE */
- mtmsrd r10,1
-#endif /* CONFIG_PPC_BOOK3E */
- li r0,PACA_IRQ_HARD_DIS
- stb r0,PACAIRQHAPPENED(r13)
-
/* Re-test flags and eventually loop */
clrrdi r9,r1,THREAD_SHIFT
ld r4,TI_FLAGS(r9)
@@ -787,14 +777,6 @@
user_work:
#endif /* CONFIG_PREEMPT */
- /* Enable interrupts */
-#ifdef CONFIG_PPC_BOOK3E
- wrteei 1
-#else
- ori r10,r10,MSR_EE
- mtmsrd r10,1
-#endif /* CONFIG_PPC_BOOK3E */
-
andi. r0,r4,_TIF_NEED_RESCHED
beq 1f
bl .restore_interrupts
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index cb705fd..8f880bc 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -768,8 +768,8 @@
std r3,_DAR(r1)
std r4,_DSISR(r1)
bl .save_nvgprs
+ DISABLE_INTS
addi r3,r1,STACK_FRAME_OVERHEAD
- ENABLE_INTS
bl .alignment_exception
b .ret_from_except
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index cfe7a38..18bdf74 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -40,6 +40,8 @@
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/fadump.h>
+#include <asm/debug.h>
+#include <asm/setup.h>
static struct fw_dump fw_dump;
static struct fadump_mem_struct fdm;
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 79bb282..b01d14e 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -65,7 +65,8 @@
static void *ibmebus_alloc_coherent(struct device *dev,
size_t size,
dma_addr_t *dma_handle,
- gfp_t flag)
+ gfp_t flag,
+ struct dma_attrs *attrs)
{
void *mem;
@@ -77,7 +78,8 @@
static void ibmebus_free_coherent(struct device *dev,
size_t size, void *vaddr,
- dma_addr_t dma_handle)
+ dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
kfree(vaddr);
}
@@ -136,8 +138,8 @@
}
static struct dma_map_ops ibmebus_dma_ops = {
- .alloc_coherent = ibmebus_alloc_coherent,
- .free_coherent = ibmebus_free_coherent,
+ .alloc = ibmebus_alloc_coherent,
+ .free = ibmebus_free_coherent,
.map_sg = ibmebus_map_sg,
.unmap_sg = ibmebus_unmap_sg,
.dma_supported = ibmebus_dma_supported,
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 243dbab..c6c6f3b 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -260,11 +260,17 @@
* if they are currently disabled. This is typically called before
* schedule() or do_signal() when returning to userspace. We do it
* in C to avoid the burden of dealing with lockdep etc...
+ *
+ * NOTE: This is called with interrupts hard disabled but not marked
+ * as such in paca->irq_happened, so we need to resync this.
*/
void restore_interrupts(void)
{
- if (irqs_disabled())
+ if (irqs_disabled()) {
+ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
local_irq_enable();
+ } else
+ __hard_irq_enable();
}
#endif /* CONFIG_PPC64 */
@@ -330,14 +336,10 @@
alloc_cpumask_var(&mask, GFP_KERNEL);
- for_each_irq(irq) {
+ for_each_irq_desc(irq, desc) {
struct irq_data *data;
struct irq_chip *chip;
- desc = irq_to_desc(irq);
- if (!desc)
- continue;
-
data = irq_desc_get_irq_data(desc);
if (irqd_is_per_cpu(data))
continue;
@@ -560,12 +562,6 @@
local_irq_restore(flags);
}
-irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
-{
- return d->hwirq;
-}
-EXPORT_SYMBOL_GPL(irqd_to_hwirq);
-
irq_hw_number_t virq_to_hw(unsigned int virq)
{
struct irq_data *irq_data = irq_get_irq_data(virq);
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index 76a6e40..782bd0a 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -24,6 +24,7 @@
#include <asm/current.h>
#include <asm/processor.h>
#include <asm/machdep.h>
+#include <asm/debug.h>
/*
* This table contains the mapping between PowerPC hardware trap types, and
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index c957b12..5df7777 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -23,14 +23,11 @@
void machine_kexec_mask_interrupts(void) {
unsigned int i;
+ struct irq_desc *desc;
- for_each_irq(i) {
- struct irq_desc *desc = irq_to_desc(i);
+ for_each_irq_desc(i, desc) {
struct irq_chip *chip;
- if (!desc)
- continue;
-
chip = irq_desc_get_chip(desc);
if (!chip)
continue;
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index f88698c..4937c96 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1235,7 +1235,7 @@
ctrl |= CTRL_RUNLATCH;
mtspr(SPRN_CTRLT, ctrl);
- ti->local_flags |= TLF_RUNLATCH;
+ ti->local_flags |= _TLF_RUNLATCH;
}
/* Called with hard IRQs off */
@@ -1244,7 +1244,7 @@
struct thread_info *ti = current_thread_info();
unsigned long ctrl;
- ti->local_flags &= ~TLF_RUNLATCH;
+ ti->local_flags &= ~_TLF_RUNLATCH;
ctrl = mfspr(SPRN_CTRLF);
ctrl &= ~CTRL_RUNLATCH;
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 9825f29..ec8a53f 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -150,6 +150,9 @@
}
#ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+
/* Checks wdt=x and wdt_period=xx command-line option */
notrace int __init early_parse_wdt(char *p)
{
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 6aa0c66..1589723 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -248,7 +248,7 @@
addr, regs->nip, regs->link, code);
}
- if (!arch_irq_disabled_regs(regs))
+ if (arch_irqs_disabled() && !arch_irq_disabled_regs(regs))
local_irq_enable();
memset(&info, 0, sizeof(info));
@@ -1019,7 +1019,9 @@
return;
}
- local_irq_enable();
+ /* We restore the interrupt state now */
+ if (!arch_irq_disabled_regs(regs))
+ local_irq_enable();
#ifdef CONFIG_MATH_EMULATION
/* (reason & REASON_ILLEGAL) would be the obvious thing here,
@@ -1069,6 +1071,10 @@
{
int sig, code, fixed = 0;
+ /* We restore the interrupt state now */
+ if (!arch_irq_disabled_regs(regs))
+ local_irq_enable();
+
/* we don't implement logging of alignment exceptions */
if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
fixed = fix_alignment(regs);
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index b2f7c84..a3a9990 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -482,7 +482,8 @@
}
static void *vio_dma_iommu_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
void *ret;
@@ -492,7 +493,7 @@
return NULL;
}
- ret = dma_iommu_ops.alloc_coherent(dev, size, dma_handle, flag);
+ ret = dma_iommu_ops.alloc(dev, size, dma_handle, flag, attrs);
if (unlikely(ret == NULL)) {
vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
atomic_inc(&viodev->cmo.allocs_failed);
@@ -502,11 +503,12 @@
}
static void vio_dma_iommu_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct vio_dev *viodev = to_vio_dev(dev);
- dma_iommu_ops.free_coherent(dev, size, vaddr, dma_handle);
+ dma_iommu_ops.free(dev, size, vaddr, dma_handle, attrs);
vio_cmo_dealloc(viodev, roundup(size, PAGE_SIZE));
}
@@ -607,8 +609,8 @@
}
struct dma_map_ops vio_dma_mapping_ops = {
- .alloc_coherent = vio_dma_iommu_alloc_coherent,
- .free_coherent = vio_dma_iommu_free_coherent,
+ .alloc = vio_dma_iommu_alloc_coherent,
+ .free = vio_dma_iommu_free_coherent,
.map_sg = vio_dma_iommu_map_sg,
.unmap_sg = vio_dma_iommu_unmap_sg,
.map_page = vio_dma_iommu_map_page,
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index ddc485a..c3beaee 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -258,6 +258,8 @@
!(memslot->userspace_addr & (s - 1))) {
start &= ~(s - 1);
pgsize = s;
+ get_page(hpage);
+ put_page(page);
page = hpage;
}
}
@@ -281,11 +283,8 @@
err = 0;
out:
- if (got) {
- if (PageHuge(page))
- page = compound_head(page);
+ if (got)
put_page(page);
- }
return err;
up_err:
@@ -678,8 +677,15 @@
SetPageDirty(page);
out_put:
- if (page)
- put_page(page);
+ if (page) {
+ /*
+ * We drop pages[0] here, not page because page might
+ * have been set to the head page of a compound, but
+ * we have to drop the reference on the correct tail
+ * page to match the get inside gup()
+ */
+ put_page(pages[0]);
+ }
return ret;
out_unlock:
@@ -979,6 +985,7 @@
pa = *physp;
}
page = pfn_to_page(pa >> PAGE_SHIFT);
+ get_page(page);
} else {
hva = gfn_to_hva_memslot(memslot, gfn);
npages = get_user_pages_fast(hva, 1, 1, pages);
@@ -991,8 +998,6 @@
page = compound_head(page);
psize <<= compound_order(page);
}
- if (!kvm->arch.using_mmu_notifiers)
- get_page(page);
offset = gpa & (psize - 1);
if (nb_ret)
*nb_ret = psize - offset;
@@ -1003,7 +1008,6 @@
{
struct page *page = virt_to_page(va);
- page = compound_head(page);
put_page(page);
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index f1950d1..135663a 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -21,6 +21,7 @@
#include <asm/disassemble.h>
#include <asm/kvm_book3s.h>
#include <asm/reg.h>
+#include <asm/switch_to.h>
#define OP_19_XOP_RFID 18
#define OP_19_XOP_RFI 50
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 01294a5..108d1f5 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1192,8 +1192,6 @@
continue;
pfn = physp[j] >> PAGE_SHIFT;
page = pfn_to_page(pfn);
- if (PageHuge(page))
- page = compound_head(page);
SetPageDirty(page);
put_page(page);
}
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index bed1279..e1b60f5 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -173,9 +173,9 @@
static struct kvmppc_linear_info *kvm_alloc_linear(int type)
{
- struct kvmppc_linear_info *ri;
+ struct kvmppc_linear_info *ri, *ret;
- ri = NULL;
+ ret = NULL;
spin_lock(&linear_lock);
list_for_each_entry(ri, &free_linears, list) {
if (ri->type != type)
@@ -183,11 +183,12 @@
list_del(&ri->list);
atomic_inc(&ri->use_count);
+ memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
+ ret = ri;
break;
}
spin_unlock(&linear_lock);
- memset(ri->base_virt, 0, ri->npages << PAGE_SHIFT);
- return ri;
+ return ret;
}
static void kvm_release_linear(struct kvmppc_linear_info *ri)
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S
index 3f7b674..d3fb4df 100644
--- a/arch/powerpc/kvm/book3s_hv_interrupts.S
+++ b/arch/powerpc/kvm/book3s_hv_interrupts.S
@@ -46,8 +46,10 @@
/* Save host state to the stack */
stdu r1, -SWITCH_FRAME_SIZE(r1)
- /* Save non-volatile registers (r14 - r31) */
+ /* Save non-volatile registers (r14 - r31) and CR */
SAVE_NVGPRS(r1)
+ mfcr r3
+ std r3, _CCR(r1)
/* Save host DSCR */
BEGIN_FTR_SECTION
@@ -157,8 +159,10 @@
* R13 = PACA
*/
- /* Restore non-volatile host registers (r14 - r31) */
+ /* Restore non-volatile host registers (r14 - r31) and CR */
REST_NVGPRS(r1)
+ ld r4, _CCR(r1)
+ mtcr r4
addi r1, r1, SWITCH_FRAME_SIZE
ld r0, PPC_LR_STKOFF(r1)
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S
index 0a8515a..3e35383 100644
--- a/arch/powerpc/kvm/book3s_interrupts.S
+++ b/arch/powerpc/kvm/book3s_interrupts.S
@@ -84,6 +84,10 @@
/* Save non-volatile registers (r14 - r31) */
SAVE_NVGPRS(r1)
+ /* Save CR */
+ mfcr r14
+ stw r14, _CCR(r1)
+
/* Save LR */
PPC_STL r0, _LINK(r1)
@@ -165,6 +169,9 @@
PPC_LL r4, _LINK(r1)
mtlr r4
+ lwz r14, _CCR(r1)
+ mtcr r14
+
/* Restore non-volatile host registers (r14 - r31) */
REST_NVGPRS(r1)
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c
index e70ef2d..a59a25a 100644
--- a/arch/powerpc/kvm/book3s_paired_singles.c
+++ b/arch/powerpc/kvm/book3s_paired_singles.c
@@ -24,6 +24,7 @@
#include <asm/kvm_fpu.h>
#include <asm/reg.h>
#include <asm/cacheflush.h>
+#include <asm/switch_to.h>
#include <linux/vmalloc.h>
/* #define DEBUG */
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index 7340e10..7759053 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -33,6 +33,7 @@
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
#include <asm/mmu_context.h>
+#include <asm/switch_to.h>
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
@@ -776,6 +777,7 @@
}
}
+ preempt_disable();
if (!(r & RESUME_HOST)) {
/* To avoid clobbering exit_reason, only check for signals if
* we aren't already exiting to userspace for some other
@@ -797,8 +799,6 @@
run->exit_reason = KVM_EXIT_INTR;
r = -EINTR;
} else {
- preempt_disable();
-
/* In case an interrupt came in that was triggered
* from userspace (like DEC), we need to check what
* to inject now! */
@@ -880,7 +880,8 @@
switch (reg->id) {
case KVM_REG_PPC_HIOR:
- r = put_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+ r = copy_to_user((u64 __user *)(long)reg->addr,
+ &to_book3s(vcpu)->hior, sizeof(u64));
break;
default:
break;
@@ -895,7 +896,8 @@
switch (reg->id) {
case KVM_REG_PPC_HIOR:
- r = get_user(to_book3s(vcpu)->hior, (u64 __user *)reg->addr);
+ r = copy_from_user(&to_book3s(vcpu)->hior,
+ (u64 __user *)(long)reg->addr, sizeof(u64));
if (!r)
to_book3s(vcpu)->hior_explicit = true;
break;
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S
index 10d8ef6..c8c4b87 100644
--- a/arch/powerpc/kvm/booke_interrupts.S
+++ b/arch/powerpc/kvm/booke_interrupts.S
@@ -34,7 +34,8 @@
/* r2 is special: it holds 'current', and it made nonvolatile in the
* kernel with the -ffixed-r2 gcc option. */
#define HOST_R2 12
-#define HOST_NV_GPRS 16
+#define HOST_CR 16
+#define HOST_NV_GPRS 20
#define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * 4))
#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4)
#define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
@@ -296,8 +297,10 @@
/* Return to kvm_vcpu_run(). */
lwz r4, HOST_STACK_LR(r1)
+ lwz r5, HOST_CR(r1)
addi r1, r1, HOST_STACK_SIZE
mtlr r4
+ mtcr r5
/* r3 still contains the return code from kvmppc_handle_exit(). */
blr
@@ -314,6 +317,8 @@
stw r3, HOST_RUN(r1)
mflr r3
stw r3, HOST_STACK_LR(r1)
+ mfcr r5
+ stw r5, HOST_CR(r1)
/* Save host non-volatile register state to stack. */
stw r14, HOST_NV_GPR(r14)(r1)
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h
index af1ab5e..5c3cf2d 100644
--- a/arch/powerpc/net/bpf_jit.h
+++ b/arch/powerpc/net/bpf_jit.h
@@ -48,7 +48,13 @@
/*
* Assembly helpers from arch/powerpc/net/bpf_jit.S:
*/
-extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
+#define DECLARE_LOAD_FUNC(func) \
+ extern u8 func[], func##_negative_offset[], func##_positive_offset[]
+
+DECLARE_LOAD_FUNC(sk_load_word);
+DECLARE_LOAD_FUNC(sk_load_half);
+DECLARE_LOAD_FUNC(sk_load_byte);
+DECLARE_LOAD_FUNC(sk_load_byte_msh);
#define FUNCTION_DESCR_SIZE 24
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S
index ff4506e..55ba385 100644
--- a/arch/powerpc/net/bpf_jit_64.S
+++ b/arch/powerpc/net/bpf_jit_64.S
@@ -31,14 +31,13 @@
* then branch directly to slow_path_XXX if required. (In fact, could
* load a spare GPR with the address of slow_path_generic and pass size
* as an argument, making the call site a mtlr, li and bllr.)
- *
- * Technically, the "is addr < 0" check is unnecessary & slowing down
- * the ABS path, as it's statically checked on generation.
*/
.globl sk_load_word
sk_load_word:
cmpdi r_addr, 0
- blt bpf_error
+ blt bpf_slow_path_word_neg
+ .globl sk_load_word_positive_offset
+sk_load_word_positive_offset:
/* Are we accessing past headlen? */
subi r_scratch1, r_HL, 4
cmpd r_scratch1, r_addr
@@ -51,7 +50,9 @@
.globl sk_load_half
sk_load_half:
cmpdi r_addr, 0
- blt bpf_error
+ blt bpf_slow_path_half_neg
+ .globl sk_load_half_positive_offset
+sk_load_half_positive_offset:
subi r_scratch1, r_HL, 2
cmpd r_scratch1, r_addr
blt bpf_slow_path_half
@@ -61,7 +62,9 @@
.globl sk_load_byte
sk_load_byte:
cmpdi r_addr, 0
- blt bpf_error
+ blt bpf_slow_path_byte_neg
+ .globl sk_load_byte_positive_offset
+sk_load_byte_positive_offset:
cmpd r_HL, r_addr
ble bpf_slow_path_byte
lbzx r_A, r_D, r_addr
@@ -69,22 +72,20 @@
/*
* BPF_S_LDX_B_MSH: ldxb 4*([offset]&0xf)
- * r_addr is the offset value, already known positive
+ * r_addr is the offset value
*/
.globl sk_load_byte_msh
sk_load_byte_msh:
+ cmpdi r_addr, 0
+ blt bpf_slow_path_byte_msh_neg
+ .globl sk_load_byte_msh_positive_offset
+sk_load_byte_msh_positive_offset:
cmpd r_HL, r_addr
ble bpf_slow_path_byte_msh
lbzx r_X, r_D, r_addr
rlwinm r_X, r_X, 2, 32-4-2, 31-2
blr
-bpf_error:
- /* Entered with cr0 = lt */
- li r3, 0
- /* Generated code will 'blt epilogue', returning 0. */
- blr
-
/* Call out to skb_copy_bits:
* We'll need to back up our volatile regs first; we have
* local variable space at r1+(BPF_PPC_STACK_BASIC).
@@ -136,3 +137,84 @@
lbz r_X, BPF_PPC_STACK_BASIC+(2*8)(r1)
rlwinm r_X, r_X, 2, 32-4-2, 31-2
blr
+
+/* Call out to bpf_internal_load_pointer_neg_helper:
+ * We'll need to back up our volatile regs first; we have
+ * local variable space at r1+(BPF_PPC_STACK_BASIC).
+ * Allocate a new stack frame here to remain ABI-compliant in
+ * stashing LR.
+ */
+#define sk_negative_common(SIZE) \
+ mflr r0; \
+ std r0, 16(r1); \
+ /* R3 goes in parameter space of caller's frame */ \
+ std r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ std r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ std r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ stdu r1, -BPF_PPC_SLOWPATH_FRAME(r1); \
+ /* R3 = r_skb, as passed */ \
+ mr r4, r_addr; \
+ li r5, SIZE; \
+ bl bpf_internal_load_pointer_neg_helper; \
+ /* R3 != 0 on success */ \
+ addi r1, r1, BPF_PPC_SLOWPATH_FRAME; \
+ ld r0, 16(r1); \
+ ld r_A, (BPF_PPC_STACK_BASIC+(0*8))(r1); \
+ ld r_X, (BPF_PPC_STACK_BASIC+(1*8))(r1); \
+ mtlr r0; \
+ cmpldi r3, 0; \
+ beq bpf_error_slow; /* cr0 = EQ */ \
+ mr r_addr, r3; \
+ ld r_skb, (BPF_PPC_STACKFRAME+48)(r1); \
+ /* Great success! */
+
+bpf_slow_path_word_neg:
+ lis r_scratch1,-32 /* SKF_LL_OFF */
+ cmpd r_addr, r_scratch1 /* addr < SKF_* */
+ blt bpf_error /* cr0 = LT */
+ .globl sk_load_word_negative_offset
+sk_load_word_negative_offset:
+ sk_negative_common(4)
+ lwz r_A, 0(r_addr)
+ blr
+
+bpf_slow_path_half_neg:
+ lis r_scratch1,-32 /* SKF_LL_OFF */
+ cmpd r_addr, r_scratch1 /* addr < SKF_* */
+ blt bpf_error /* cr0 = LT */
+ .globl sk_load_half_negative_offset
+sk_load_half_negative_offset:
+ sk_negative_common(2)
+ lhz r_A, 0(r_addr)
+ blr
+
+bpf_slow_path_byte_neg:
+ lis r_scratch1,-32 /* SKF_LL_OFF */
+ cmpd r_addr, r_scratch1 /* addr < SKF_* */
+ blt bpf_error /* cr0 = LT */
+ .globl sk_load_byte_negative_offset
+sk_load_byte_negative_offset:
+ sk_negative_common(1)
+ lbz r_A, 0(r_addr)
+ blr
+
+bpf_slow_path_byte_msh_neg:
+ lis r_scratch1,-32 /* SKF_LL_OFF */
+ cmpd r_addr, r_scratch1 /* addr < SKF_* */
+ blt bpf_error /* cr0 = LT */
+ .globl sk_load_byte_msh_negative_offset
+sk_load_byte_msh_negative_offset:
+ sk_negative_common(1)
+ lbz r_X, 0(r_addr)
+ rlwinm r_X, r_X, 2, 32-4-2, 31-2
+ blr
+
+bpf_error_slow:
+ /* fabricate a cr0 = lt */
+ li r_scratch1, -1
+ cmpdi r_scratch1, 0
+bpf_error:
+ /* Entered with cr0 = lt */
+ li r3, 0
+ /* Generated code will 'blt epilogue', returning 0. */
+ blr
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 73619d3..2dc8b14 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -127,6 +127,9 @@
PPC_BLR();
}
+#define CHOOSE_LOAD_FUNC(K, func) \
+ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
+
/* Assemble the body code between the prologue & epilogue. */
static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
struct codegen_context *ctx,
@@ -391,21 +394,16 @@
/*** Absolute loads from packet header/data ***/
case BPF_S_LD_W_ABS:
- func = sk_load_word;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_word);
goto common_load;
case BPF_S_LD_H_ABS:
- func = sk_load_half;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_half);
goto common_load;
case BPF_S_LD_B_ABS:
- func = sk_load_byte;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
common_load:
- /*
- * Load from [K]. Reference with the (negative)
- * SKF_NET_OFF/SKF_LL_OFF offsets is unsupported.
- */
+ /* Load from [K]. */
ctx->seen |= SEEN_DATAREF;
- if ((int)K < 0)
- return -ENOTSUPP;
PPC_LI64(r_scratch1, func);
PPC_MTLR(r_scratch1);
PPC_LI32(r_addr, K);
@@ -429,7 +427,7 @@
common_load_ind:
/*
* Load from [X + K]. Negative offsets are tested for
- * in the helper functions, and result in a 'ret 0'.
+ * in the helper functions.
*/
ctx->seen |= SEEN_DATAREF | SEEN_XREG;
PPC_LI64(r_scratch1, func);
@@ -443,13 +441,7 @@
break;
case BPF_S_LDX_B_MSH:
- /*
- * x86 version drops packet (RET 0) when K<0, whereas
- * interpreter does allow K<0 (__load_pointer, special
- * ancillary data). common_load returns ENOTSUPP if K<0,
- * so we fall back to interpreter & filter works.
- */
- func = sk_load_byte_msh;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
goto common_load;
break;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index bfb11e0..e2d401a 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -93,7 +93,7 @@
};
/* MPC5200 device tree match tables */
-const struct of_device_id mpc52xx_pci_ids[] __initdata = {
+const struct of_device_id mpc52xx_pci_ids[] __initconst = {
{ .type = "pci", .compatible = "fsl,mpc5200-pci", },
{ .type = "pci", .compatible = "mpc5200-pci", },
{}
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 9fef530..67dac22 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -21,6 +21,12 @@
{ .compatible = "fsl,qe", },
{ .compatible = "fsl,cpm2", },
{ .compatible = "fsl,srio", },
+ /* So that the DMA channel nodes can be probed individually: */
+ { .compatible = "fsl,eloplus-dma", },
+ /* For the PMC driver */
+ { .compatible = "fsl,mpc8548-guts", },
+ /* Probably unnecessary? */
+ { .compatible = "gpio-leds", },
{},
};
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 3754ddc..d208ebc 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -270,7 +270,7 @@
if (machine_is(p1021_mds)) {
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
np = of_find_node_by_name(NULL, "global-utilities");
if (np) {
@@ -399,12 +399,6 @@
machine_arch_initcall(mpc8568_mds, board_fixups);
machine_arch_initcall(mpc8569_mds, board_fixups);
-static struct of_device_id mpc85xx_ids[] = {
- { .compatible = "fsl,mpc8548-guts", },
- { .compatible = "gpio-leds", },
- {},
-};
-
static int __init mpc85xx_publish_devices(void)
{
if (machine_is(mpc8568_mds))
@@ -412,10 +406,7 @@
if (machine_is(mpc8569_mds))
simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio");
- mpc85xx_common_publish_devices();
- of_platform_bus_probe(NULL, mpc85xx_ids, NULL);
-
- return 0;
+ return mpc85xx_common_publish_devices();
}
machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices);
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
index 9848f9e..313fce4 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c
@@ -127,7 +127,7 @@
#if defined(CONFIG_UCC_GETH) || defined(CONFIG_SERIAL_QE)
if (machine_is(p1025_rdb)) {
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
np = of_find_node_by_name(NULL, "global-utilities");
if (np) {
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 0fe88e3..f700c81 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -150,7 +150,7 @@
{
struct device_node *guts_node;
struct device_node *indirect_node = NULL;
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
u8 __iomem *lbc_lcs0_ba = NULL;
u8 __iomem *lbc_lcs1_ba = NULL;
u8 b;
@@ -269,7 +269,7 @@
void p1022ds_set_pixel_clock(unsigned int pixclock)
{
struct device_node *guts_np = NULL;
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
unsigned long freq;
u64 temp;
u32 pxclk;
@@ -460,18 +460,7 @@
pr_info("Freescale P1022 DS reference board\n");
}
-static struct of_device_id __initdata p1022_ds_ids[] = {
- /* So that the DMA channel nodes can be probed individually: */
- { .compatible = "fsl,eloplus-dma", },
- {},
-};
-
-static int __init p1022_ds_publish_devices(void)
-{
- mpc85xx_common_publish_devices();
- return of_platform_bus_probe(NULL, p1022_ds_ids, NULL);
-}
-machine_device_initcall(p1022_ds, p1022_ds_publish_devices);
+machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices);
machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
index bbc6152..62cd3c5 100644
--- a/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
+++ b/arch/powerpc/platforms/86xx/mpc8610_hpcd.c
@@ -225,7 +225,7 @@
void mpc8610hpcd_set_pixel_clock(unsigned int pixclock)
{
struct device_node *guts_np = NULL;
- struct ccsr_guts_86xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
unsigned long freq;
u64 temp;
u32 pxclk;
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c
index db360fc..85825b5 100644
--- a/arch/powerpc/platforms/cell/axon_msi.c
+++ b/arch/powerpc/platforms/cell/axon_msi.c
@@ -114,7 +114,7 @@
pr_devel("axon_msi: woff %x roff %x msi %x\n",
write_offset, msic->read_offset, msi);
- if (msi < NR_IRQS && irq_get_chip_data(msi) == msic) {
+ if (msi < nr_irqs && irq_get_chip_data(msi) == msic) {
generic_handle_irq(msi);
msic->fifo_virt[idx] = cpu_to_le32(0xffffffff);
} else {
@@ -276,9 +276,6 @@
if (rc)
return rc;
- /* We rely on being able to stash a virq in a u16 */
- BUILD_BUG_ON(NR_IRQS > 65536);
-
list_for_each_entry(entry, &dev->msi_list, list) {
virq = irq_create_direct_mapping(msic->irq_domain);
if (virq == NO_IRQ) {
@@ -392,7 +389,8 @@
}
memset(msic->fifo_virt, 0xff, MSIC_FIFO_SIZE_BYTES);
- msic->irq_domain = irq_domain_add_nomap(dn, &msic_host_ops, msic);
+ /* We rely on being able to stash a virq in a u16, so limit irqs to < 65536 */
+ msic->irq_domain = irq_domain_add_nomap(dn, 65536, &msic_host_ops, msic);
if (!msic->irq_domain) {
printk(KERN_ERR "axon_msi: couldn't allocate irq_domain for %s\n",
dn->full_name);
diff --git a/arch/powerpc/platforms/cell/beat_interrupt.c b/arch/powerpc/platforms/cell/beat_interrupt.c
index e5c3a2c..8c6dc42 100644
--- a/arch/powerpc/platforms/cell/beat_interrupt.c
+++ b/arch/powerpc/platforms/cell/beat_interrupt.c
@@ -239,7 +239,7 @@
ppc_md.get_irq = beatic_get_irq;
/* Allocate an irq host */
- beatic_host = irq_domain_add_nomap(NULL, &beatic_pic_host_ops, NULL);
+ beatic_host = irq_domain_add_nomap(NULL, 0, &beatic_pic_host_ops, NULL);
BUG_ON(beatic_host == NULL);
irq_set_default_host(beatic_host);
}
@@ -248,6 +248,6 @@
{
int i;
- for (i = 1; i < NR_IRQS; i++)
+ for (i = 1; i < nr_irqs; i++)
beat_destruct_irq_plug(i);
}
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index ae9fc7b..b9f509a 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -564,7 +564,8 @@
/* A coherent allocation implies strong ordering */
static void *dma_fixed_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
if (iommu_fixed_is_weak)
return iommu_alloc_coherent(dev, cell_get_iommu_table(dev),
@@ -572,18 +573,19 @@
device_to_mask(dev), flag,
dev_to_node(dev));
else
- return dma_direct_ops.alloc_coherent(dev, size, dma_handle,
- flag);
+ return dma_direct_ops.alloc(dev, size, dma_handle, flag,
+ attrs);
}
static void dma_fixed_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
if (iommu_fixed_is_weak)
iommu_free_coherent(cell_get_iommu_table(dev), size, vaddr,
dma_handle);
else
- dma_direct_ops.free_coherent(dev, size, vaddr, dma_handle);
+ dma_direct_ops.free(dev, size, vaddr, dma_handle, attrs);
}
static dma_addr_t dma_fixed_map_page(struct device *dev, struct page *page,
@@ -642,8 +644,8 @@
static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
struct dma_map_ops dma_iommu_fixed_ops = {
- .alloc_coherent = dma_fixed_alloc_coherent,
- .free_coherent = dma_fixed_free_coherent,
+ .alloc = dma_fixed_alloc_coherent,
+ .free = dma_fixed_free_coherent,
.map_sg = dma_fixed_map_sg,
.unmap_sg = dma_fixed_unmap_sg,
.dma_supported = dma_fixed_dma_supported,
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c
index 7f9b674..6e3409d 100644
--- a/arch/powerpc/platforms/cell/qpace_setup.c
+++ b/arch/powerpc/platforms/cell/qpace_setup.c
@@ -61,7 +61,7 @@
printk("*** %04x : %s\n", hex, s ? s : "");
}
-static const struct of_device_id qpace_bus_ids[] __initdata = {
+static const struct of_device_id qpace_bus_ids[] __initconst = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .type = "spider", },
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index fa3e294..4ab0876 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -140,7 +140,7 @@
return 0;
}
-static const struct of_device_id cell_bus_ids[] __initdata = {
+static const struct of_device_id cell_bus_ids[] __initconst = {
{ .type = "soc", },
{ .compatible = "soc", },
{ .type = "spider", },
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 996c5ff..03685a3 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -366,11 +366,20 @@
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
+
+ /*
+ * If the timer is pending, that means we raced with the
+ * irq, in which case we just return
+ */
+ if (timer_pending(&host->timeout_timer))
+ goto skip;
+
kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr));
if (host->state != state_idle) {
host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT;
add_timer(&host->timeout_timer);
}
+ skip:
spin_unlock_irqrestore(&host->lock, flags);
}
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c
index 66ad93d..c4e6305 100644
--- a/arch/powerpc/platforms/powermac/pic.c
+++ b/arch/powerpc/platforms/powermac/pic.c
@@ -57,9 +57,9 @@
static DEFINE_RAW_SPINLOCK(pmac_pic_lock);
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-static unsigned long ppc_lost_interrupts[NR_MASK_WORDS];
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+/* The max irq number this driver deals with is 128; see max_irqs */
+static DECLARE_BITMAP(ppc_lost_interrupts, 128);
+static DECLARE_BITMAP(ppc_cached_irq_mask, 128);
static int pmac_irq_cascade = -1;
static struct irq_domain *pmac_pic_host;
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index a81e5a8..b4ddaa3 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -192,7 +192,7 @@
{
int rc = -ENOMEM;
- psurge_host = irq_domain_add_nomap(NULL, &psurge_host_ops, NULL);
+ psurge_host = irq_domain_add_nomap(NULL, 0, &psurge_host_ops, NULL);
if (psurge_host)
psurge_secondary_virq = irq_create_direct_mapping(psurge_host);
diff --git a/arch/powerpc/platforms/ps3/interrupt.c b/arch/powerpc/platforms/ps3/interrupt.c
index 2a4ff86..5f3b232 100644
--- a/arch/powerpc/platforms/ps3/interrupt.c
+++ b/arch/powerpc/platforms/ps3/interrupt.c
@@ -753,9 +753,8 @@
unsigned cpu;
struct irq_domain *host;
- host = irq_domain_add_nomap(NULL, &ps3_host_ops, NULL);
+ host = irq_domain_add_nomap(NULL, PS3_PLUG_MAX + 1, &ps3_host_ops, NULL);
irq_set_default_host(host);
- irq_set_virq_count(PS3_PLUG_MAX + 1);
for_each_possible_cpu(cpu) {
struct ps3_private *pd = &per_cpu(ps3_private, cpu);
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 880eb9c..5606fe3 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -515,7 +515,8 @@
* to the dma address (mapping) of the first page.
*/
static void * ps3_alloc_coherent(struct device *_dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
int result;
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -552,7 +553,7 @@
}
static void ps3_free_coherent(struct device *_dev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev);
@@ -701,8 +702,8 @@
}
static struct dma_map_ops ps3_sb_dma_ops = {
- .alloc_coherent = ps3_alloc_coherent,
- .free_coherent = ps3_free_coherent,
+ .alloc = ps3_alloc_coherent,
+ .free = ps3_free_coherent,
.map_sg = ps3_sb_map_sg,
.unmap_sg = ps3_sb_unmap_sg,
.dma_supported = ps3_dma_supported,
@@ -712,8 +713,8 @@
};
static struct dma_map_ops ps3_ioc0_dma_ops = {
- .alloc_coherent = ps3_alloc_coherent,
- .free_coherent = ps3_free_coherent,
+ .alloc = ps3_alloc_coherent,
+ .free = ps3_free_coherent,
.map_sg = ps3_ioc0_map_sg,
.unmap_sg = ps3_ioc0_unmap_sg,
.dma_supported = ps3_dma_supported,
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index aadbe4f..178a5f3 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -30,9 +30,9 @@
two or more partitions.
config EEH
- bool "PCI Extended Error Handling (EEH)" if EXPERT
+ bool
depends on PPC_PSERIES && PCI
- default y if !EXPERT
+ default y
config PSERIES_MSI
bool
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 309d38e..a75e37d 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -1076,7 +1076,7 @@
pr_debug("EEH: Adding device %s\n", pci_name(dev));
dn = pci_device_to_OF_node(dev);
- edev = pci_dev_to_eeh_dev(dev);
+ edev = of_node_to_eeh_dev(dn);
if (edev->pdev == dev) {
pr_debug("EEH: Already referenced !\n");
return;
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c
index 4a47525..4cb375c 100644
--- a/arch/powerpc/platforms/pseries/eeh_event.c
+++ b/arch/powerpc/platforms/pseries/eeh_event.c
@@ -59,8 +59,7 @@
struct eeh_event *event;
struct eeh_dev *edev;
- daemonize("eehd");
- set_current_state(TASK_INTERRUPTIBLE);
+ set_task_comm(current, "eehd");
spin_lock_irqsave(&eeh_eventlist_lock, flags);
event = NULL;
@@ -83,6 +82,7 @@
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
eeh_pci_name(edev->pdev));
+ set_current_state(TASK_INTERRUPTIBLE); /* Don't add to load average */
edev = handle_eeh_events(event);
eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index d3be961..10386b6 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -51,8 +51,7 @@
static intctl_cpm2_t __iomem *cpm2_intctl;
static struct irq_domain *cpm2_pic_host;
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+static unsigned long ppc_cached_irq_mask[2]; /* 2 32-bit registers */
static const u_char irq_to_siureg[] = {
1, 1, 1, 1, 1, 1, 1, 1,
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index d5f5416..b724622 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -18,69 +18,45 @@
extern int cpm_get_irq(struct pt_regs *regs);
static struct irq_domain *mpc8xx_pic_host;
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-static unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
+static unsigned long mpc8xx_cached_irq_mask;
static sysconf8xx_t __iomem *siu_reg;
-int cpm_get_irq(struct pt_regs *regs);
+static inline unsigned long mpc8xx_irqd_to_bit(struct irq_data *d)
+{
+ return 0x80000000 >> irqd_to_hwirq(d);
+}
static void mpc8xx_unmask_irq(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
}
static void mpc8xx_mask_irq(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] &= ~(1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ mpc8xx_cached_irq_mask &= ~mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
}
static void mpc8xx_ack(struct irq_data *d)
{
- int bit;
- unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
- bit = irq_nr & 0x1f;
- out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
+ out_be32(&siu_reg->sc_sipend, mpc8xx_irqd_to_bit(d));
}
static void mpc8xx_end_irq(struct irq_data *d)
{
- int bit, word;
- unsigned int irq_nr = (unsigned int)irqd_to_hwirq(d);
-
- bit = irq_nr & 0x1f;
- word = irq_nr >> 5;
-
- ppc_cached_irq_mask[word] |= (1 << (31-bit));
- out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
+ mpc8xx_cached_irq_mask |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_simask, mpc8xx_cached_irq_mask);
}
static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
- if (flow_type & IRQ_TYPE_EDGE_FALLING) {
- irq_hw_number_t hw = (unsigned int)irqd_to_hwirq(d);
+ /* only external IRQ senses are programmable */
+ if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !(irqd_to_hwirq(d) & 1)) {
unsigned int siel = in_be32(&siu_reg->sc_siel);
-
- /* only external IRQ senses are programmable */
- if ((hw & 1) == 0) {
- siel |= (0x80000000 >> hw);
- out_be32(&siu_reg->sc_siel, siel);
- __irq_set_handler_locked(d->irq, handle_edge_irq);
- }
+ siel |= mpc8xx_irqd_to_bit(d);
+ out_be32(&siu_reg->sc_siel, siel);
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
}
return 0;
}
@@ -132,6 +108,9 @@
IRQ_TYPE_EDGE_FALLING,
};
+ if (intspec[0] > 0x1f)
+ return 0;
+
*out_hwirq = intspec[0];
if (intsize > 1 && intspec[1] < 4)
*out_flags = map_pic_senses[intspec[1]];
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 9ac71eb..395af13 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -604,18 +604,14 @@
}
/* Determine if the linux irq is an IPI */
-static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq)
+static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int src)
{
- unsigned int src = virq_to_hw(irq);
-
return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]);
}
/* Determine if the linux irq is a timer */
-static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq)
+static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int src)
{
- unsigned int src = virq_to_hw(irq);
-
return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]);
}
@@ -876,21 +872,45 @@
if (src >= mpic->num_sources)
return -EINVAL;
- if (flow_type == IRQ_TYPE_NONE)
- if (mpic->senses && src < mpic->senses_count)
- flow_type = mpic->senses[src];
- if (flow_type == IRQ_TYPE_NONE)
- flow_type = IRQ_TYPE_LEVEL_LOW;
+ vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+ /* We don't support "none" type */
+ if (flow_type == IRQ_TYPE_NONE)
+ flow_type = IRQ_TYPE_DEFAULT;
+
+ /* Default: read HW settings */
+ if (flow_type == IRQ_TYPE_DEFAULT) {
+ switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
+ MPIC_INFO(VECPRI_SENSE_MASK))) {
+ case MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE):
+ flow_type = IRQ_TYPE_EDGE_RISING;
+ break;
+ case MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
+ flow_type = IRQ_TYPE_EDGE_FALLING;
+ break;
+ case MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE):
+ flow_type = IRQ_TYPE_LEVEL_HIGH;
+ break;
+ case MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+ break;
+ }
+ }
+
+ /* Apply to irq desc */
irqd_set_trigger_type(d, flow_type);
+ /* Apply to HW */
if (mpic_is_ht_interrupt(mpic, src))
vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
MPIC_VECPRI_SENSE_EDGE;
else
vecpri = mpic_type_to_vecpri(mpic, flow_type);
- vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
MPIC_INFO(VECPRI_SENSE_MASK));
vnew |= vecpri;
@@ -1026,7 +1046,7 @@
irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
/* Set default irq type */
- irq_set_irq_type(virq, IRQ_TYPE_NONE);
+ irq_set_irq_type(virq, IRQ_TYPE_DEFAULT);
/* If the MPIC was reset, then all vectors have already been
* initialized. Otherwise, a per source lazy initialization
@@ -1417,12 +1437,6 @@
mpic->num_sources = isu_first + mpic->isu_size;
}
-void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
-{
- mpic->senses = senses;
- mpic->senses_count = count;
-}
-
void __init mpic_init(struct mpic *mpic)
{
int i, cpu;
@@ -1555,12 +1569,12 @@
return;
raw_spin_lock_irqsave(&mpic_lock, flags);
- if (mpic_is_ipi(mpic, irq)) {
+ if (mpic_is_ipi(mpic, src)) {
reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) &
~MPIC_VECPRI_PRIORITY_MASK;
mpic_ipi_write(src - mpic->ipi_vecs[0],
reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT));
- } else if (mpic_is_tm(mpic, irq)) {
+ } else if (mpic_is_tm(mpic, src)) {
reg = mpic_tm_read(src - mpic->timer_vecs[0]) &
~MPIC_VECPRI_PRIORITY_MASK;
mpic_tm_write(src - mpic->timer_vecs[0],
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index 6e7fa38..483d8fa 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -27,6 +27,7 @@
static struct mpic_msgr **mpic_msgrs;
static unsigned int mpic_msgr_count;
+static DEFINE_RAW_SPINLOCK(msgrs_lock);
static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value)
{
@@ -56,12 +57,11 @@
if (reg_num >= mpic_msgr_count)
return ERR_PTR(-ENODEV);
- raw_spin_lock_irqsave(&msgr->lock, flags);
- if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) {
- msgr = mpic_msgrs[reg_num];
+ raw_spin_lock_irqsave(&msgrs_lock, flags);
+ msgr = mpic_msgrs[reg_num];
+ if (msgr->in_use == MSGR_FREE)
msgr->in_use = MSGR_INUSE;
- }
- raw_spin_unlock_irqrestore(&msgr->lock, flags);
+ raw_spin_unlock_irqrestore(&msgrs_lock, flags);
return msgr;
}
@@ -228,7 +228,7 @@
reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i;
msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE;
- msgr->mer = msgr->base + MPIC_MSGR_MER_OFFSET;
+ msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET);
msgr->in_use = MSGR_FREE;
msgr->num = i;
raw_spin_lock_init(&msgr->lock);
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index ceb09cb..818e763 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
+ * Copyright (C) 2006-2010 Freescale Semicondutor, Inc. All rights reserved.
*
* Authors: Shlomi Gridish <gridish@freescale.com>
* Li Yang <leoli@freescale.com>
@@ -266,7 +266,19 @@
static void qe_snums_init(void)
{
int i;
- static const u8 snum_init[] = {
+ static const u8 snum_init_76[] = {
+ 0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
+ 0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
+ 0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
+ 0xD8, 0xD9, 0xE8, 0xE9, 0x44, 0x45, 0x4C, 0x4D,
+ 0x54, 0x55, 0x5C, 0x5D, 0x64, 0x65, 0x6C, 0x6D,
+ 0x74, 0x75, 0x7C, 0x7D, 0x84, 0x85, 0x8C, 0x8D,
+ 0x94, 0x95, 0x9C, 0x9D, 0xA4, 0xA5, 0xAC, 0xAD,
+ 0xB4, 0xB5, 0xBC, 0xBD, 0xC4, 0xC5, 0xCC, 0xCD,
+ 0xD4, 0xD5, 0xDC, 0xDD, 0xE4, 0xE5, 0xEC, 0xED,
+ 0xF4, 0xF5, 0xFC, 0xFD,
+ };
+ static const u8 snum_init_46[] = {
0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
@@ -274,9 +286,15 @@
0x28, 0x29, 0x38, 0x39, 0x48, 0x49, 0x58, 0x59,
0x68, 0x69, 0x78, 0x79, 0x80, 0x81,
};
+ static const u8 *snum_init;
qe_num_of_snum = qe_get_num_of_snums();
+ if (qe_num_of_snum == 76)
+ snum_init = snum_init_76;
+ else
+ snum_init = snum_init_46;
+
for (i = 0; i < qe_num_of_snum; i++) {
snums[i].num = snum_init[i];
snums[i].state = QE_SNUM_STATE_FREE;
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 49a3ece..702256a 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -22,6 +22,7 @@
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <asm/debug.h>
#include <asm/prom.h>
#include <asm/scom.h>
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c
index ea5e204..cd1d18d 100644
--- a/arch/powerpc/sysdev/xics/xics-common.c
+++ b/arch/powerpc/sysdev/xics/xics-common.c
@@ -188,6 +188,7 @@
{
int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
unsigned int irq, virq;
+ struct irq_desc *desc;
/* If we used to be the default server, move to the new "boot_cpuid" */
if (hw_cpu == xics_default_server)
@@ -202,8 +203,7 @@
/* Allow IPIs again... */
icp_ops->set_priority(DEFAULT_PRIORITY);
- for_each_irq(virq) {
- struct irq_desc *desc;
+ for_each_irq_desc(virq, desc) {
struct irq_chip *chip;
long server;
unsigned long flags;
@@ -212,9 +212,8 @@
/* We can't set affinity on ISA interrupts */
if (virq < NUM_ISA_INTERRUPTS)
continue;
- desc = irq_to_desc(virq);
/* We only need to migrate enabled IRQS */
- if (!desc || !desc->action)
+ if (!desc->action)
continue;
if (desc->irq_data.domain != xics_host)
continue;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 2b7c0fb..9015060 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -90,7 +90,6 @@
select HAVE_KERNEL_XZ
select HAVE_ARCH_MUTEX_CPU_RELAX
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
- select HAVE_RCU_TABLE_FREE if SMP
select ARCH_SAVE_PAGE_KEYS if HIBERNATION
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 6cf8e26..1957a9d 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,8 +1,12 @@
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_AUDIT=y
-CONFIG_RCU_TRACE=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
@@ -14,16 +18,22 @@
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_CGROUP=y
+CONFIG_NAMESPACES=y
CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_EXPERT=y
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLAB=y
CONFIG_PROFILING=y
CONFIG_OPROFILE=y
CONFIG_KPROBES=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_IBM_PARTITION=y
CONFIG_DEFAULT_DEADLINE=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -34,18 +44,15 @@
CONFIG_BINFMT_MISC=m
CONFIG_CMM=m
CONFIG_HZ_100=y
-CONFIG_KEXEC=y
-CONFIG_PM=y
+CONFIG_CRASH_DUMP=y
CONFIG_HIBERNATION=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_NET_KEY=y
-CONFIG_AFIUCV=m
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_INET_LRO is not set
CONFIG_IPV6=y
-CONFIG_NET_SCTPPROBE=m
CONFIG_L2TP=m
CONFIG_L2TP_DEBUGFS=m
CONFIG_VLAN_8021Q=y
@@ -84,15 +91,14 @@
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_ZFCP=y
-CONFIG_ZFCP_DIF=y
CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
CONFIG_BONDING=m
+CONFIG_DUMMY=m
CONFIG_EQUALIZER=m
CONFIG_TUN=m
-CONFIG_NET_ETHERNET=y
CONFIG_VIRTIO_NET=y
CONFIG_RAW_DRIVER=m
+CONFIG_VIRTIO_BALLOON=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -103,27 +109,21 @@
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_IBM_PARTITION=y
-CONFIG_DLM=m
CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
CONFIG_TIMER_STATS=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_LOCK_STAT=y
CONFIG_DEBUG_LOCKDEP=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_NOTIFIERS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_RCU_TRACE=y
CONFIG_KPROBES_SANITY_TEST=y
CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y
CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
CONFIG_LATENCYTOP=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_DEBUG_PAGEALLOC=y
-# CONFIG_FTRACE is not set
+CONFIG_BLK_DEV_IO_TRACE=y
# CONFIG_STRICT_DEVMEM is not set
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m
@@ -173,4 +173,3 @@
CONFIG_CRYPTO_DES_S390=m
CONFIG_CRYPTO_AES_S390=m
CONFIG_CRC7=m
-CONFIG_VIRTIO_BALLOON=y
diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h
index 1e5b27e..2ee66a6 100644
--- a/arch/s390/include/asm/facility.h
+++ b/arch/s390/include/asm/facility.h
@@ -38,12 +38,11 @@
unsigned long nr;
preempt_disable();
- S390_lowcore.stfl_fac_list = 0;
asm volatile(
" .insn s,0xb2b10000,0(0)\n" /* stfl */
"0:\n"
EX_TABLE(0b, 0b)
- : "=m" (S390_lowcore.stfl_fac_list));
+ : "+m" (S390_lowcore.stfl_fac_list));
nr = 4; /* bytes stored by stfl */
memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4);
if (S390_lowcore.stfl_fac_list & 0x01000000) {
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 8eef9b5..78e3041 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -22,10 +22,7 @@
unsigned long *page_table_alloc(struct mm_struct *, unsigned long);
void page_table_free(struct mm_struct *, unsigned long *);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
-void __tlb_remove_table(void *_table);
-#endif
static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
diff --git a/arch/s390/include/asm/swab.h b/arch/s390/include/asm/swab.h
index 6bdee21..a3e4ebb 100644
--- a/arch/s390/include/asm/swab.h
+++ b/arch/s390/include/asm/swab.h
@@ -77,7 +77,7 @@
asm volatile(
#ifndef __s390x__
- " icm %0,2,%O+1(%R1)\n"
+ " icm %0,2,%O1+1(%R1)\n"
" ic %0,%1\n"
: "=&d" (result) : "Q" (*x) : "cc");
#else /* __s390x__ */
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index c687a2c..775a5ee 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -30,14 +30,10 @@
struct mmu_gather {
struct mm_struct *mm;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch *batch;
-#endif
unsigned int fullmm;
- unsigned int need_flush;
};
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch {
struct rcu_head rcu;
unsigned int nr;
@@ -49,7 +45,6 @@
extern void tlb_table_flush(struct mmu_gather *tlb);
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-#endif
static inline void tlb_gather_mmu(struct mmu_gather *tlb,
struct mm_struct *mm,
@@ -57,29 +52,20 @@
{
tlb->mm = mm;
tlb->fullmm = full_mm_flush;
- tlb->need_flush = 0;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->batch = NULL;
-#endif
if (tlb->fullmm)
__tlb_flush_mm(mm);
}
static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{
- if (!tlb->need_flush)
- return;
- tlb->need_flush = 0;
- __tlb_flush_mm(tlb->mm);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb_table_flush(tlb);
-#endif
}
static inline void tlb_finish_mmu(struct mmu_gather *tlb,
unsigned long start, unsigned long end)
{
- tlb_flush_mmu(tlb);
+ tlb_table_flush(tlb);
}
/*
@@ -105,10 +91,8 @@
static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long address)
{
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return page_table_free_rcu(tlb, (unsigned long *) pte);
-#endif
page_table_free(tlb->mm, (unsigned long *) pte);
}
@@ -125,10 +109,8 @@
#ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 31))
return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return tlb_remove_table(tlb, pmd);
-#endif
crst_table_free(tlb->mm, (unsigned long *) pmd);
#endif
}
@@ -146,10 +128,8 @@
#ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 42))
return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return tlb_remove_table(tlb, pud);
-#endif
crst_table_free(tlb->mm, (unsigned long *) pud);
#endif
}
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index c27a072..adccd90 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -474,9 +474,9 @@
stck __LC_LAST_UPDATE_CLOCK
spt 5f-.LPG0(%r13)
mvc __LC_LAST_UPDATE_TIMER(8),5f-.LPG0(%r13)
+ xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
#ifndef CONFIG_MARCH_G5
# check capabilities against MARCH_{G5,Z900,Z990,Z9_109,Z10}
- xc __LC_STFL_FAC_LIST(8),__LC_STFL_FAC_LIST
.insn s,0xb2b10000,__LC_STFL_FAC_LIST # store facility list
tm __LC_STFL_FAC_LIST,0x01 # stfle available ?
jz 0f
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 1c2cdd5..8a22c27 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -118,9 +118,10 @@
"a" (__do_softirq)
: "0", "1", "2", "3", "4", "5", "14",
"cc", "memory" );
- } else
+ } else {
/* We are already on the async stack. */
__do_softirq();
+ }
}
local_irq_restore(flags);
@@ -192,11 +193,12 @@
int index = ext_hash(code);
spin_lock_irqsave(&ext_int_hash_lock, flags);
- list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
+ list_for_each_entry_rcu(p, &ext_int_hash[index], entry) {
if (p->code == code && p->handler == handler) {
list_del_rcu(&p->entry);
kfree_rcu(p, rcu);
}
+ }
spin_unlock_irqrestore(&ext_int_hash_lock, flags);
return 0;
}
@@ -211,9 +213,10 @@
old_regs = set_irq_regs(regs);
irq_enter();
- if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
+ if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) {
/* Serve timer interrupts first. */
clock_comparator_work();
+ }
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
if (ext_code.code != 0x1004)
__get_cpu_var(s390_idle).nohz_delay = 1;
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index 4640508..cb019f4 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -178,7 +178,7 @@
err = lcctl(cpuhw->state);
if (err) {
pr_err("Enabling the performance measuring unit "
- "failed with rc=%lx\n", err);
+ "failed with rc=%x\n", err);
return;
}
@@ -203,7 +203,7 @@
err = lcctl(inactive);
if (err) {
pr_err("Disabling the performance measuring unit "
- "failed with rc=%lx\n", err);
+ "failed with rc=%x\n", err);
return;
}
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 7bb15fc..e1335dc 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -61,21 +61,14 @@
return copied < 0 ? -EFAULT : 0;
}
-/*
- * Copy memory in real mode (kernel to kernel)
- */
-int memcpy_real(void *dest, void *src, size_t count)
+static int __memcpy_real(void *dest, void *src, size_t count)
{
register unsigned long _dest asm("2") = (unsigned long) dest;
register unsigned long _len1 asm("3") = (unsigned long) count;
register unsigned long _src asm("4") = (unsigned long) src;
register unsigned long _len2 asm("5") = (unsigned long) count;
- unsigned long flags;
int rc = -EFAULT;
- if (!count)
- return 0;
- flags = __arch_local_irq_stnsm(0xf8UL);
asm volatile (
"0: mvcle %1,%2,0x0\n"
"1: jo 0b\n"
@@ -86,7 +79,23 @@
"+d" (_len2), "=m" (*((long *) dest))
: "m" (*((long *) src))
: "cc", "memory");
- arch_local_irq_restore(flags);
+ return rc;
+}
+
+/*
+ * Copy memory in real mode (kernel to kernel)
+ */
+int memcpy_real(void *dest, void *src, size_t count)
+{
+ unsigned long flags;
+ int rc;
+
+ if (!count)
+ return 0;
+ local_irq_save(flags);
+ __arch_local_irq_stnsm(0xfbUL);
+ rc = __memcpy_real(dest, src, count);
+ local_irq_restore(flags);
return rc;
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 373adf6..6e765bf 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -678,8 +678,6 @@
}
}
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
-
static void __page_table_free_rcu(void *table, unsigned bit)
{
struct page *page;
@@ -733,7 +731,66 @@
free_pages((unsigned long) table, ALLOC_ORDER);
}
-#endif
+static void tlb_remove_table_smp_sync(void *arg)
+{
+ /* Simply deliver the interrupt */
+}
+
+static void tlb_remove_table_one(void *table)
+{
+ /*
+ * This isn't an RCU grace period and hence the page-tables cannot be
+ * assumed to be actually RCU-freed.
+ *
+ * It is however sufficient for software page-table walkers that rely
+ * on IRQ disabling. See the comment near struct mmu_table_batch.
+ */
+ smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
+ __tlb_remove_table(table);
+}
+
+static void tlb_remove_table_rcu(struct rcu_head *head)
+{
+ struct mmu_table_batch *batch;
+ int i;
+
+ batch = container_of(head, struct mmu_table_batch, rcu);
+
+ for (i = 0; i < batch->nr; i++)
+ __tlb_remove_table(batch->tables[i]);
+
+ free_page((unsigned long)batch);
+}
+
+void tlb_table_flush(struct mmu_gather *tlb)
+{
+ struct mmu_table_batch **batch = &tlb->batch;
+
+ if (*batch) {
+ __tlb_flush_mm(tlb->mm);
+ call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
+ *batch = NULL;
+ }
+}
+
+void tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+ struct mmu_table_batch **batch = &tlb->batch;
+
+ if (*batch == NULL) {
+ *batch = (struct mmu_table_batch *)
+ __get_free_page(GFP_NOWAIT | __GFP_NOWARN);
+ if (*batch == NULL) {
+ __tlb_flush_mm(tlb->mm);
+ tlb_remove_table_one(table);
+ return;
+ }
+ (*batch)->nr = 0;
+ }
+ (*batch)->tables[(*batch)->nr++] = table;
+ if ((*batch)->nr == MAX_TABLE_BATCH)
+ tlb_table_flush(tlb);
+}
/*
* switch on pgstes for its userspace process (for kvm)
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index c1d5a82..5f2bb42 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -61,6 +61,7 @@
config DWARF_UNWINDER
bool "Enable the DWARF unwinder for stacktraces"
select FRAME_POINTER
+ depends on SUPERH32
default n
help
Enabling this option will make stacktraces more accurate, at
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index d879848..d0d6221 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -28,6 +28,7 @@
#include <cpu/sh7785.h>
#include <asm/heartbeat.h>
#include <asm/clock.h>
+#include <asm/bl_bit.h>
/*
* NOTE: This board has 2 physical memory maps.
diff --git a/arch/sh/boards/mach-hp6xx/pm.c b/arch/sh/boards/mach-hp6xx/pm.c
index adc9b4b..8b50cf7 100644
--- a/arch/sh/boards/mach-hp6xx/pm.c
+++ b/arch/sh/boards/mach-hp6xx/pm.c
@@ -14,6 +14,7 @@
#include <linux/gfp.h>
#include <asm/io.h>
#include <asm/hd64461.h>
+#include <asm/bl_bit.h>
#include <mach/hp6xx.h>
#include <cpu/dac.h>
#include <asm/freq.h>
diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c
index b1cb271..67ee956 100644
--- a/arch/sh/drivers/dma/dma-sysfs.c
+++ b/arch/sh/drivers/dma/dma-sysfs.c
@@ -54,7 +54,7 @@
if (unlikely(ret))
return ret;
- return device_create_file(dma_subsys.dev_root, &dev_attr_devices.attr);
+ return device_create_file(dma_subsys.dev_root, &dev_attr_devices);
}
postcore_initcall(dma_subsys_init);
diff --git a/arch/sh/include/asm/atomic.h b/arch/sh/include/asm/atomic.h
index 37f2f4a..f4c1c20 100644
--- a/arch/sh/include/asm/atomic.h
+++ b/arch/sh/include/asm/atomic.h
@@ -11,7 +11,7 @@
#include <linux/types.h>
#include <asm/cmpxchg.h>
-#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+#define ATOMIC_INIT(i) { (i) }
#define atomic_read(v) (*(volatile int *)&(v)->counter)
#define atomic_set(v,i) ((v)->counter = (i))
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index 1a73c3e..8bd965e 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -52,25 +52,31 @@
return dma_addr == 0;
}
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
void *memory;
if (dma_alloc_from_coherent(dev, size, dma_handle, &memory))
return memory;
- if (!ops->alloc_coherent)
+ if (!ops->alloc)
return NULL;
- memory = ops->alloc_coherent(dev, size, dma_handle, gfp);
+ memory = ops->alloc(dev, size, dma_handle, gfp, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
return memory;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -78,14 +84,16 @@
return;
debug_dma_free_coherent(dev, size, vaddr, dma_handle);
- if (ops->free_coherent)
- ops->free_coherent(dev, size, vaddr, dma_handle);
+ if (ops->free)
+ ops->free(dev, size, vaddr, dma_handle, attrs);
}
/* arch/sh/mm/consistent.c */
extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag);
+ dma_addr_t *dma_addr, gfp_t flag,
+ struct dma_attrs *attrs);
extern void dma_generic_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs);
#endif /* __ASM_SH_DMA_MAPPING_H */
diff --git a/arch/sh/kernel/cpu/fpu.c b/arch/sh/kernel/cpu/fpu.c
index 7f1b70c..f8f7af5 100644
--- a/arch/sh/kernel/cpu/fpu.c
+++ b/arch/sh/kernel/cpu/fpu.c
@@ -2,6 +2,7 @@
#include <linux/slab.h>
#include <asm/processor.h>
#include <asm/fpu.h>
+#include <asm/traps.h>
int init_fpu(struct task_struct *tsk)
{
diff --git a/arch/sh/kernel/cpu/sh2a/fpu.c b/arch/sh/kernel/cpu/sh2a/fpu.c
index 488d24e..98bbaa4 100644
--- a/arch/sh/kernel/cpu/sh2a/fpu.c
+++ b/arch/sh/kernel/cpu/sh2a/fpu.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/fpu.h>
+#include <asm/traps.h>
/* The PR (precision) bit in the FP Status Register must be clear when
* an frchg instruction is executed, otherwise the instruction is undefined.
diff --git a/arch/sh/kernel/cpu/sh4/fpu.c b/arch/sh/kernel/cpu/sh4/fpu.c
index e74cd6c..69ab4d3 100644
--- a/arch/sh/kernel/cpu/sh4/fpu.c
+++ b/arch/sh/kernel/cpu/sh4/fpu.c
@@ -16,6 +16,7 @@
#include <cpu/fpu.h>
#include <asm/processor.h>
#include <asm/fpu.h>
+#include <asm/traps.h>
/* The PR (precision) bit in the FP Status Register must be clear when
* an frchg instruction is executed, otherwise the instruction is undefined.
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
index 5853989..04ab5ae 100644
--- a/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
+++ b/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
@@ -113,7 +113,7 @@
CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
/* MSTP32 clocks */
- CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
+ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP004]),
CLKDEV_CON_ID("riic0", &mstp_clks[MSTP000]),
CLKDEV_CON_ID("riic1", &mstp_clks[MSTP000]),
CLKDEV_CON_ID("riic2", &mstp_clks[MSTP000]),
diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c
index a6f95ae..08d27fa 100644
--- a/arch/sh/kernel/cpu/shmobile/pm.c
+++ b/arch/sh/kernel/cpu/shmobile/pm.c
@@ -16,6 +16,7 @@
#include <asm/suspend.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
+#include <asm/bl_bit.h>
/*
* Notifier lists for pre/post sleep notification
diff --git a/arch/sh/kernel/dma-nommu.c b/arch/sh/kernel/dma-nommu.c
index 3c55b87..5b0bfcd 100644
--- a/arch/sh/kernel/dma-nommu.c
+++ b/arch/sh/kernel/dma-nommu.c
@@ -63,8 +63,8 @@
#endif
struct dma_map_ops nommu_dma_ops = {
- .alloc_coherent = dma_generic_alloc_coherent,
- .free_coherent = dma_generic_free_coherent,
+ .alloc = dma_generic_alloc_coherent,
+ .free = dma_generic_free_coherent,
.map_page = nommu_map_page,
.map_sg = nommu_map_sg,
#ifdef CONFIG_DMA_NONCOHERENT
diff --git a/arch/sh/kernel/idle.c b/arch/sh/kernel/idle.c
index 64852ec..ee226e2 100644
--- a/arch/sh/kernel/idle.c
+++ b/arch/sh/kernel/idle.c
@@ -17,8 +17,8 @@
#include <linux/irqflags.h>
#include <linux/smp.h>
#include <linux/cpuidle.h>
-#include <asm/pgalloc.h>
#include <linux/atomic.h>
+#include <asm/pgalloc.h>
#include <asm/smp.h>
#include <asm/bl_bit.h>
diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c
index efb6d39..b117781 100644
--- a/arch/sh/kernel/kgdb.c
+++ b/arch/sh/kernel/kgdb.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <asm/traps.h>
/* Macros for single step instruction identification */
#define OPCODE_BT(op) (((op) & 0xff00) == 0x8900)
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index f72e3a9..94273aa 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -26,6 +26,7 @@
#include <asm/mmu_context.h>
#include <asm/fpu.h>
#include <asm/syscalls.h>
+#include <asm/switch_to.h>
void show_regs(struct pt_regs * regs)
{
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c
index a17a14d..eaebdf6 100644
--- a/arch/sh/kernel/smp.c
+++ b/arch/sh/kernel/smp.c
@@ -27,6 +27,7 @@
#include <asm/smp.h>
#include <asm/cacheflush.h>
#include <asm/sections.h>
+#include <asm/setup.h>
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
int __cpu_logical_map[NR_CPUS]; /* Map logical to physical */
diff --git a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
index 555a64f..23af175 100644
--- a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
+++ b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
@@ -34,6 +34,41 @@
1: .short __NR_rt_sigreturn
.LEND_rt_sigreturn:
.size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+ .previous
.section .eh_frame,"a",@progbits
+.LCIE1:
+ .ualong .LCIE1_end - .LCIE1_start
+.LCIE1_start:
+ .ualong 0 /* CIE ID */
+ .byte 0x1 /* Version number */
+ .string "zRS" /* NUL-terminated augmentation string */
+ .uleb128 0x1 /* Code alignment factor */
+ .sleb128 -4 /* Data alignment factor */
+ .byte 0x11 /* Return address register column */
+ .uleb128 0x1 /* Augmentation length and data */
+ .byte 0x1b /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+ .byte 0xc, 0xf, 0x0 /* DW_CFA_def_cfa: r15 ofs 0 */
+
+ .align 2
+.LCIE1_end:
+
+ .ualong .LFDE0_end-.LFDE0_start /* Length FDE0 */
+.LFDE0_start:
+ .ualong .LFDE0_start-.LCIE1 /* CIE pointer */
+ .ualong .LSTART_sigreturn-. /* PC-relative start address */
+ .ualong .LEND_sigreturn-.LSTART_sigreturn
+ .uleb128 0 /* Augmentation */
+ .align 2
+.LFDE0_end:
+
+ .ualong .LFDE1_end-.LFDE1_start /* Length FDE1 */
+.LFDE1_start:
+ .ualong .LFDE1_start-.LCIE1 /* CIE pointer */
+ .ualong .LSTART_rt_sigreturn-. /* PC-relative start address */
+ .ualong .LEND_rt_sigreturn-.LSTART_rt_sigreturn
+ .uleb128 0 /* Augmentation */
+ .align 2
+.LFDE1_end:
+
.previous
diff --git a/arch/sh/kernel/vsyscall/vsyscall-trapa.S b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
index 3e70f85..0eb74d0 100644
--- a/arch/sh/kernel/vsyscall/vsyscall-trapa.S
+++ b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
@@ -3,37 +3,34 @@
.type __kernel_vsyscall,@function
__kernel_vsyscall:
.LSTART_vsyscall:
- /* XXX: We'll have to do something here once we opt to use the vDSO
- * page for something other than the signal trampoline.. as well as
- * fill out .eh_frame -- PFM. */
+ trapa #0x10
+ nop
.LEND_vsyscall:
.size __kernel_vsyscall,.-.LSTART_vsyscall
+ .previous
.section .eh_frame,"a",@progbits
- .previous
.LCIE:
.ualong .LCIE_end - .LCIE_start
.LCIE_start:
.ualong 0 /* CIE ID */
.byte 0x1 /* Version number */
- .string "zRS" /* NUL-terminated augmentation string */
+ .string "zR" /* NUL-terminated augmentation string */
.uleb128 0x1 /* Code alignment factor */
.sleb128 -4 /* Data alignment factor */
.byte 0x11 /* Return address register column */
- /* Augmentation length and data (none) */
- .byte 0xc /* DW_CFA_def_cfa */
- .uleb128 0xf /* r15 */
- .uleb128 0x0 /* offset 0 */
-
+ .uleb128 0x1 /* Augmentation length and data */
+ .byte 0x1b /* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+ .byte 0xc,0xf,0x0 /* DW_CFA_def_cfa: r15 ofs 0 */
.align 2
.LCIE_end:
.ualong .LFDE_end-.LFDE_start /* Length FDE */
.LFDE_start:
- .ualong .LCIE /* CIE pointer */
- .ualong .LSTART_vsyscall-. /* start address */
+ .ualong .LFDE_start-.LCIE /* CIE pointer */
+ .ualong .LSTART_vsyscall-. /* PC-relative start address */
.ualong .LEND_vsyscall-.LSTART_vsyscall
- .uleb128 0
+ .uleb128 0 /* Augmentation */
.align 2
.LFDE_end:
.previous
diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
index 112fea1..0e52928 100644
--- a/arch/sh/mm/cache-sh4.c
+++ b/arch/sh/mm/cache-sh4.c
@@ -18,6 +18,7 @@
#include <linux/highmem.h>
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
+#include <asm/cache_insns.h>
#include <asm/cacheflush.h>
/*
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index f251b5f..b81d9db 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -33,7 +33,8 @@
fs_initcall(dma_init);
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp)
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
void *ret, *ret_nocache;
int order = get_order(size);
@@ -64,7 +65,8 @@
}
void dma_generic_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
int order = get_order(size);
unsigned long pfn = dma_handle >> PAGE_SHIFT;
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c
index 324eef9..e99b104 100644
--- a/arch/sh/mm/fault_32.c
+++ b/arch/sh/mm/fault_32.c
@@ -86,7 +86,7 @@
pte_t *pte_k;
/* Make sure we are in vmalloc/module/P3 area: */
- if (!(address >= VMALLOC_START && address < P3_ADDR_MAX))
+ if (!(address >= P3SEG && address < P3_ADDR_MAX))
return -1;
/*
diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c
index 75a17f5..0b85dd9 100644
--- a/arch/sh/mm/flush-sh4.c
+++ b/arch/sh/mm/flush-sh4.c
@@ -1,5 +1,6 @@
#include <linux/mm.h>
#include <asm/mmu_context.h>
+#include <asm/cache_insns.h>
#include <asm/cacheflush.h>
#include <asm/traps.h>
diff --git a/arch/sh/mm/sram.c b/arch/sh/mm/sram.c
index bc156ec..2d8fa71 100644
--- a/arch/sh/mm/sram.c
+++ b/arch/sh/mm/sram.c
@@ -9,6 +9,7 @@
*/
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/errno.h>
#include <asm/sram.h>
/*
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
index 8c0e4f7..48a7c65 100644
--- a/arch/sparc/include/asm/dma-mapping.h
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -26,24 +26,30 @@
#include <asm-generic/dma-mapping-common.h>
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
void *cpu_addr;
- cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag);
+ cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
return cpu_addr;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
- ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
}
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 6fa2f79..76e4a52 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -12,8 +12,6 @@
* the SpitFire page tables.
*/
-#include <asm-generic/pgtable-nopud.h>
-
#include <linux/compiler.h>
#include <linux/const.h>
#include <asm/types.h>
@@ -22,6 +20,8 @@
#include <asm/page.h>
#include <asm/processor.h>
+#include <asm-generic/pgtable-nopud.h>
+
/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
* The page copy blockops can use 0x6000000 to 0x8000000.
* The TSB is mapped in the 0x8000000 to 0xa000000 range.
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index fea13c7..b93c2c9 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -1264,4 +1264,4 @@
return vio_register_driver(&ds_driver);
}
-subsys_initcall(ds_init);
+fs_initcall(ds_init);
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 4643d68..070ed14 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -280,7 +280,8 @@
}
static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addrp, gfp_t gfp)
+ dma_addr_t *dma_addrp, gfp_t gfp,
+ struct dma_attrs *attrs)
{
unsigned long flags, order, first_page;
struct iommu *iommu;
@@ -330,7 +331,8 @@
}
static void dma_4u_free_coherent(struct device *dev, size_t size,
- void *cpu, dma_addr_t dvma)
+ void *cpu, dma_addr_t dvma,
+ struct dma_attrs *attrs)
{
struct iommu *iommu;
unsigned long flags, order, npages;
@@ -825,8 +827,8 @@
}
static struct dma_map_ops sun4u_dma_ops = {
- .alloc_coherent = dma_4u_alloc_coherent,
- .free_coherent = dma_4u_free_coherent,
+ .alloc = dma_4u_alloc_coherent,
+ .free = dma_4u_free_coherent,
.map_page = dma_4u_map_page,
.unmap_page = dma_4u_unmap_page,
.map_sg = dma_4u_map_sg,
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index d0479e2..21bd739 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -261,7 +261,8 @@
* CPU may access them without any explicit flushing.
*/
static void *sbus_alloc_coherent(struct device *dev, size_t len,
- dma_addr_t *dma_addrp, gfp_t gfp)
+ dma_addr_t *dma_addrp, gfp_t gfp,
+ struct dma_attrs *attrs)
{
struct platform_device *op = to_platform_device(dev);
unsigned long len_total = PAGE_ALIGN(len);
@@ -315,7 +316,7 @@
}
static void sbus_free_coherent(struct device *dev, size_t n, void *p,
- dma_addr_t ba)
+ dma_addr_t ba, struct dma_attrs *attrs)
{
struct resource *res;
struct page *pgv;
@@ -407,8 +408,8 @@
}
struct dma_map_ops sbus_dma_ops = {
- .alloc_coherent = sbus_alloc_coherent,
- .free_coherent = sbus_free_coherent,
+ .alloc = sbus_alloc_coherent,
+ .free = sbus_free_coherent,
.map_page = sbus_map_page,
.unmap_page = sbus_unmap_page,
.map_sg = sbus_map_sg,
@@ -436,7 +437,8 @@
* hwdev should be valid struct pci_dev pointer for PCI devices.
*/
static void *pci32_alloc_coherent(struct device *dev, size_t len,
- dma_addr_t *pba, gfp_t gfp)
+ dma_addr_t *pba, gfp_t gfp,
+ struct dma_attrs *attrs)
{
unsigned long len_total = PAGE_ALIGN(len);
void *va;
@@ -489,7 +491,7 @@
* past this call are illegal.
*/
static void pci32_free_coherent(struct device *dev, size_t n, void *p,
- dma_addr_t ba)
+ dma_addr_t ba, struct dma_attrs *attrs)
{
struct resource *res;
@@ -645,8 +647,8 @@
}
struct dma_map_ops pci32_dma_ops = {
- .alloc_coherent = pci32_alloc_coherent,
- .free_coherent = pci32_free_coherent,
+ .alloc = pci32_alloc_coherent,
+ .free = pci32_free_coherent,
.map_page = pci32_map_page,
.unmap_page = pci32_unmap_page,
.map_sg = pci32_map_sg,
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index a19c8a0..35e4367 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -104,11 +104,11 @@
{
cpumask_t mask;
- cpus_and(mask, cpu_online_map, *affinity);
- if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
+ cpumask_and(&mask, cpu_online_mask, affinity);
+ if (cpumask_equal(&mask, cpu_online_mask) || cpumask_empty(&mask))
return boot_cpu_id;
else
- return first_cpu(mask);
+ return cpumask_first(&mask);
}
#else
#define irq_choose_cpu(affinity) boot_cpu_id
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index aba6b95..19f5605 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -45,7 +45,6 @@
void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
{
- struct leon_pci_info *info = pbus->sysdata;
struct pci_dev *dev;
int i, has_io, has_mem;
u16 cmd;
@@ -111,18 +110,6 @@
return pci_enable_resources(dev, mask);
}
-struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
-{
- /*
- * Currently the OpenBoot nodes are not connected with the PCI device,
- * this is because the LEON PROM does not create PCI nodes. Eventually
- * this will change and the same approach as pcic.c can be used to
- * match PROM nodes with pci devices.
- */
- return NULL;
-}
-EXPORT_SYMBOL(pci_device_to_OF_node);
-
void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
{
#ifdef CONFIG_PCI_DEBUG
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 1210fde..160cac9 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -23,6 +23,7 @@
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/gfp.h>
+#include <linux/cpu.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -78,6 +79,8 @@
local_flush_tlb_all();
leon_configure_cache_smp();
+ notify_cpu_starting(cpuid);
+
/* Get our local ticker going. */
smp_setup_percpu_timer();
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index af5755d..7661e84 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -128,7 +128,8 @@
}
static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addrp, gfp_t gfp)
+ dma_addr_t *dma_addrp, gfp_t gfp,
+ struct dma_attrs *attrs)
{
unsigned long flags, order, first_page, npages, n;
struct iommu *iommu;
@@ -198,7 +199,7 @@
}
static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
- dma_addr_t dvma)
+ dma_addr_t dvma, struct dma_attrs *attrs)
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
@@ -527,8 +528,8 @@
}
static struct dma_map_ops sun4v_dma_ops = {
- .alloc_coherent = dma_4v_alloc_coherent,
- .free_coherent = dma_4v_free_coherent,
+ .alloc = dma_4v_alloc_coherent,
+ .free = dma_4v_free_coherent,
.map_page = dma_4v_map_page,
.unmap_page = dma_4v_unmap_page,
.map_sg = dma_4v_map_sg,
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 77f1b95e..9171fc2 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -20,11 +20,6 @@
.text
.align 32
-__handle_softirq:
- call do_softirq
- nop
- ba,a,pt %xcc, __handle_softirq_continue
- nop
__handle_preemption:
call schedule
wrpr %g0, RTRAP_PSTATE, %pstate
@@ -89,9 +84,7 @@
cmp %l1, 0
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
- bne,pn %icc, __handle_softirq
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
-__handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4
and %l1, %l4, %l4
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 232df99..3ee51f1 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -566,15 +566,10 @@
SYSCALL_DEFINE2(64_munmap, unsigned long, addr, size_t, len)
{
- long ret;
-
if (invalid_64bit_range(addr, len))
return -EINVAL;
- down_write(¤t->mm->mmap_sem);
- ret = do_munmap(current->mm, addr, len);
- up_write(¤t->mm->mmap_sem);
- return ret;
+ return vm_munmap(addr, len);
}
extern unsigned long do_mremap(unsigned long addr,
diff --git a/arch/sparc/mm/fault_32.c b/arch/sparc/mm/fault_32.c
index 7705c67..df3155a 100644
--- a/arch/sparc/mm/fault_32.c
+++ b/arch/sparc/mm/fault_32.c
@@ -225,6 +225,8 @@
unsigned long g2;
int from_user = !(regs->psr & PSR_PS);
int fault, code;
+ unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+ (write ? FAULT_FLAG_WRITE : 0));
if(text_fault)
address = regs->pc;
@@ -251,6 +253,7 @@
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
+retry:
down_read(&mm->mmap_sem);
/*
@@ -289,7 +292,11 @@
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -297,13 +304,29 @@
goto do_sigbus;
BUG();
}
- if (fault & VM_FAULT_MAJOR) {
- current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
- } else {
- current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR) {
+ current->maj_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
+ 1, regs, address);
+ } else {
+ current->min_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
+ 1, regs, address);
+ }
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /* No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
}
+
up_read(&mm->mmap_sem);
return;
diff --git a/arch/sparc/mm/fault_64.c b/arch/sparc/mm/fault_64.c
index 504c062..1fe0429 100644
--- a/arch/sparc/mm/fault_64.c
+++ b/arch/sparc/mm/fault_64.c
@@ -279,6 +279,7 @@
unsigned int insn = 0;
int si_code, fault_code, fault;
unsigned long address, mm_rss;
+ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
fault_code = get_thread_fault_code();
@@ -333,6 +334,8 @@
insn = get_fault_insn(regs, insn);
goto handle_kernel_fault;
}
+
+retry:
down_read(&mm->mmap_sem);
}
@@ -423,7 +426,12 @@
goto bad_area;
}
- fault = handle_mm_fault(mm, vma, address, (fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
+ flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
+ fault = handle_mm_fault(mm, vma, address, flags);
+
+ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+ return;
+
if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
@@ -431,12 +439,27 @@
goto do_sigbus;
BUG();
}
- if (fault & VM_FAULT_MAJOR) {
- current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
- } else {
- current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
+ if (flags & FAULT_FLAG_ALLOW_RETRY) {
+ if (fault & VM_FAULT_MAJOR) {
+ current->maj_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ,
+ 1, regs, address);
+ } else {
+ current->min_flt++;
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN,
+ 1, regs, address);
+ }
+ if (fault & VM_FAULT_RETRY) {
+ flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+ /* No need to up_read(&mm->mmap_sem) as we would
+ * have already released it in __lock_page_or_retry
+ * in mm/filemap.c.
+ */
+
+ goto retry;
+ }
}
up_read(&mm->mmap_sem);
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 11270ca..96033e2 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -12,7 +12,7 @@
select GENERIC_PENDING_IRQ if SMP
select GENERIC_IRQ_SHOW
select SYS_HYPERVISOR
- select ARCH_HAVE_NMI_SAFE_CMPXCHG if !M386
+ select ARCH_HAVE_NMI_SAFE_CMPXCHG
# FIXME: investigate whether we need/want these options.
# select HAVE_IOREMAP_PROT
@@ -69,6 +69,9 @@
config ARCH_DMA_ADDR_T_64BIT
def_bool y
+config NEED_DMA_MAP_STATE
+ def_bool y
+
config LOCKDEP_SUPPORT
def_bool y
@@ -118,7 +121,7 @@
config ARCH_DEFCONFIG
string
- default "arch/tile/configs/tile_defconfig" if !TILEGX
+ default "arch/tile/configs/tilepro_defconfig" if !TILEGX
default "arch/tile/configs/tilegx_defconfig" if TILEGX
source "init/Kconfig"
@@ -240,6 +243,7 @@
config PAGE_OFFSET
hex
+ depends on !64BIT
default 0xF0000000 if VMSPLIT_3_75G
default 0xE0000000 if VMSPLIT_3_5G
default 0xB0000000 if VMSPLIT_2_75G
diff --git a/arch/tile/Makefile b/arch/tile/Makefile
index 17acce7..9520bc5 100644
--- a/arch/tile/Makefile
+++ b/arch/tile/Makefile
@@ -30,7 +30,8 @@
KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS)
endif
-LIBGCC_PATH := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
+LIBGCC_PATH := \
+ $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
# Provide the path to use for "make defconfig".
KBUILD_DEFCONFIG := $(ARCH)_defconfig
@@ -53,8 +54,6 @@
# See arch/tile/Kbuild for content of core part of the kernel
core-y += arch/tile/
-core-$(CONFIG_KVM) += arch/tile/kvm/
-
ifdef TILERA_ROOT
INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
endif
diff --git a/arch/tile/include/arch/spr_def.h b/arch/tile/include/arch/spr_def.h
index f548efe..d6ba449 100644
--- a/arch/tile/include/arch/spr_def.h
+++ b/arch/tile/include/arch/spr_def.h
@@ -60,8 +60,8 @@
_concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,)
#define SPR_IPI_EVENT_RESET_K \
_concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,)
-#define SPR_IPI_MASK_SET_K \
- _concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_SET_K \
+ _concat4(SPR_IPI_EVENT_SET_, CONFIG_KERNEL_PL,,)
#define INT_IPI_K \
_concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h
index bb696da..f246142 100644
--- a/arch/tile/include/asm/atomic.h
+++ b/arch/tile/include/asm/atomic.h
@@ -17,6 +17,8 @@
#ifndef _ASM_TILE_ATOMIC_H
#define _ASM_TILE_ATOMIC_H
+#include <asm/cmpxchg.h>
+
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
@@ -121,54 +123,6 @@
*/
#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0)
-/* Nonexistent functions intended to cause link errors. */
-extern unsigned long __xchg_called_with_bad_pointer(void);
-extern unsigned long __cmpxchg_called_with_bad_pointer(void);
-
-#define xchg(ptr, x) \
- ({ \
- typeof(*(ptr)) __x; \
- switch (sizeof(*(ptr))) { \
- case 4: \
- __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \
- (atomic_t *)(ptr), \
- (u32)(typeof((x)-(x)))(x)); \
- break; \
- case 8: \
- __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \
- (atomic64_t *)(ptr), \
- (u64)(typeof((x)-(x)))(x)); \
- break; \
- default: \
- __xchg_called_with_bad_pointer(); \
- } \
- __x; \
- })
-
-#define cmpxchg(ptr, o, n) \
- ({ \
- typeof(*(ptr)) __x; \
- switch (sizeof(*(ptr))) { \
- case 4: \
- __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \
- (atomic_t *)(ptr), \
- (u32)(typeof((o)-(o)))(o), \
- (u32)(typeof((n)-(n)))(n)); \
- break; \
- case 8: \
- __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \
- (atomic64_t *)(ptr), \
- (u64)(typeof((o)-(o)))(o), \
- (u64)(typeof((n)-(n)))(n)); \
- break; \
- default: \
- __cmpxchg_called_with_bad_pointer(); \
- } \
- __x; \
- })
-
-#define tas(ptr) (xchg((ptr), 1))
-
#endif /* __ASSEMBLY__ */
#ifndef __tilegx__
diff --git a/arch/tile/include/asm/atomic_32.h b/arch/tile/include/asm/atomic_32.h
index 466dc4a..54d1da8 100644
--- a/arch/tile/include/asm/atomic_32.h
+++ b/arch/tile/include/asm/atomic_32.h
@@ -200,7 +200,7 @@
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as @v was not already @u.
- * Returns the old value of @v.
+ * Returns non-zero if @v was not @u, and zero otherwise.
*/
static inline u64 atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
{
diff --git a/arch/tile/include/asm/bitops_64.h b/arch/tile/include/asm/bitops_64.h
index 58d021a..60b87ee 100644
--- a/arch/tile/include/asm/bitops_64.h
+++ b/arch/tile/include/asm/bitops_64.h
@@ -38,10 +38,10 @@
static inline void change_bit(unsigned nr, volatile unsigned long *addr)
{
- unsigned long old, mask = (1UL << (nr % BITS_PER_LONG));
- long guess, oldval;
+ unsigned long mask = (1UL << (nr % BITS_PER_LONG));
+ unsigned long guess, oldval;
addr += nr / BITS_PER_LONG;
- old = *addr;
+ oldval = *addr;
do {
guess = oldval;
oldval = atomic64_cmpxchg((atomic64_t *)addr,
@@ -85,7 +85,7 @@
volatile unsigned long *addr)
{
unsigned long mask = (1UL << (nr % BITS_PER_LONG));
- long guess, oldval = *addr;
+ unsigned long guess, oldval;
addr += nr / BITS_PER_LONG;
oldval = *addr;
do {
diff --git a/arch/tile/include/asm/cmpxchg.h b/arch/tile/include/asm/cmpxchg.h
new file mode 100644
index 0000000..276f067
--- /dev/null
+++ b/arch/tile/include/asm/cmpxchg.h
@@ -0,0 +1,73 @@
+/*
+ * cmpxchg.h -- forked from asm/atomic.h with this copyright:
+ *
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ * 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, version 2.
+ *
+ * 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, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _ASM_TILE_CMPXCHG_H
+#define _ASM_TILE_CMPXCHG_H
+
+#ifndef __ASSEMBLY__
+
+/* Nonexistent functions intended to cause link errors. */
+extern unsigned long __xchg_called_with_bad_pointer(void);
+extern unsigned long __cmpxchg_called_with_bad_pointer(void);
+
+#define xchg(ptr, x) \
+ ({ \
+ typeof(*(ptr)) __x; \
+ switch (sizeof(*(ptr))) { \
+ case 4: \
+ __x = (typeof(__x))(typeof(__x-__x))atomic_xchg( \
+ (atomic_t *)(ptr), \
+ (u32)(typeof((x)-(x)))(x)); \
+ break; \
+ case 8: \
+ __x = (typeof(__x))(typeof(__x-__x))atomic64_xchg( \
+ (atomic64_t *)(ptr), \
+ (u64)(typeof((x)-(x)))(x)); \
+ break; \
+ default: \
+ __xchg_called_with_bad_pointer(); \
+ } \
+ __x; \
+ })
+
+#define cmpxchg(ptr, o, n) \
+ ({ \
+ typeof(*(ptr)) __x; \
+ switch (sizeof(*(ptr))) { \
+ case 4: \
+ __x = (typeof(__x))(typeof(__x-__x))atomic_cmpxchg( \
+ (atomic_t *)(ptr), \
+ (u32)(typeof((o)-(o)))(o), \
+ (u32)(typeof((n)-(n)))(n)); \
+ break; \
+ case 8: \
+ __x = (typeof(__x))(typeof(__x-__x))atomic64_cmpxchg( \
+ (atomic64_t *)(ptr), \
+ (u64)(typeof((o)-(o)))(o), \
+ (u64)(typeof((n)-(n)))(n)); \
+ break; \
+ default: \
+ __cmpxchg_called_with_bad_pointer(); \
+ } \
+ __x; \
+ })
+
+#define tas(ptr) (xchg((ptr), 1))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_TILE_CMPXCHG_H */
diff --git a/arch/tile/include/asm/irq.h b/arch/tile/include/asm/irq.h
index f80f8ce..33cff9a 100644
--- a/arch/tile/include/asm/irq.h
+++ b/arch/tile/include/asm/irq.h
@@ -21,7 +21,7 @@
#define NR_IRQS 32
/* IRQ numbers used for linux IPIs. */
-#define IRQ_RESCHEDULE 1
+#define IRQ_RESCHEDULE 0
#define irq_canonicalize(irq) (irq)
diff --git a/arch/tile/include/asm/pci.h b/arch/tile/include/asm/pci.h
index 5d5a635..32e6cbe 100644
--- a/arch/tile/include/asm/pci.h
+++ b/arch/tile/include/asm/pci.h
@@ -47,8 +47,8 @@
*/
#define PCI_DMA_BUS_IS_PHYS 1
-int __devinit tile_pci_init(void);
-int __devinit pcibios_init(void);
+int __init tile_pci_init(void);
+int __init pcibios_init(void);
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
diff --git a/arch/tile/include/asm/spinlock_64.h b/arch/tile/include/asm/spinlock_64.h
index 72be590..5f8b6a0 100644
--- a/arch/tile/include/asm/spinlock_64.h
+++ b/arch/tile/include/asm/spinlock_64.h
@@ -137,7 +137,7 @@
static inline void arch_write_unlock(arch_rwlock_t *rw)
{
__insn_mf();
- rw->lock = 0;
+ __insn_exch4(&rw->lock, 0); /* Avoid waiting in the write buffer. */
}
static inline int arch_read_trylock(arch_rwlock_t *rw)
diff --git a/arch/tile/include/asm/stack.h b/arch/tile/include/asm/stack.h
index 4d97a2d..0e9d382a 100644
--- a/arch/tile/include/asm/stack.h
+++ b/arch/tile/include/asm/stack.h
@@ -25,7 +25,6 @@
struct KBacktraceIterator {
BacktraceIterator it;
struct task_struct *task; /* task we are backtracing */
- pte_t *pgtable; /* page table for user space access */
int end; /* iteration complete. */
int new_context; /* new context is starting */
int profile; /* profiling, so stop on async intrpt */
diff --git a/arch/tile/include/asm/traps.h b/arch/tile/include/asm/traps.h
index 5f20f92..e28c3df4 100644
--- a/arch/tile/include/asm/traps.h
+++ b/arch/tile/include/asm/traps.h
@@ -64,7 +64,11 @@
#ifdef __tilegx__
+/* kernel/single_step.c */
void gx_singlestep_handle(struct pt_regs *, int fault_num);
+
+/* kernel/intvec_64.S */
+void fill_ra_stack(void);
#endif
-#endif /* _ASM_TILE_SYSCALLS_H */
+#endif /* _ASM_TILE_TRAPS_H */
diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S
index 431e9ae6..ec91568 100644
--- a/arch/tile/kernel/entry.S
+++ b/arch/tile/kernel/entry.S
@@ -85,6 +85,7 @@
/* Loop forever on a nap during SMP boot. */
STD_ENTRY(smp_nap)
nap
+ nop /* avoid provoking the icache prefetch with a jump */
j smp_nap /* we are not architecturally guaranteed not to exit nap */
jrp lr /* clue in the backtracer */
STD_ENDPROC(smp_nap)
@@ -105,5 +106,6 @@
.global _cpu_idle_nap
_cpu_idle_nap:
nap
+ nop /* avoid provoking the icache prefetch with a jump */
jrp lr
STD_ENDPROC(_cpu_idle)
diff --git a/arch/tile/kernel/intvec_32.S b/arch/tile/kernel/intvec_32.S
index aecc8ed..5d56a1e 100644
--- a/arch/tile/kernel/intvec_32.S
+++ b/arch/tile/kernel/intvec_32.S
@@ -799,6 +799,10 @@
* This routine takes a boolean in r30 indicating if this is an NMI.
* If so, we also expect a boolean in r31 indicating whether to
* re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
*/
STD_ENTRY(interrupt_return)
/* If we're resuming to kernel space, don't check thread flags. */
@@ -1237,7 +1241,10 @@
bzt r30, 1f
jal do_syscall_trace
FEEDBACK_REENTER(handle_syscall)
-1: j .Lresume_userspace /* jump into middle of interrupt_return */
+1: {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Linvalid_syscall:
/* Report an invalid syscall back to the user program */
@@ -1246,7 +1253,10 @@
movei r28, -ENOSYS
}
sw r29, r28
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(handle_syscall)
/* Return the address for oprofile to suppress in backtraces. */
@@ -1262,7 +1272,10 @@
jal sim_notify_fork
jal schedule_tail
FEEDBACK_REENTER(ret_from_fork)
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(ret_from_fork)
/*
@@ -1376,7 +1389,10 @@
jal send_sigtrap /* issue a SIGTRAP */
FEEDBACK_REENTER(handle_ill)
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Ldispatch_normal_ill:
{
diff --git a/arch/tile/kernel/intvec_64.S b/arch/tile/kernel/intvec_64.S
index 79c93e1..49d9d66 100644
--- a/arch/tile/kernel/intvec_64.S
+++ b/arch/tile/kernel/intvec_64.S
@@ -22,6 +22,7 @@
#include <asm/irqflags.h>
#include <asm/asm-offsets.h>
#include <asm/types.h>
+#include <asm/signal.h>
#include <hv/hypervisor.h>
#include <arch/abi.h>
#include <arch/interrupts.h>
@@ -605,6 +606,10 @@
* This routine takes a boolean in r30 indicating if this is an NMI.
* If so, we also expect a boolean in r31 indicating whether to
* re-enable the oprofile interrupts.
+ *
+ * Note that .Lresume_userspace is jumped to directly in several
+ * places, and we need to make sure r30 is set correctly in those
+ * callers as well.
*/
STD_ENTRY(interrupt_return)
/* If we're resuming to kernel space, don't check thread flags. */
@@ -1039,11 +1044,28 @@
/* Do syscall trace again, if requested. */
ld r30, r31
- andi r30, r30, _TIF_SYSCALL_TRACE
- beqzt r30, 1f
+ andi r0, r30, _TIF_SYSCALL_TRACE
+ {
+ andi r0, r30, _TIF_SINGLESTEP
+ beqzt r0, 1f
+ }
jal do_syscall_trace
FEEDBACK_REENTER(handle_syscall)
-1: j .Lresume_userspace /* jump into middle of interrupt_return */
+ andi r0, r30, _TIF_SINGLESTEP
+
+1: beqzt r0, 2f
+
+ /* Single stepping -- notify ptrace. */
+ {
+ movei r0, SIGTRAP
+ jal ptrace_notify
+ }
+ FEEDBACK_REENTER(handle_syscall)
+
+2: {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
.Lcompat_syscall:
/*
@@ -1077,7 +1099,10 @@
movei r28, -ENOSYS
}
st r29, r28
- j .Lresume_userspace /* jump into middle of interrupt_return */
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(handle_syscall)
/* Return the address for oprofile to suppress in backtraces. */
@@ -1093,7 +1118,10 @@
jal sim_notify_fork
jal schedule_tail
FEEDBACK_REENTER(ret_from_fork)
- j .Lresume_userspace
+ {
+ movei r30, 0 /* not an NMI */
+ j .Lresume_userspace /* jump into middle of interrupt_return */
+ }
STD_ENDPROC(ret_from_fork)
/* Various stub interrupt handlers and syscall handlers */
@@ -1156,6 +1184,18 @@
push_extra_callee_saves r0
j do_trap
+/* Fill the return address stack with nonzero entries. */
+STD_ENTRY(fill_ra_stack)
+ {
+ move r0, lr
+ jal 1f
+ }
+1: jal 2f
+2: jal 3f
+3: jal 4f
+4: jrp r0
+ STD_ENDPROC(fill_ra_stack)
+
/* Include .intrpt1 array of interrupt vectors */
.section ".intrpt1", "ax"
@@ -1166,7 +1206,7 @@
#define do_hardwall_trap bad_intr
#endif
- int_hand INT_MEM_ERROR, MEM_ERROR, bad_intr
+ int_hand INT_MEM_ERROR, MEM_ERROR, do_trap
int_hand INT_SINGLE_STEP_3, SINGLE_STEP_3, bad_intr
#if CONFIG_KERNEL_PL == 2
int_hand INT_SINGLE_STEP_2, SINGLE_STEP_2, gx_singlestep_handle
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index b90ab99..98d4769 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -67,6 +67,8 @@
area = __get_vm_area(size, VM_ALLOC, MEM_MODULE_START, MEM_MODULE_END);
if (!area)
goto error;
+ area->nr_pages = npages;
+ area->pages = pages;
if (map_vm_area(area, prot_rwx, &pages)) {
vunmap(area->addr);
diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index a1bb59e..b56d12b 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -141,7 +141,7 @@
*
* Returns the number of controllers discovered.
*/
-int __devinit tile_pci_init(void)
+int __init tile_pci_init(void)
{
int i;
@@ -287,7 +287,7 @@
* The controllers have been set up by the time we get here, by a call to
* tile_pci_init.
*/
-int __devinit pcibios_init(void)
+int __init pcibios_init(void)
{
int i;
diff --git a/arch/tile/kernel/proc.c b/arch/tile/kernel/proc.c
index 7a93270..446a7f5 100644
--- a/arch/tile/kernel/proc.c
+++ b/arch/tile/kernel/proc.c
@@ -146,7 +146,6 @@
},
{}
};
-#endif
static struct ctl_path tile_path[] = {
{ .procname = "tile" },
@@ -155,10 +154,9 @@
static int __init proc_sys_tile_init(void)
{
-#ifndef __tilegx__ /* FIXME: GX: no support for unaligned access yet */
register_sysctl_paths(tile_path, unaligned_table);
-#endif
return 0;
}
arch_initcall(proc_sys_tile_init);
+#endif
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 30caeca..2d5ef61 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -28,6 +28,7 @@
#include <linux/tracehook.h>
#include <linux/signal.h>
#include <asm/stack.h>
+#include <asm/switch_to.h>
#include <asm/homecache.h>
#include <asm/syscalls.h>
#include <asm/traps.h>
@@ -285,7 +286,7 @@
static struct task_struct corrupt = { .comm = "<corrupt>" };
struct task_struct *tsk = current;
if (unlikely((unsigned long)tsk < PAGE_OFFSET ||
- (void *)tsk > high_memory ||
+ (high_memory && (void *)tsk > high_memory) ||
((unsigned long)tsk & (__alignof__(*tsk) - 1)) != 0)) {
pr_err("Corrupt 'current' %p (sp %#lx)\n", tsk, stack_pointer);
tsk = &corrupt;
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 5f85d8b..bff23f4 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -103,13 +103,11 @@
static int __init setup_maxmem(char *str)
{
- long maxmem_mb;
- if (str == NULL || strict_strtol(str, 0, &maxmem_mb) != 0 ||
- maxmem_mb == 0)
+ unsigned long long maxmem;
+ if (str == NULL || (maxmem = memparse(str, NULL)) == 0)
return -EINVAL;
- maxmem_pfn = (maxmem_mb >> (HPAGE_SHIFT - 20)) <<
- (HPAGE_SHIFT - PAGE_SHIFT);
+ maxmem_pfn = (maxmem >> HPAGE_SHIFT) << (HPAGE_SHIFT - PAGE_SHIFT);
pr_info("Forcing RAM used to no more than %dMB\n",
maxmem_pfn >> (20 - PAGE_SHIFT));
return 0;
@@ -119,14 +117,15 @@
static int __init setup_maxnodemem(char *str)
{
char *endp;
- long maxnodemem_mb, node;
+ unsigned long long maxnodemem;
+ long node;
node = str ? simple_strtoul(str, &endp, 0) : INT_MAX;
- if (node >= MAX_NUMNODES || *endp != ':' ||
- strict_strtol(endp+1, 0, &maxnodemem_mb) != 0)
+ if (node >= MAX_NUMNODES || *endp != ':')
return -EINVAL;
- maxnodemem_pfn[node] = (maxnodemem_mb >> (HPAGE_SHIFT - 20)) <<
+ maxnodemem = memparse(endp+1, NULL);
+ maxnodemem_pfn[node] = (maxnodemem >> HPAGE_SHIFT) <<
(HPAGE_SHIFT - PAGE_SHIFT);
pr_info("Forcing RAM used on node %ld to no more than %dMB\n",
node, maxnodemem_pfn[node] >> (20 - PAGE_SHIFT));
@@ -913,6 +912,13 @@
#ifdef CONFIG_BLK_DEV_INITRD
+/*
+ * Note that the kernel can potentially support other compression
+ * techniques than gz, though we don't do so by default. If we ever
+ * decide to do so we can either look for other filename extensions,
+ * or just allow a file with this name to be compressed with an
+ * arbitrary compressor (somewhat counterintuitively).
+ */
static int __initdata set_initramfs_file;
static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
@@ -928,9 +934,9 @@
early_param("initramfs_file", setup_initramfs_file);
/*
- * We look for an additional "initramfs.cpio.gz" file in the hvfs.
+ * We look for an "initramfs.cpio.gz" file in the hvfs.
* If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs after any built-in initramfs_data.
+ * unpacked to the initramfs.
*/
static void __init load_hv_initrd(void)
{
@@ -1100,7 +1106,7 @@
/*
* cpu_cacheable_map lists all the cpus whose caches the hypervisor can
- * flush on our behalf. It is set to cpu_possible_map OR'ed with
+ * flush on our behalf. It is set to cpu_possible_mask OR'ed with
* hash_for_home_map, and it is what should be passed to
* hv_flush_remote() to flush all caches. Note that if there are
* dedicated hypervisor driver tiles that have authorized use of their
@@ -1186,7 +1192,7 @@
sizeof(cpu_lotar_map));
if (rc < 0) {
pr_err("warning: no HV_INQ_TILES_LOTAR; using AVAIL\n");
- cpu_lotar_map = cpu_possible_map;
+ cpu_lotar_map = *cpu_possible_mask;
}
#if CHIP_HAS_CBOX_HOME_MAP()
@@ -1196,9 +1202,9 @@
sizeof(hash_for_home_map));
if (rc < 0)
early_panic("hv_inquire_tiles(HFH_CACHE) failed: rc %d\n", rc);
- cpumask_or(&cpu_cacheable_map, &cpu_possible_map, &hash_for_home_map);
+ cpumask_or(&cpu_cacheable_map, cpu_possible_mask, &hash_for_home_map);
#else
- cpu_cacheable_map = cpu_possible_map;
+ cpu_cacheable_map = *cpu_possible_mask;
#endif
}
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index bc1eb58..89529c9 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -153,6 +153,25 @@
if (((unsigned long)addr % size) == 0)
return bundle;
+ /*
+ * Return SIGBUS with the unaligned address, if requested.
+ * Note that we return SIGBUS even for completely invalid addresses
+ * as long as they are in fact unaligned; this matches what the
+ * tilepro hardware would be doing, if it could provide us with the
+ * actual bad address in an SPR, which it doesn't.
+ */
+ if (unaligned_fixup == 0) {
+ siginfo_t info = {
+ .si_signo = SIGBUS,
+ .si_code = BUS_ADRALN,
+ .si_addr = addr
+ };
+ trace_unhandled_signal("unaligned trap", regs,
+ (unsigned long)addr, SIGBUS);
+ force_sig_info(info.si_signo, &info, current);
+ return (tilepro_bundle_bits) 0;
+ }
+
#ifndef __LITTLE_ENDIAN
# error We assume little-endian representation with copy_xx_user size 2 here
#endif
@@ -192,18 +211,6 @@
return (tile_bundle_bits) 0;
}
- if (unaligned_fixup == 0) {
- siginfo_t info = {
- .si_signo = SIGBUS,
- .si_code = BUS_ADRALN,
- .si_addr = addr
- };
- trace_unhandled_signal("unaligned trap", regs,
- (unsigned long)addr, SIGBUS);
- force_sig_info(info.si_signo, &info, current);
- return (tile_bundle_bits) 0;
- }
-
if (unaligned_printk || unaligned_fixup_count == 0) {
pr_info("Process %d/%s: PC %#lx: Fixup of"
" unaligned %s at %#lx.\n",
@@ -339,12 +346,10 @@
}
/* allocate a cache line of writable, executable memory */
- down_write(¤t->mm->mmap_sem);
- buffer = (void __user *) do_mmap(NULL, 0, 64,
+ buffer = (void __user *) vm_mmap(NULL, 0, 64,
PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
0);
- up_write(¤t->mm->mmap_sem);
if (IS_ERR((void __force *)buffer)) {
kfree(state);
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index a44e103..91da0f7 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -103,7 +103,7 @@
set_cpu_online(smp_processor_id(), 0);
arch_local_irq_disable_all();
for (;;)
- asm("nap");
+ asm("nap; nop");
}
/* This function calls the 'stop' function on all other CPUs in the system. */
@@ -113,6 +113,12 @@
send_IPI_allbutself(MSG_TAG_STOP_CPU);
}
+/* On panic, just wait; we may get an smp_send_stop() later on. */
+void panic_smp_self_stop(void)
+{
+ while (1)
+ asm("nap; nop");
+}
/*
* Dispatch code called from hv_message_intr() for HV_MSG_TILE hv messages.
diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c
index b949edc..172aef7 100644
--- a/arch/tile/kernel/smpboot.c
+++ b/arch/tile/kernel/smpboot.c
@@ -196,6 +196,8 @@
/* This must be done before setting cpu_online_mask */
wmb();
+ notify_cpu_starting(smp_processor_id());
+
/*
* We need to hold call_lock, so there is no inconsistency
* between the time smp_call_function() determines number of
diff --git a/arch/tile/kernel/stack.c b/arch/tile/kernel/stack.c
index 37ee4d0..b2f44c2 100644
--- a/arch/tile/kernel/stack.c
+++ b/arch/tile/kernel/stack.c
@@ -21,10 +21,12 @@
#include <linux/stacktrace.h>
#include <linux/uaccess.h>
#include <linux/mmzone.h>
+#include <linux/dcache.h>
+#include <linux/fs.h>
#include <asm/backtrace.h>
#include <asm/page.h>
-#include <asm/tlbflush.h>
#include <asm/ucontext.h>
+#include <asm/switch_to.h>
#include <asm/sigframe.h>
#include <asm/stack.h>
#include <arch/abi.h>
@@ -44,72 +46,23 @@
return sp >= kstack_base && sp < kstack_base + THREAD_SIZE;
}
-/* Is address valid for reading? */
-static int valid_address(struct KBacktraceIterator *kbt, unsigned long address)
-{
- HV_PTE *l1_pgtable = kbt->pgtable;
- HV_PTE *l2_pgtable;
- unsigned long pfn;
- HV_PTE pte;
- struct page *page;
-
- if (l1_pgtable == NULL)
- return 0; /* can't read user space in other tasks */
-
-#ifdef CONFIG_64BIT
- /* Find the real l1_pgtable by looking in the l0_pgtable. */
- pte = l1_pgtable[HV_L0_INDEX(address)];
- if (!hv_pte_get_present(pte))
- return 0;
- pfn = hv_pte_get_pfn(pte);
- if (pte_huge(pte)) {
- if (!pfn_valid(pfn)) {
- pr_err("L0 huge page has bad pfn %#lx\n", pfn);
- return 0;
- }
- return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
- }
- page = pfn_to_page(pfn);
- BUG_ON(PageHighMem(page)); /* No HIGHMEM on 64-bit. */
- l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
-#endif
- pte = l1_pgtable[HV_L1_INDEX(address)];
- if (!hv_pte_get_present(pte))
- return 0;
- pfn = hv_pte_get_pfn(pte);
- if (pte_huge(pte)) {
- if (!pfn_valid(pfn)) {
- pr_err("huge page has bad pfn %#lx\n", pfn);
- return 0;
- }
- return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
- }
-
- page = pfn_to_page(pfn);
- if (PageHighMem(page)) {
- pr_err("L2 page table not in LOWMEM (%#llx)\n",
- HV_PFN_TO_CPA(pfn));
- return 0;
- }
- l2_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
- pte = l2_pgtable[HV_L2_INDEX(address)];
- return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
-}
-
/* Callback for backtracer; basically a glorified memcpy */
static bool read_memory_func(void *result, unsigned long address,
unsigned int size, void *vkbt)
{
int retval;
struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt;
+
+ if (address == 0)
+ return 0;
if (__kernel_text_address(address)) {
/* OK to read kernel code. */
} else if (address >= PAGE_OFFSET) {
/* We only tolerate kernel-space reads of this task's stack */
if (!in_kernel_stack(kbt, address))
return 0;
- } else if (!valid_address(kbt, address)) {
- return 0; /* invalid user-space address */
+ } else if (!kbt->is_current) {
+ return 0; /* can't read from other user address spaces */
}
pagefault_disable();
retval = __copy_from_user_inatomic(result,
@@ -127,6 +80,8 @@
unsigned long sp = kbt->it.sp;
struct pt_regs *p;
+ if (sp % sizeof(long) != 0)
+ return NULL;
if (!in_kernel_stack(kbt, sp))
return NULL;
if (!in_kernel_stack(kbt, sp + C_ABI_SAVE_AREA_SIZE + PTREGS_SIZE-1))
@@ -169,27 +124,27 @@
}
/* Return a pt_regs pointer for a valid signal handler frame */
-static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt)
+static struct pt_regs *valid_sigframe(struct KBacktraceIterator* kbt,
+ struct rt_sigframe* kframe)
{
BacktraceIterator *b = &kbt->it;
- if (b->pc == VDSO_BASE) {
- struct rt_sigframe *frame;
- unsigned long sigframe_top =
- b->sp + sizeof(struct rt_sigframe) - 1;
- if (!valid_address(kbt, b->sp) ||
- !valid_address(kbt, sigframe_top)) {
- if (kbt->verbose)
- pr_err(" (odd signal: sp %#lx?)\n",
- (unsigned long)(b->sp));
+ if (b->pc == VDSO_BASE && b->sp < PAGE_OFFSET &&
+ b->sp % sizeof(long) == 0) {
+ int retval;
+ pagefault_disable();
+ retval = __copy_from_user_inatomic(
+ kframe, (void __user __force *)b->sp,
+ sizeof(*kframe));
+ pagefault_enable();
+ if (retval != 0 ||
+ (unsigned int)(kframe->info.si_signo) >= _NSIG)
return NULL;
- }
- frame = (struct rt_sigframe *)b->sp;
if (kbt->verbose) {
pr_err(" <received signal %d>\n",
- frame->info.si_signo);
+ kframe->info.si_signo);
}
- return (struct pt_regs *)&frame->uc.uc_mcontext;
+ return (struct pt_regs *)&kframe->uc.uc_mcontext;
}
return NULL;
}
@@ -202,10 +157,11 @@
static int KBacktraceIterator_restart(struct KBacktraceIterator *kbt)
{
struct pt_regs *p;
+ struct rt_sigframe kframe;
p = valid_fault_handler(kbt);
if (p == NULL)
- p = valid_sigframe(kbt);
+ p = valid_sigframe(kbt, &kframe);
if (p == NULL)
return 0;
backtrace_init(&kbt->it, read_memory_func, kbt,
@@ -265,41 +221,19 @@
/*
* Set up callback information. We grab the kernel stack base
- * so we will allow reads of that address range, and if we're
- * asking about the current process we grab the page table
- * so we can check user accesses before trying to read them.
- * We flush the TLB to avoid any weird skew issues.
+ * so we will allow reads of that address range.
*/
- is_current = (t == NULL);
+ is_current = (t == NULL || t == current);
kbt->is_current = is_current;
if (is_current)
t = validate_current();
kbt->task = t;
- kbt->pgtable = NULL;
kbt->verbose = 0; /* override in caller if desired */
kbt->profile = 0; /* override in caller if desired */
kbt->end = KBT_ONGOING;
- kbt->new_context = 0;
- if (is_current) {
- HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
- if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) {
- /*
- * Not just an optimization: this also allows
- * this to work at all before va/pa mappings
- * are set up.
- */
- kbt->pgtable = swapper_pg_dir;
- } else {
- struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa));
- if (!PageHighMem(page))
- kbt->pgtable = __va(pgdir_pa);
- else
- pr_err("page table not in LOWMEM"
- " (%#llx)\n", pgdir_pa);
- }
- local_flush_tlb_all();
+ kbt->new_context = 1;
+ if (is_current)
validate_stack(regs);
- }
if (regs == NULL) {
if (is_current || t->state == TASK_RUNNING) {
@@ -345,6 +279,78 @@
}
EXPORT_SYMBOL(KBacktraceIterator_next);
+static void describe_addr(struct KBacktraceIterator *kbt,
+ unsigned long address,
+ int have_mmap_sem, char *buf, size_t bufsize)
+{
+ struct vm_area_struct *vma;
+ size_t namelen, remaining;
+ unsigned long size, offset, adjust;
+ char *p, *modname;
+ const char *name;
+ int rc;
+
+ /*
+ * Look one byte back for every caller frame (i.e. those that
+ * aren't a new context) so we look up symbol data for the
+ * call itself, not the following instruction, which may be on
+ * a different line (or in a different function).
+ */
+ adjust = !kbt->new_context;
+ address -= adjust;
+
+ if (address >= PAGE_OFFSET) {
+ /* Handle kernel symbols. */
+ BUG_ON(bufsize < KSYM_NAME_LEN);
+ name = kallsyms_lookup(address, &size, &offset,
+ &modname, buf);
+ if (name == NULL) {
+ buf[0] = '\0';
+ return;
+ }
+ namelen = strlen(buf);
+ remaining = (bufsize - 1) - namelen;
+ p = buf + namelen;
+ rc = snprintf(p, remaining, "+%#lx/%#lx ",
+ offset + adjust, size);
+ if (modname && rc < remaining)
+ snprintf(p + rc, remaining - rc, "[%s] ", modname);
+ buf[bufsize-1] = '\0';
+ return;
+ }
+
+ /* If we don't have the mmap_sem, we can't show any more info. */
+ buf[0] = '\0';
+ if (!have_mmap_sem)
+ return;
+
+ /* Find vma info. */
+ vma = find_vma(kbt->task->mm, address);
+ if (vma == NULL || address < vma->vm_start) {
+ snprintf(buf, bufsize, "[unmapped address] ");
+ return;
+ }
+
+ if (vma->vm_file) {
+ char *s;
+ p = d_path(&vma->vm_file->f_path, buf, bufsize);
+ if (IS_ERR(p))
+ p = "?";
+ s = strrchr(p, '/');
+ if (s)
+ p = s+1;
+ } else {
+ p = "anon";
+ }
+
+ /* Generate a string description of the vma info. */
+ namelen = strlen(p);
+ remaining = (bufsize - 1) - namelen;
+ memmove(buf, p, namelen);
+ snprintf(buf + namelen, remaining, "[%lx+%lx] ",
+ vma->vm_start, vma->vm_end - vma->vm_start);
+}
+
/*
* This method wraps the backtracer's more generic support.
* It is only invoked from the architecture-specific code; show_stack()
@@ -353,6 +359,7 @@
void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
{
int i;
+ int have_mmap_sem = 0;
if (headers) {
/*
@@ -369,31 +376,16 @@
kbt->verbose = 1;
i = 0;
for (; !KBacktraceIterator_end(kbt); KBacktraceIterator_next(kbt)) {
- char *modname;
- const char *name;
- unsigned long address = kbt->it.pc;
- unsigned long offset, size;
char namebuf[KSYM_NAME_LEN+100];
+ unsigned long address = kbt->it.pc;
- if (address >= PAGE_OFFSET)
- name = kallsyms_lookup(address, &size, &offset,
- &modname, namebuf);
- else
- name = NULL;
+ /* Try to acquire the mmap_sem as we pass into userspace. */
+ if (address < PAGE_OFFSET && !have_mmap_sem && kbt->task->mm)
+ have_mmap_sem =
+ down_read_trylock(&kbt->task->mm->mmap_sem);
- if (!name)
- namebuf[0] = '\0';
- else {
- size_t namelen = strlen(namebuf);
- size_t remaining = (sizeof(namebuf) - 1) - namelen;
- char *p = namebuf + namelen;
- int rc = snprintf(p, remaining, "+%#lx/%#lx ",
- offset, size);
- if (modname && rc < remaining)
- snprintf(p + rc, remaining - rc,
- "[%s] ", modname);
- namebuf[sizeof(namebuf)-1] = '\0';
- }
+ describe_addr(kbt, address, have_mmap_sem,
+ namebuf, sizeof(namebuf));
pr_err(" frame %d: 0x%lx %s(sp 0x%lx)\n",
i++, address, namebuf, (unsigned long)(kbt->it.sp));
@@ -408,6 +400,8 @@
pr_err("Stack dump stopped; next frame identical to this one\n");
if (headers)
pr_err("Stack dump complete\n");
+ if (have_mmap_sem)
+ up_read(&kbt->task->mm->mmap_sem);
}
EXPORT_SYMBOL(tile_show_stack);
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c
index 2bb6602..73cff81 100644
--- a/arch/tile/kernel/traps.c
+++ b/arch/tile/kernel/traps.c
@@ -200,7 +200,7 @@
{
siginfo_t info = { 0 };
int signo, code;
- unsigned long address;
+ unsigned long address = 0;
bundle_bits instr;
/* Re-enable interrupts. */
@@ -223,6 +223,10 @@
}
switch (fault_num) {
+ case INT_MEM_ERROR:
+ signo = SIGBUS;
+ code = BUS_OBJERR;
+ break;
case INT_ILL:
if (copy_from_user(&instr, (void __user *)regs->pc,
sizeof(instr))) {
@@ -289,7 +293,10 @@
address = regs->pc;
break;
#ifdef __tilegx__
- case INT_ILL_TRANS:
+ case INT_ILL_TRANS: {
+ /* Avoid a hardware erratum with the return address stack. */
+ fill_ra_stack();
+
signo = SIGSEGV;
code = SEGV_MAPERR;
if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
@@ -297,6 +304,7 @@
else
address = 0; /* FIXME: GX: single-step for address */
break;
+ }
#endif
default:
panic("Unexpected do_trap interrupt number %d", fault_num);
@@ -308,7 +316,8 @@
info.si_addr = (void __user *)address;
if (signo == SIGILL)
info.si_trapno = fault_num;
- trace_unhandled_signal("trap", regs, address, signo);
+ if (signo != SIGTRAP)
+ trace_unhandled_signal("trap", regs, address, signo);
force_sig_info(signo, &info, current);
}
diff --git a/arch/tile/lib/Makefile b/arch/tile/lib/Makefile
index 0c26086..985f598 100644
--- a/arch/tile/lib/Makefile
+++ b/arch/tile/lib/Makefile
@@ -7,6 +7,7 @@
strchr_$(BITS).o strlen_$(BITS).o
ifeq ($(CONFIG_TILEGX),y)
+CFLAGS_REMOVE_memcpy_user_64.o = -fno-omit-frame-pointer
lib-y += memcpy_user_64.o
else
lib-y += atomic_32.o atomic_asm_32.o memcpy_tile64.o
diff --git a/arch/tile/lib/cacheflush.c b/arch/tile/lib/cacheflush.c
index 8928aac..db4fb89 100644
--- a/arch/tile/lib/cacheflush.c
+++ b/arch/tile/lib/cacheflush.c
@@ -39,7 +39,21 @@
{
char *p, *base;
size_t step_size, load_count;
+
+ /*
+ * On TILEPro the striping granularity is a fixed 8KB; on
+ * TILE-Gx it is configurable, and we rely on the fact that
+ * the hypervisor always configures maximum striping, so that
+ * bits 9 and 10 of the PA are part of the stripe function, so
+ * every 512 bytes we hit a striping boundary.
+ *
+ */
+#ifdef __tilegx__
+ const unsigned long STRIPE_WIDTH = 512;
+#else
const unsigned long STRIPE_WIDTH = 8192;
+#endif
+
#ifdef __tilegx__
/*
* On TILE-Gx, we must disable the dstream prefetcher before doing
@@ -74,7 +88,7 @@
* memory, that one load would be sufficient, but since we may
* be, we also need to back up to the last load issued to
* another memory controller, which would be the point where
- * we crossed an 8KB boundary (the granularity of striping
+ * we crossed a "striping" boundary (the granularity of striping
* across memory controllers). Keep backing up and doing this
* until we are before the beginning of the buffer, or have
* hit all the controllers.
@@ -88,12 +102,22 @@
* every cache line on a full memory stripe on each
* controller" that we simply do that, to simplify the logic.
*
- * FIXME: See bug 9535 for some issues with this code.
+ * On TILE-Gx the hash-for-home function is much more complex,
+ * with the upshot being we can't readily guarantee we have
+ * hit both entries in the 128-entry AMT that were hit by any
+ * load in the entire range, so we just re-load them all.
+ * With larger buffers, we may want to consider using a hypervisor
+ * trap to issue loads directly to each hash-for-home tile for
+ * each controller (doing it from Linux would trash the TLB).
*/
if (hfh) {
step_size = L2_CACHE_BYTES;
+#ifdef __tilegx__
+ load_count = (size + L2_CACHE_BYTES - 1) / L2_CACHE_BYTES;
+#else
load_count = (STRIPE_WIDTH / L2_CACHE_BYTES) *
(1 << CHIP_LOG_NUM_MSHIMS());
+#endif
} else {
step_size = STRIPE_WIDTH;
load_count = (1 << CHIP_LOG_NUM_MSHIMS());
@@ -109,7 +133,7 @@
/* Figure out how far back we need to go. */
base = p - (step_size * (load_count - 2));
- if ((long)base < (long)buffer)
+ if ((unsigned long)base < (unsigned long)buffer)
base = buffer;
/*
diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c
index 4763b3a..37440ca 100644
--- a/arch/tile/lib/memcpy_user_64.c
+++ b/arch/tile/lib/memcpy_user_64.c
@@ -14,7 +14,13 @@
* Do memcpy(), but trap and return "n" when a load or store faults.
*
* Note: this idiom only works when memcpy() compiles to a leaf function.
- * If "sp" is updated during memcpy, the "jrp lr" will be incorrect.
+ * Here leaf function not only means it does not have calls, but also
+ * requires no stack operations (sp, stack frame pointer) and no
+ * use of callee-saved registers, else "jrp lr" will be incorrect since
+ * unwinding stack frame is bypassed. Since memcpy() is not complex so
+ * these conditions are satisfied here, but we need to be careful when
+ * modifying this file. This is not a clean solution but is the best
+ * one so far.
*
* Also note that we are capturing "n" from the containing scope here.
*/
diff --git a/arch/tile/lib/spinlock_common.h b/arch/tile/lib/spinlock_common.h
index c101098..6ac3750 100644
--- a/arch/tile/lib/spinlock_common.h
+++ b/arch/tile/lib/spinlock_common.h
@@ -60,5 +60,5 @@
loops += __insn_crc32_32(stack_pointer, get_cycles_low()) &
(loops - 1);
- relax(1 << exponent);
+ relax(loops);
}
diff --git a/arch/tile/mm/fault.c b/arch/tile/mm/fault.c
index cba30e9..22e58f5 100644
--- a/arch/tile/mm/fault.c
+++ b/arch/tile/mm/fault.c
@@ -130,7 +130,7 @@
}
/*
- * Handle a fault on the vmalloc or module mapping area
+ * Handle a fault on the vmalloc area.
*/
static inline int vmalloc_fault(pgd_t *pgd, unsigned long address)
{
@@ -203,9 +203,14 @@
* interrupt or a critical region, and must do as little as possible.
* Similarly, we can't use atomic ops here, since we may be handling a
* fault caused by an atomic op access.
+ *
+ * If we find a migrating PTE while we're in an NMI context, and we're
+ * at a PC that has a registered exception handler, we don't wait,
+ * since this thread may (e.g.) have been interrupted while migrating
+ * its own stack, which would then cause us to self-deadlock.
*/
static int handle_migrating_pte(pgd_t *pgd, int fault_num,
- unsigned long address,
+ unsigned long address, unsigned long pc,
int is_kernel_mode, int write)
{
pud_t *pud;
@@ -227,6 +232,8 @@
pte_offset_kernel(pmd, address);
pteval = *pte;
if (pte_migrating(pteval)) {
+ if (in_nmi() && search_exception_tables(pc))
+ return 0;
wait_for_migration(pte);
return 1;
}
@@ -300,7 +307,7 @@
* rather than trying to patch up the existing PTE.
*/
pgd = get_current_pgd();
- if (handle_migrating_pte(pgd, fault_num, address,
+ if (handle_migrating_pte(pgd, fault_num, address, regs->pc,
is_kernel_mode, write))
return 1;
@@ -335,9 +342,12 @@
/*
* If we're trying to touch user-space addresses, we must
* be either at PL0, or else with interrupts enabled in the
- * kernel, so either way we can re-enable interrupts here.
+ * kernel, so either way we can re-enable interrupts here
+ * unless we are doing atomic access to user space with
+ * interrupts disabled.
*/
- local_irq_enable();
+ if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
+ local_irq_enable();
mm = tsk->mm;
@@ -665,7 +675,7 @@
*/
if (fault_num == INT_DTLB_ACCESS)
write = 1;
- if (handle_migrating_pte(pgd, fault_num, address, 1, write))
+ if (handle_migrating_pte(pgd, fault_num, address, pc, 1, write))
return state;
/* Return zero so that we continue on with normal fault handling. */
diff --git a/arch/tile/mm/homecache.c b/arch/tile/mm/homecache.c
index 1cc6ae4..499f737 100644
--- a/arch/tile/mm/homecache.c
+++ b/arch/tile/mm/homecache.c
@@ -394,6 +394,7 @@
return pte_to_home(*virt_to_pte(NULL, kva));
}
}
+EXPORT_SYMBOL(page_home);
void homecache_change_page_home(struct page *page, int order, int home)
{
diff --git a/arch/tile/mm/init.c b/arch/tile/mm/init.c
index 830c490..6a9d20d 100644
--- a/arch/tile/mm/init.c
+++ b/arch/tile/mm/init.c
@@ -254,11 +254,6 @@
return construct_pgprot(PAGE_KERNEL_RO, PAGE_HOME_IMMUTABLE);
}
- /* As a performance optimization, keep the boot init stack here. */
- if (address >= (ulong)&init_thread_union &&
- address < (ulong)&init_thread_union + THREAD_SIZE)
- return construct_pgprot(PAGE_KERNEL, smp_processor_id());
-
#ifndef __tilegx__
#if !ATOMIC_LOCKS_FOUND_VIA_TABLE()
/* Force the atomic_locks[] array page to be hash-for-home. */
@@ -557,6 +552,7 @@
address = MEM_SV_INTRPT;
pmd = get_pmd(pgtables, address);
+ pfn = 0; /* code starts at PA 0 */
if (ktext_small) {
/* Allocate an L2 PTE for the kernel text */
int cpu = 0;
@@ -579,10 +575,15 @@
}
BUG_ON(address != (unsigned long)_stext);
- pfn = 0; /* code starts at PA 0 */
- pte = alloc_pte();
- for (pte_ofs = 0; address < (unsigned long)_einittext;
- pfn++, pte_ofs++, address += PAGE_SIZE) {
+ pte = NULL;
+ for (; address < (unsigned long)_einittext;
+ pfn++, address += PAGE_SIZE) {
+ pte_ofs = pte_index(address);
+ if (pte_ofs == 0) {
+ if (pte)
+ assign_pte(pmd++, pte);
+ pte = alloc_pte();
+ }
if (!ktext_local) {
prot = set_remote_cache_cpu(prot, cpu);
cpu = cpumask_next(cpu, &ktext_mask);
@@ -591,7 +592,8 @@
}
pte[pte_ofs] = pfn_pte(pfn, prot);
}
- assign_pte(pmd, pte);
+ if (pte)
+ assign_pte(pmd, pte);
} else {
pte_t pteval = pfn_pte(0, PAGE_KERNEL_EXEC);
pteval = pte_mkhuge(pteval);
@@ -614,7 +616,9 @@
else
pteval = hv_pte_set_mode(pteval,
HV_PTE_MODE_CACHE_NO_L3);
- *(pte_t *)pmd = pteval;
+ for (; address < (unsigned long)_einittext;
+ pfn += PFN_DOWN(HPAGE_SIZE), address += HPAGE_SIZE)
+ *(pte_t *)(pmd++) = pfn_pte(pfn, pteval);
}
/* Set swapper_pgprot here so it is flushed to memory right away. */
diff --git a/arch/tile/mm/pgtable.c b/arch/tile/mm/pgtable.c
index 8730369..2410aa8 100644
--- a/arch/tile/mm/pgtable.c
+++ b/arch/tile/mm/pgtable.c
@@ -177,14 +177,10 @@
if (!pmd_huge_page(*pmd))
return;
- /*
- * Grab the pgd_lock, since we may need it to walk the pgd_list,
- * and since we need some kind of lock here to avoid races.
- */
- spin_lock_irqsave(&pgd_lock, flags);
+ spin_lock_irqsave(&init_mm.page_table_lock, flags);
if (!pmd_huge_page(*pmd)) {
/* Lost the race to convert the huge page. */
- spin_unlock_irqrestore(&pgd_lock, flags);
+ spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
return;
}
@@ -194,6 +190,7 @@
#ifdef __PAGETABLE_PMD_FOLDED
/* Walk every pgd on the system and update the pmd there. */
+ spin_lock(&pgd_lock);
list_for_each(pos, &pgd_list) {
pmd_t *copy_pmd;
pgd = list_to_pgd(pos) + pgd_index(addr);
@@ -201,6 +198,7 @@
copy_pmd = pmd_offset(pud, addr);
__set_pmd(copy_pmd, *pmd);
}
+ spin_unlock(&pgd_lock);
#endif
/* Tell every cpu to notice the change. */
@@ -208,7 +206,7 @@
cpu_possible_mask, NULL, 0);
/* Hold the lock until the TLB flush is finished to avoid races. */
- spin_unlock_irqrestore(&pgd_lock, flags);
+ spin_unlock_irqrestore(&init_mm.page_table_lock, flags);
}
/*
@@ -217,9 +215,13 @@
* against pageattr.c; it is the unique case in which a valid change
* of kernel pagetables can't be lazily synchronized by vmalloc faults.
* vmalloc faults work because attached pagetables are never freed.
- * The locking scheme was chosen on the basis of manfred's
- * recommendations and having no core impact whatsoever.
- * -- wli
+ *
+ * The lock is always taken with interrupts disabled, unlike on x86
+ * and other platforms, because we need to take the lock in
+ * shatter_huge_page(), which may be called from an interrupt context.
+ * We are not at risk from the tlbflush IPI deadlock that was seen on
+ * x86, since we use the flush_remote() API to have the hypervisor do
+ * the TLB flushes regardless of irq disabling.
*/
DEFINE_SPINLOCK(pgd_lock);
LIST_HEAD(pgd_list);
@@ -469,10 +471,18 @@
void set_pte(pte_t *ptep, pte_t pte)
{
- struct page *page = pfn_to_page(pte_pfn(pte));
-
- /* Update the home of a PTE if necessary */
- pte = pte_set_home(pte, page_home(page));
+ if (pte_present(pte) &&
+ (!CHIP_HAS_MMIO() || hv_pte_get_mode(pte) != HV_PTE_MODE_MMIO)) {
+ /* The PTE actually references physical memory. */
+ unsigned long pfn = pte_pfn(pte);
+ if (pfn_valid(pfn)) {
+ /* Update the home of the PTE from the struct page. */
+ pte = pte_set_home(pte, page_home(pfn_to_page(pfn)));
+ } else if (hv_pte_get_mode(pte) == 0) {
+ /* remap_pfn_range(), etc, must supply PTE mode. */
+ panic("set_pte(): out-of-range PFN and mode 0\n");
+ }
+ }
__set_pte(ptep, pte);
}
diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h
index dc36b22..6673508 100644
--- a/arch/um/drivers/cow.h
+++ b/arch/um/drivers/cow.h
@@ -3,41 +3,6 @@
#include <asm/types.h>
-#if defined(__KERNEL__)
-
-# include <asm/byteorder.h>
-
-# if defined(__BIG_ENDIAN)
-# define ntohll(x) (x)
-# define htonll(x) (x)
-# elif defined(__LITTLE_ENDIAN)
-# define ntohll(x) be64_to_cpu(x)
-# define htonll(x) cpu_to_be64(x)
-# else
-# error "Could not determine byte order"
-# endif
-
-#else
-/* For the definition of ntohl, htonl and __BYTE_ORDER */
-#include <endian.h>
-#include <netinet/in.h>
-#if defined(__BYTE_ORDER)
-
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define ntohll(x) (x)
-# define htonll(x) (x)
-# elif __BYTE_ORDER == __LITTLE_ENDIAN
-# define ntohll(x) bswap_64(x)
-# define htonll(x) bswap_64(x)
-# else
-# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined"
-# endif
-
-#else /* ! defined(__BYTE_ORDER) */
-# error "Could not determine byte order: __BYTE_ORDER not defined"
-#endif
-#endif /* ! defined(__KERNEL__) */
-
extern int init_cow_file(int fd, char *cow_file, char *backing_file,
int sectorsize, int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out);
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 9cbb426..0ee9cc6 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -8,11 +8,10 @@
* that.
*/
#include <unistd.h>
-#include <byteswap.h>
#include <errno.h>
#include <string.h>
#include <arpa/inet.h>
-#include <asm/types.h>
+#include <endian.h>
#include "cow.h"
#include "cow_sys.h"
@@ -214,8 +213,8 @@
"header\n");
goto out;
}
- header->magic = htonl(COW_MAGIC);
- header->version = htonl(COW_VERSION);
+ header->magic = htobe32(COW_MAGIC);
+ header->version = htobe32(COW_VERSION);
err = -EINVAL;
if (strlen(backing_file) > sizeof(header->backing_file) - 1) {
@@ -246,10 +245,10 @@
goto out_free;
}
- header->mtime = htonl(modtime);
- header->size = htonll(*size);
- header->sectorsize = htonl(sectorsize);
- header->alignment = htonl(alignment);
+ header->mtime = htobe32(modtime);
+ header->size = htobe64(*size);
+ header->sectorsize = htobe32(sectorsize);
+ header->alignment = htobe32(alignment);
header->cow_format = COW_BITMAP;
err = cow_write_file(fd, header, sizeof(*header));
@@ -301,8 +300,8 @@
magic = header->v1.magic;
if (magic == COW_MAGIC)
version = header->v1.version;
- else if (magic == ntohl(COW_MAGIC))
- version = ntohl(header->v1.version);
+ else if (magic == be32toh(COW_MAGIC))
+ version = be32toh(header->v1.version);
/* No error printed because the non-COW case comes through here */
else goto out;
@@ -327,9 +326,9 @@
"header\n");
goto out;
}
- *mtime_out = ntohl(header->v2.mtime);
- *size_out = ntohll(header->v2.size);
- *sectorsize_out = ntohl(header->v2.sectorsize);
+ *mtime_out = be32toh(header->v2.mtime);
+ *size_out = be64toh(header->v2.size);
+ *sectorsize_out = be32toh(header->v2.sectorsize);
*bitmap_offset_out = sizeof(header->v2);
*align_out = *sectorsize_out;
file = header->v2.backing_file;
@@ -341,10 +340,10 @@
"header\n");
goto out;
}
- *mtime_out = ntohl(header->v3.mtime);
- *size_out = ntohll(header->v3.size);
- *sectorsize_out = ntohl(header->v3.sectorsize);
- *align_out = ntohl(header->v3.alignment);
+ *mtime_out = be32toh(header->v3.mtime);
+ *size_out = be64toh(header->v3.size);
+ *sectorsize_out = be32toh(header->v3.sectorsize);
+ *align_out = be32toh(header->v3.alignment);
if (*align_out == 0) {
cow_printf("read_cow_header - invalid COW header, "
"align == 0\n");
@@ -366,16 +365,16 @@
* this was used until Dec2005 - 64bits are needed to represent
* 2038+. I.e. we can safely do this truncating cast.
*
- * Additionally, we must use ntohl() instead of ntohll(), since
+ * Additionally, we must use be32toh() instead of be64toh(), since
* the program used to use the former (tested - I got mtime
* mismatch "0 vs whatever").
*
* Ever heard about bug-to-bug-compatibility ? ;-) */
- *mtime_out = (time32_t) ntohl(header->v3_b.mtime);
+ *mtime_out = (time32_t) be32toh(header->v3_b.mtime);
- *size_out = ntohll(header->v3_b.size);
- *sectorsize_out = ntohl(header->v3_b.sectorsize);
- *align_out = ntohl(header->v3_b.alignment);
+ *size_out = be64toh(header->v3_b.size);
+ *sectorsize_out = be32toh(header->v3_b.sectorsize);
+ *align_out = be32toh(header->v3_b.alignment);
if (*align_out == 0) {
cow_printf("read_cow_header - invalid COW header, "
"align == 0\n");
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index e672bd6..43b39d6 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -22,6 +22,7 @@
#include <linux/workqueue.h>
#include <linux/mutex.h>
#include <asm/uaccess.h>
+#include <asm/switch_to.h>
#include "init.h"
#include "irq_kern.h"
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 8419f5c..fff2435 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,3 +1,4 @@
generic-y += bug.h cputime.h device.h emergency-restart.h futex.h hardirq.h
generic-y += hw_irq.h irq_regs.h kdebug.h percpu.h sections.h topology.h xor.h
-generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h
+generic-y += ftrace.h pci.h io.h param.h delay.h mutex.h current.h exec.h
+generic-y += switch_to.h
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 492bc4c..65a1c3d 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -3,9 +3,10 @@
# Licensed under the GPL
#
-CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
- -DELF_ARCH=$(LDS_ELF_ARCH) \
- -DELF_FORMAT=$(LDS_ELF_FORMAT)
+CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \
+ -DELF_ARCH=$(LDS_ELF_ARCH) \
+ -DELF_FORMAT=$(LDS_ELF_FORMAT) \
+ $(LDS_EXTRA)
extra-y := vmlinux.lds
clean-files :=
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index f386d04..2b73ded 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -88,11 +88,8 @@
extern void arch_switch_to(struct task_struct *to);
-void *_switch_to(void *prev, void *next, void *last)
+void *__switch_to(struct task_struct *from, struct task_struct *to)
{
- struct task_struct *from = prev;
- struct task_struct *to = next;
-
to->thread.prev_sched = from;
set_current(to);
@@ -111,7 +108,6 @@
} while (current->thread.saved_task);
return current->thread.prev_sched;
-
}
void interrupt_end(void)
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 4947b31..0a49ef0 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -103,7 +103,6 @@
void uml_setup_stubs(struct mm_struct *mm)
{
- struct page **pages;
int err, ret;
if (!skas_needs_stub)
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 2e9852c..0a9e57e 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -41,7 +41,7 @@
cpu_tasks[0].pid = pid;
cpu_tasks[0].task = current;
#ifdef CONFIG_SMP
- cpu_online_map = cpumask_of_cpu(0);
+ init_cpu_online(get_cpu_mask(0));
#endif
start_kernel();
return 0;
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index 155206a..6f588e1 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -76,7 +76,7 @@
cpu_relax();
notify_cpu_starting(cpu);
- cpu_set(cpu, cpu_online_map);
+ set_cpu_online(cpu, true);
default_idle();
return 0;
}
@@ -110,8 +110,7 @@
for (i = 0; i < ncpus; ++i)
set_cpu_possible(i, true);
- cpu_clear(me, cpu_online_map);
- cpu_set(me, cpu_online_map);
+ set_cpu_online(me, true);
cpu_set(me, cpu_callin_map);
err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
@@ -138,13 +137,13 @@
void smp_prepare_boot_cpu(void)
{
- cpu_set(smp_processor_id(), cpu_online_map);
+ set_cpu_online(smp_processor_id(), true);
}
int __cpu_up(unsigned int cpu)
{
cpu_set(cpu, smp_commenced_mask);
- while (!cpu_isset(cpu, cpu_online_map))
+ while (!cpu_online(cpu))
mb();
return 0;
}
diff --git a/arch/unicore32/include/asm/dma-mapping.h b/arch/unicore32/include/asm/dma-mapping.h
index 9258e59..366460a 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -82,20 +82,26 @@
return 0;
}
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
- return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
+ return dma_ops->alloc(dev, size, dma_handle, flag, attrs);
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
- dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+ dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
}
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c
index bfa9fbb..16c08b2 100644
--- a/arch/unicore32/mm/dma-swiotlb.c
+++ b/arch/unicore32/mm/dma-swiotlb.c
@@ -17,9 +17,23 @@
#include <asm/dma.h>
+static void *unicore_swiotlb_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flags,
+ struct dma_attrs *attrs)
+{
+ return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
+}
+
+static void unicore_swiotlb_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
+{
+ swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
struct dma_map_ops swiotlb_dma_map_ops = {
- .alloc_coherent = swiotlb_alloc_coherent,
- .free_coherent = swiotlb_free_coherent,
+ .alloc = unicore_swiotlb_alloc_coherent,
+ .free = unicore_swiotlb_free_coherent,
.map_sg = swiotlb_map_sg_attrs,
.unmap_sg = swiotlb_unmap_sg_attrs,
.dma_supported = swiotlb_dma_supported,
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1d14cc6b..c9866b0 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -81,7 +81,7 @@
select CLKEVT_I8253
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_IOMAP
- select DCACHE_WORD_ACCESS if !DEBUG_PAGEALLOC
+ select DCACHE_WORD_ACCESS
config INSTRUCTION_DECODER
def_bool (KPROBES || PERF_EVENTS)
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index 968dbe2..41a7237 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -129,6 +129,7 @@
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
# prevent gcc from generating any FP code by mistake
KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
KBUILD_CFLAGS += $(mflags-y)
KBUILD_AFLAGS += $(mflags-y)
diff --git a/arch/x86/Makefile.um b/arch/x86/Makefile.um
index 4be406a..36b62bc 100644
--- a/arch/x86/Makefile.um
+++ b/arch/x86/Makefile.um
@@ -14,6 +14,9 @@
export LDFLAGS
+LDS_EXTRA := -Ui386
+export LDS_EXTRA
+
# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y.
include $(srctree)/arch/x86/Makefile_32.cpu
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index a055993..c85e3ac 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -33,6 +33,9 @@
__HEAD
ENTRY(startup_32)
#ifdef CONFIG_EFI_STUB
+ jmp preferred_addr
+
+ .balign 0x10
/*
* We don't need the return address, so set up the stack so
* efi_main() can find its arugments.
@@ -41,12 +44,17 @@
call efi_main
cmpl $0, %eax
- je preferred_addr
movl %eax, %esi
- call 1f
+ jne 2f
1:
+ /* EFI init failed, so hang. */
+ hlt
+ jmp 1b
+2:
+ call 3f
+3:
popl %eax
- subl $1b, %eax
+ subl $3b, %eax
subl BP_pref_address(%esi), %eax
add BP_code32_start(%esi), %eax
leal preferred_addr(%eax), %eax
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 558d76c..87e03a1 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -200,18 +200,28 @@
* entire text+data+bss and hopefully all of memory.
*/
#ifdef CONFIG_EFI_STUB
- pushq %rsi
+ /*
+ * The entry point for the PE/COFF executable is 0x210, so only
+ * legacy boot loaders will execute this jmp.
+ */
+ jmp preferred_addr
+
+ .org 0x210
mov %rcx, %rdi
mov %rdx, %rsi
call efi_main
- popq %rsi
- cmpq $0,%rax
- je preferred_addr
movq %rax,%rsi
- call 1f
+ cmpq $0,%rax
+ jne 2f
1:
+ /* EFI init failed, so hang. */
+ hlt
+ jmp 1b
+2:
+ call 3f
+3:
popq %rax
- subq $1b, %rax
+ subq $3b, %rax
subq BP_pref_address(%rsi), %rax
add BP_code32_start(%esi), %eax
leaq preferred_addr(%rax), %rax
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
index d3c0b02..fb7117a 100644
--- a/arch/x86/boot/compressed/relocs.c
+++ b/arch/x86/boot/compressed/relocs.c
@@ -403,13 +403,11 @@
for (i = 0; i < ehdr.e_shnum; i++) {
struct section *sec = &secs[i];
char *sym_strtab;
- Elf32_Sym *sh_symtab;
int j;
if (sec->shdr.sh_type != SHT_SYMTAB) {
continue;
}
- sh_symtab = sec->symtab;
sym_strtab = sec->link->strtab;
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
Elf32_Sym *sym;
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index ed54976..24443a3 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -205,8 +205,13 @@
put_unaligned_le32(file_sz, &buf[pe_header + 0x50]);
#ifdef CONFIG_X86_32
- /* Address of entry point */
- put_unaligned_le32(i, &buf[pe_header + 0x28]);
+ /*
+ * Address of entry point.
+ *
+ * The EFI stub entry point is +16 bytes from the start of
+ * the .text section.
+ */
+ put_unaligned_le32(i + 16, &buf[pe_header + 0x28]);
/* .text size */
put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]);
@@ -217,9 +222,11 @@
/*
* Address of entry point. startup_32 is at the beginning and
* the 64-bit entry point (startup_64) is always 512 bytes
- * after.
+ * after. The EFI stub entry point is 16 bytes after that, as
+ * the first instruction allows legacy loaders to jump over
+ * the EFI stub initialisation
*/
- put_unaligned_le32(i + 512, &buf[pe_header + 0x28]);
+ put_unaligned_le32(i + 528, &buf[pe_header + 0x28]);
/* .text size */
put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]);
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index d511d95..07b3a68 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -119,9 +119,7 @@
end = PAGE_ALIGN(end);
if (end <= start)
return;
- down_write(¤t->mm->mmap_sem);
- do_brk(start, end - start);
- up_write(¤t->mm->mmap_sem);
+ vm_brk(start, end - start);
}
#ifdef CORE_DUMP
@@ -296,8 +294,7 @@
/* OK, This is the point of no return */
set_personality(PER_LINUX);
- set_thread_flag(TIF_IA32);
- current->mm->context.ia32_compat = 1;
+ set_personality_ia32(false);
setup_new_exec(bprm);
@@ -332,9 +329,7 @@
pos = 32;
map_size = ex.a_text+ex.a_data;
- down_write(¤t->mm->mmap_sem);
- error = do_brk(text_addr & PAGE_MASK, map_size);
- up_write(¤t->mm->mmap_sem);
+ error = vm_brk(text_addr & PAGE_MASK, map_size);
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
@@ -373,9 +368,7 @@
if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) {
loff_t pos = fd_offset;
- down_write(¤t->mm->mmap_sem);
- do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
- up_write(¤t->mm->mmap_sem);
+ vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
@@ -385,26 +378,22 @@
goto beyond_if;
}
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+ error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
MAP_EXECUTABLE | MAP_32BIT,
fd_offset);
- up_write(¤t->mm->mmap_sem);
if (error != N_TXTADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
}
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+ error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
MAP_EXECUTABLE | MAP_32BIT,
fd_offset + ex.a_text);
- up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
@@ -476,9 +465,7 @@
error_time = jiffies;
}
#endif
- down_write(¤t->mm->mmap_sem);
- do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
- up_write(¤t->mm->mmap_sem);
+ vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
file->f_op->read(file, (char __user *)start_addr,
ex.a_text + ex.a_data, &pos);
@@ -490,12 +477,10 @@
goto out;
}
/* Now use mmap to map the library into memory. */
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+ error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
N_TXTOFF(ex));
- up_write(¤t->mm->mmap_sem);
retval = error;
if (error != start_addr)
goto out;
@@ -503,9 +488,7 @@
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
- down_write(¤t->mm->mmap_sem);
- error = do_brk(start_addr + len, bss - len);
- up_write(¤t->mm->mmap_sem);
+ error = vm_brk(start_addr + len, bss - len);
retval = error;
if (error != start_addr + len)
goto out;
diff --git a/arch/x86/include/asm/cmpxchg.h b/arch/x86/include/asm/cmpxchg.h
index b3b7332..99480e5 100644
--- a/arch/x86/include/asm/cmpxchg.h
+++ b/arch/x86/include/asm/cmpxchg.h
@@ -43,7 +43,7 @@
switch (sizeof(*(ptr))) { \
case __X86_CASE_B: \
asm volatile (lock #op "b %b0, %1\n" \
- : "+r" (__ret), "+m" (*(ptr)) \
+ : "+q" (__ret), "+m" (*(ptr)) \
: : "memory", "cc"); \
break; \
case __X86_CASE_W: \
@@ -173,7 +173,7 @@
switch (sizeof(*(ptr))) { \
case __X86_CASE_B: \
asm volatile (lock "addb %b1, %0\n" \
- : "+m" (*(ptr)) : "ri" (inc) \
+ : "+m" (*(ptr)) : "qi" (inc) \
: "memory", "cc"); \
break; \
case __X86_CASE_W: \
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index ed3065f..4b4331d 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -59,7 +59,8 @@
extern int dma_set_mask(struct device *dev, u64 mask);
extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag);
+ dma_addr_t *dma_addr, gfp_t flag,
+ struct dma_attrs *attrs);
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
@@ -111,9 +112,11 @@
return gfp;
}
+#define dma_alloc_coherent(d,s,h,f) dma_alloc_attrs(d,s,h,f,NULL)
+
static inline void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
- gfp_t gfp)
+dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ gfp_t gfp, struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
void *memory;
@@ -129,18 +132,21 @@
if (!is_device_dma_capable(dev))
return NULL;
- if (!ops->alloc_coherent)
+ if (!ops->alloc)
return NULL;
- memory = ops->alloc_coherent(dev, size, dma_handle,
- dma_alloc_coherent_gfp_flags(dev, gfp));
+ memory = ops->alloc(dev, size, dma_handle,
+ dma_alloc_coherent_gfp_flags(dev, gfp), attrs);
debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
return memory;
}
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t bus)
+#define dma_free_coherent(d,s,c,h) dma_free_attrs(d,s,c,h,NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t bus,
+ struct dma_attrs *attrs)
{
struct dma_map_ops *ops = get_dma_ops(dev);
@@ -150,8 +156,8 @@
return;
debug_dma_free_coherent(dev, size, vaddr, bus);
- if (ops->free_coherent)
- ops->free_coherent(dev, size, vaddr, bus);
+ if (ops->free)
+ ops->free(dev, size, vaddr, bus, attrs);
}
#endif
diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h
index 3427b77..7ef7c30 100644
--- a/arch/x86/include/asm/posix_types.h
+++ b/arch/x86/include/asm/posix_types.h
@@ -7,9 +7,9 @@
#else
# ifdef __i386__
# include "posix_types_32.h"
-# elif defined(__LP64__)
-# include "posix_types_64.h"
-# else
+# elif defined(__ILP32__)
# include "posix_types_x32.h"
+# else
+# include "posix_types_64.h"
# endif
#endif
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 7284c9a..4fa7dcc 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -974,16 +974,6 @@
#define cpu_has_amd_erratum(x) (false)
#endif /* CONFIG_CPU_SUP_AMD */
-#ifdef CONFIG_X86_32
-/*
- * disable hlt during certain critical i/o operations
- */
-#define HAVE_DISABLE_HLT
-#endif
-
-void disable_hlt(void);
-void enable_hlt(void);
-
void cpu_idle_wait(void);
extern unsigned long arch_align_stack(unsigned long sp);
diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h
index 4a08538..5ca71c0 100644
--- a/arch/x86/include/asm/sigcontext.h
+++ b/arch/x86/include/asm/sigcontext.h
@@ -257,7 +257,7 @@
__u64 oldmask;
__u64 cr2;
struct _fpstate __user *fpstate; /* zero when no FPU context */
-#ifndef __LP64__
+#ifdef __ILP32__
__u32 __fpstate_pad;
#endif
__u64 reserved1[8];
diff --git a/arch/x86/include/asm/siginfo.h b/arch/x86/include/asm/siginfo.h
index fc1aa55..34c47b3 100644
--- a/arch/x86/include/asm/siginfo.h
+++ b/arch/x86/include/asm/siginfo.h
@@ -2,7 +2,13 @@
#define _ASM_X86_SIGINFO_H
#ifdef __x86_64__
-# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+# ifdef __ILP32__ /* x32 */
+typedef long long __kernel_si_clock_t __attribute__((aligned(4)));
+# define __ARCH_SI_CLOCK_T __kernel_si_clock_t
+# define __ARCH_SI_ATTRIBUTES __attribute__((aligned(8)))
+# else /* x86-64 */
+# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+# endif
#endif
#include <asm-generic/siginfo.h>
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 8be5f54..e054459 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -557,6 +557,8 @@
extern unsigned long
copy_from_user_nmi(void *to, const void __user *from, unsigned long n);
+extern __must_check long
+strncpy_from_user(char *dst, const char __user *src, long count);
/*
* movsl can be slow when source and dest are not both 8-byte aligned
diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 566e803..8084bc73 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -213,11 +213,6 @@
return n;
}
-long __must_check strncpy_from_user(char *dst, const char __user *src,
- long count);
-long __must_check __strncpy_from_user(char *dst,
- const char __user *src, long count);
-
/**
* strlen_user: - Get the size of a string in user space.
* @str: The string to measure.
diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h
index 1c66d30..fcd4b6f 100644
--- a/arch/x86/include/asm/uaccess_64.h
+++ b/arch/x86/include/asm/uaccess_64.h
@@ -208,10 +208,6 @@
}
}
-__must_check long
-strncpy_from_user(char *dst, const char __user *src, long count);
-__must_check long
-__strncpy_from_user(char *dst, const char __user *src, long count);
__must_check long strnlen_user(const char __user *str, long n);
__must_check long __strnlen_user(const char __user *str, long n);
__must_check long strlen_user(const char __user *str);
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 37cdc9d..4437001 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -63,10 +63,10 @@
#else
# ifdef __i386__
# include <asm/unistd_32.h>
-# elif defined(__LP64__)
-# include <asm/unistd_64.h>
-# else
+# elif defined(__ILP32__)
# include <asm/unistd_x32.h>
+# else
+# include <asm/unistd_64.h>
# endif
#endif
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
new file mode 100644
index 0000000..e58f03b
--- /dev/null
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -0,0 +1,79 @@
+#ifndef _ASM_WORD_AT_A_TIME_H
+#define _ASM_WORD_AT_A_TIME_H
+
+/*
+ * This is largely generic for little-endian machines, but the
+ * optimal byte mask counting is probably going to be something
+ * that is architecture-specific. If you have a reliably fast
+ * bit count instruction, that might be better than the multiply
+ * and shift, for example.
+ */
+
+#ifdef CONFIG_64BIT
+
+/*
+ * Jan Achrenius on G+: microoptimized version of
+ * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
+ * that works for the bytemasks without having to
+ * mask them first.
+ */
+static inline long count_masked_bytes(unsigned long mask)
+{
+ return mask*0x0001020304050608ul >> 56;
+}
+
+#else /* 32-bit case */
+
+/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+static inline long count_masked_bytes(long mask)
+{
+ /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+ long a = (0x0ff0001+mask) >> 23;
+ /* Fix the 1 for 00 case */
+ return a & mask;
+}
+
+#endif
+
+#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
+
+/* Return the high bit set in the first byte that is a zero */
+static inline unsigned long has_zero(unsigned long a)
+{
+ return ((a - REPEAT_BYTE(0x01)) & ~a) & REPEAT_BYTE(0x80);
+}
+
+/*
+ * Load an unaligned word from kernel space.
+ *
+ * In the (very unlikely) case of the word being a page-crosser
+ * and the next page not being mapped, take the exception and
+ * return zeroes in the non-existing part.
+ */
+static inline unsigned long load_unaligned_zeropad(const void *addr)
+{
+ unsigned long ret, dummy;
+
+ asm(
+ "1:\tmov %2,%0\n"
+ "2:\n"
+ ".section .fixup,\"ax\"\n"
+ "3:\t"
+ "lea %2,%1\n\t"
+ "and %3,%1\n\t"
+ "mov (%1),%0\n\t"
+ "leal %2,%%ecx\n\t"
+ "andl %4,%%ecx\n\t"
+ "shll $3,%%ecx\n\t"
+ "shr %%cl,%0\n\t"
+ "jmp 2b\n"
+ ".previous\n"
+ _ASM_EXTABLE(1b, 3b)
+ :"=&r" (ret),"=&c" (dummy)
+ :"m" (*(unsigned long *)addr),
+ "i" (-sizeof(unsigned long)),
+ "i" (sizeof(unsigned long)-1));
+ return ret;
+}
+
+#endif /* _ASM_WORD_AT_A_TIME_H */
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index baaca8d..764b66a 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -195,6 +195,5 @@
extern void x86_init_noop(void);
extern void x86_init_uint_noop(unsigned int unused);
-extern void x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node);
#endif
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 103b6ab..146a49c 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -24,6 +24,10 @@
static char temp_stack[4096];
#endif
+asmlinkage void acpi_enter_s3(void)
+{
+ acpi_enter_sleep_state(3, wake_sleep_flags);
+}
/**
* acpi_suspend_lowlevel - save kernel state
*
diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h
index 416d4be..d68677a 100644
--- a/arch/x86/kernel/acpi/sleep.h
+++ b/arch/x86/kernel/acpi/sleep.h
@@ -3,12 +3,16 @@
*/
#include <asm/trampoline.h>
+#include <linux/linkage.h>
extern unsigned long saved_video_mode;
extern long saved_magic;
extern int wakeup_pmode_return;
+extern u8 wake_sleep_flags;
+extern asmlinkage void acpi_enter_s3(void);
+
extern unsigned long acpi_copy_wakeup_routine(unsigned long);
extern void wakeup_long64(void);
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index 13ab7205..7261083 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -74,9 +74,7 @@
ENTRY(do_suspend_lowlevel)
call save_processor_state
call save_registers
- pushl $3
- call acpi_enter_sleep_state
- addl $4, %esp
+ call acpi_enter_s3
# In case of S3 failure, we'll emerge here. Jump
# to ret_point to recover
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index 8ea5164..014d1d2 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -71,9 +71,7 @@
movq %rsi, saved_rsi
addq $8, %rsp
- movl $3, %edi
- xorl %eax, %eax
- call acpi_enter_sleep_state
+ call acpi_enter_s3
/* in case something went wrong, restore the machine status and go on */
jmp resume_point
diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c
index b1e7c7f..e6631120 100644
--- a/arch/x86/kernel/amd_gart_64.c
+++ b/arch/x86/kernel/amd_gart_64.c
@@ -477,7 +477,7 @@
/* allocate and map a coherent mapping */
static void *
gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,
- gfp_t flag)
+ gfp_t flag, struct dma_attrs *attrs)
{
dma_addr_t paddr;
unsigned long align_mask;
@@ -500,7 +500,8 @@
}
__free_pages(page, get_order(size));
} else
- return dma_generic_alloc_coherent(dev, size, dma_addr, flag);
+ return dma_generic_alloc_coherent(dev, size, dma_addr, flag,
+ attrs);
return NULL;
}
@@ -508,7 +509,7 @@
/* free a coherent mapping */
static void
gart_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr)
+ dma_addr_t dma_addr, struct dma_attrs *attrs)
{
gart_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL, NULL);
free_pages((unsigned long)vaddr, get_order(size));
@@ -700,8 +701,8 @@
.unmap_sg = gart_unmap_sg,
.map_page = gart_map_page,
.unmap_page = gart_unmap_page,
- .alloc_coherent = gart_alloc_coherent,
- .free_coherent = gart_free_coherent,
+ .alloc = gart_alloc_coherent,
+ .free = gart_free_coherent,
.mapping_error = gart_mapping_error,
};
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 11544d8..edc2448 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1637,9 +1637,11 @@
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/* The BIOS may have set up the APIC at some other address */
- rdmsr(MSR_IA32_APICBASE, l, h);
- if (l & MSR_IA32_APICBASE_ENABLE)
- mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ if (l & MSR_IA32_APICBASE_ENABLE)
+ mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+ }
pr_info("Found and enabled local APIC!\n");
return 0;
@@ -1657,13 +1659,15 @@
* MSR. This can only be done in software for Intel P6 or later
* and AMD K7 (Model > 1) or later.
*/
- rdmsr(MSR_IA32_APICBASE, l, h);
- if (!(l & MSR_IA32_APICBASE_ENABLE)) {
- pr_info("Local APIC disabled by BIOS -- reenabling.\n");
- l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | addr;
- wrmsr(MSR_IA32_APICBASE, l, h);
- enabled_via_apicbase = 1;
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+ pr_info("Local APIC disabled by BIOS -- reenabling.\n");
+ l &= ~MSR_IA32_APICBASE_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | addr;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ enabled_via_apicbase = 1;
+ }
}
return apic_verify();
}
@@ -2209,10 +2213,12 @@
* FIXME! This will be wrong if we ever support suspend on
* SMP! We'll need to do this as part of the CPU restore!
*/
- rdmsr(MSR_IA32_APICBASE, l, h);
- l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
- wrmsr(MSR_IA32_APICBASE, l, h);
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ l &= ~MSR_IA32_APICBASE_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ }
}
maxlvt = lapic_get_maxlvt();
diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c
index 899803e..23e75422e 100644
--- a/arch/x86/kernel/apic/apic_numachip.c
+++ b/arch/x86/kernel/apic/apic_numachip.c
@@ -207,8 +207,11 @@
static void fixup_cpu_id(struct cpuinfo_x86 *c, int node)
{
- c->phys_proc_id = node;
- per_cpu(cpu_llc_id, smp_processor_id()) = node;
+
+ if (c->phys_proc_id != node) {
+ c->phys_proc_id = node;
+ per_cpu(cpu_llc_id, smp_processor_id()) = node;
+ }
}
static int __init numachip_system_init(void)
diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 8a778db..991e315 100644
--- a/arch/x86/kernel/apic/x2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -24,6 +24,12 @@
{
if (x2apic_phys)
return x2apic_enabled();
+ else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
+ (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) &&
+ x2apic_enabled()) {
+ printk(KERN_DEBUG "System requires x2apic physical mode\n");
+ return 1;
+ }
else
return 0;
}
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 0a44b90..146bb62 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -26,7 +26,8 @@
* contact AMD for precise details and a CPU swap.
*
* See http://www.multimania.com/poulot/k6bug.html
- * http://www.amd.com/K6/k6docs/revgd.html
+ * and section 2.6.2 of "AMD-K6 Processor Revision Guide - Model 6"
+ * (Publication # 21266 Issue Date: August 1998)
*
* The following test is erm.. interesting. AMD neglected to up
* the chip setting when fixing the bug but they also tweaked some
@@ -94,7 +95,6 @@
"system stability may be impaired when more than 32 MB are used.\n");
else
printk(KERN_CONT "probably OK (after B9730xxxx).\n");
- printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n");
}
/* K6 with old style WHCR */
@@ -353,10 +353,11 @@
node = per_cpu(cpu_llc_id, cpu);
/*
- * If core numbers are inconsistent, it's likely a multi-fabric platform,
- * so invoke platform-specific handler
+ * On multi-fabric platform (e.g. Numascale NumaChip) a
+ * platform-specific handler needs to be called to fixup some
+ * IDs of the CPU.
*/
- if (c->phys_proc_id != node)
+ if (x86_cpuinit.fixup_cpu_id)
x86_cpuinit.fixup_cpu_id(c, node);
if (!node_online(node)) {
@@ -579,6 +580,24 @@
}
}
+ /* re-enable TopologyExtensions if switched off by BIOS */
+ if ((c->x86 == 0x15) &&
+ (c->x86_model >= 0x10) && (c->x86_model <= 0x1f) &&
+ !cpu_has(c, X86_FEATURE_TOPOEXT)) {
+ u64 val;
+
+ if (!rdmsrl_amd_safe(0xc0011005, &val)) {
+ val |= 1ULL << 54;
+ wrmsrl_amd_safe(0xc0011005, val);
+ rdmsrl(0xc0011005, val);
+ if (val & (1ULL << 54)) {
+ set_cpu_cap(c, X86_FEATURE_TOPOEXT);
+ printk(KERN_INFO FW_INFO "CPU: Re-enabling "
+ "disabled Topology Extensions Support\n");
+ }
+ }
+ }
+
cpu_detect_cache_sizes(c);
/* Multi core CPU? */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 67e2583..cf79302 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1163,15 +1163,6 @@
#endif /* ! CONFIG_KGDB */
/*
- * Prints an error where the NUMA and configured core-number mismatch and the
- * platform didn't override this to fix it up
- */
-void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node)
-{
- pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id);
-}
-
-/*
* cpu_init() initializes state that is per-CPU. Some data is already
* initialized (naturally) in the bootstrap process, such as the GDT
* and IDT. We reload them nevertheless, this function acts as a
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index 73d08ed..b8f3653 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -433,14 +433,14 @@
/* check if @slot is already used or the index is already disabled */
ret = amd_get_l3_disable_slot(nb, slot);
if (ret >= 0)
- return -EINVAL;
+ return -EEXIST;
if (index > nb->l3_cache.indices)
return -EINVAL;
/* check whether the other slot has disabled the same index already */
if (index == amd_get_l3_disable_slot(nb, !slot))
- return -EINVAL;
+ return -EEXIST;
amd_l3_disable_index(nb, cpu, slot, index);
@@ -468,8 +468,8 @@
err = amd_set_l3_disable_slot(this_leaf->base.nb, cpu, slot, val);
if (err) {
if (err == -EEXIST)
- printk(KERN_WARNING "L3 disable slot %d in use!\n",
- slot);
+ pr_warning("L3 slot %d in use/index already disabled!\n",
+ slot);
return err;
}
return count;
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c
index ef484d9..a2dfacf 100644
--- a/arch/x86/kernel/cpu/perf_event_p4.c
+++ b/arch/x86/kernel/cpu/perf_event_p4.c
@@ -1271,6 +1271,17 @@
return num ? -EINVAL : 0;
}
+PMU_FORMAT_ATTR(cccr, "config:0-31" );
+PMU_FORMAT_ATTR(escr, "config:32-62");
+PMU_FORMAT_ATTR(ht, "config:63" );
+
+static struct attribute *intel_p4_formats_attr[] = {
+ &format_attr_cccr.attr,
+ &format_attr_escr.attr,
+ &format_attr_ht.attr,
+ NULL,
+};
+
static __initconst const struct x86_pmu p4_pmu = {
.name = "Netburst P4/Xeon",
.handle_irq = p4_pmu_handle_irq,
@@ -1305,6 +1316,8 @@
* the former idea is taken from OProfile code
*/
.perfctr_second_write = 1,
+
+ .format_attrs = intel_p4_formats_attr,
};
__init int p4_pmu_init(void)
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index 7734bcb..2d6e649 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -235,6 +235,7 @@
if (tsk_used_math(tsk)) {
if (HAVE_HWFP && tsk == current)
unlazy_fpu(tsk);
+ tsk->thread.fpu.last_cpu = ~0;
return 0;
}
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 7943e0c..3dafc60 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -282,8 +282,13 @@
else if (!(warned++))
set_affinity = 0;
+ /*
+ * We unmask if the irq was not marked masked by the
+ * core code. That respects the lazy irq disable
+ * behaviour.
+ */
if (!irqd_can_move_in_process_context(data) &&
- !irqd_irq_disabled(data) && chip->irq_unmask)
+ !irqd_irq_masked(data) && chip->irq_unmask)
chip->irq_unmask(data);
raw_spin_unlock(&desc->lock);
diff --git a/arch/x86/kernel/kdebugfs.c b/arch/x86/kernel/kdebugfs.c
index 90fcf62..1d5d31e 100644
--- a/arch/x86/kernel/kdebugfs.c
+++ b/arch/x86/kernel/kdebugfs.c
@@ -68,16 +68,9 @@
return count;
}
-static int setup_data_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static const struct file_operations fops_setup_data = {
.read = setup_data_read,
- .open = setup_data_open,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index db6720e..8bfb614 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -43,6 +43,8 @@
#include <linux/smp.h>
#include <linux/nmi.h>
#include <linux/hw_breakpoint.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
#include <asm/debugreg.h>
#include <asm/apicdef.h>
@@ -741,6 +743,64 @@
regs->ip = ip;
}
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+ int err;
+ char opc[BREAK_INSTR_SIZE];
+
+ bpt->type = BP_BREAKPOINT;
+ err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+ BREAK_INSTR_SIZE);
+ if (err)
+ return err;
+ err = probe_kernel_write((char *)bpt->bpt_addr,
+ arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+#ifdef CONFIG_DEBUG_RODATA
+ if (!err)
+ return err;
+ /*
+ * It is safe to call text_poke() because normal kernel execution
+ * is stopped on all cores, so long as the text_mutex is not locked.
+ */
+ if (mutex_is_locked(&text_mutex))
+ return -EBUSY;
+ text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+ BREAK_INSTR_SIZE);
+ err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+ if (err)
+ return err;
+ if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
+ return -EINVAL;
+ bpt->type = BP_POKE_BREAKPOINT;
+#endif /* CONFIG_DEBUG_RODATA */
+ return err;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+#ifdef CONFIG_DEBUG_RODATA
+ int err;
+ char opc[BREAK_INSTR_SIZE];
+
+ if (bpt->type != BP_POKE_BREAKPOINT)
+ goto knl_write;
+ /*
+ * It is safe to call text_poke() because normal kernel execution
+ * is stopped on all cores, so long as the text_mutex is not locked.
+ */
+ if (mutex_is_locked(&text_mutex))
+ goto knl_write;
+ text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE);
+ err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+ if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
+ goto knl_write;
+ return err;
+knl_write:
+#endif /* CONFIG_DEBUG_RODATA */
+ return probe_kernel_write((char *)bpt->bpt_addr,
+ (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
+}
+
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: */
.gdb_bpt_instr = { 0xcc },
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 694d801..e554e5a 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -38,6 +38,7 @@
#include <asm/traps.h>
#include <asm/desc.h>
#include <asm/tlbflush.h>
+#include <asm/idle.h>
static int kvmapf = 1;
@@ -78,7 +79,6 @@
u32 token;
int cpu;
bool halted;
- struct mm_struct *mm;
};
static struct kvm_task_sleep_head {
@@ -125,9 +125,7 @@
n.token = token;
n.cpu = smp_processor_id();
- n.mm = current->active_mm;
n.halted = idle || preempt_count() > 1;
- atomic_inc(&n.mm->mm_count);
init_waitqueue_head(&n.wq);
hlist_add_head(&n.link, &b->list);
spin_unlock(&b->lock);
@@ -160,9 +158,6 @@
static void apf_task_wake_one(struct kvm_task_sleep_node *n)
{
hlist_del_init(&n->link);
- if (!n->mm)
- return;
- mmdrop(n->mm);
if (n->halted)
smp_send_reschedule(n->cpu);
else if (waitqueue_active(&n->wq))
@@ -206,7 +201,7 @@
* async PF was not yet handled.
* Add dummy entry for the token.
*/
- n = kmalloc(sizeof(*n), GFP_ATOMIC);
+ n = kzalloc(sizeof(*n), GFP_ATOMIC);
if (!n) {
/*
* Allocation failed! Busy wait while other cpu
@@ -218,7 +213,6 @@
}
n->token = token;
n->cpu = smp_processor_id();
- n->mm = NULL;
init_waitqueue_head(&n->wq);
hlist_add_head(&n->link, &b->list);
} else
@@ -253,7 +247,10 @@
kvm_async_pf_task_wait((u32)read_cr2());
break;
case KVM_PV_REASON_PAGE_READY:
+ rcu_irq_enter();
+ exit_idle();
kvm_async_pf_task_wake((u32)read_cr2());
+ rcu_irq_exit();
break;
}
}
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index 73465aa..8a2ce8f 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -82,11 +82,6 @@
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
- if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
- pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
- return -1;
- }
-
csig->rev = c->microcode;
pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
@@ -380,6 +375,13 @@
struct microcode_ops * __init init_amd_microcode(void)
{
+ struct cpuinfo_x86 *c = &cpu_data(0);
+
+ if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
+ pr_warning("AMD CPU family 0x%x not supported\n", c->x86);
+ return NULL;
+ }
+
patch = (void *)get_zeroed_page(GFP_KERNEL);
if (!patch)
return NULL;
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 87a0f86..c9bda6d 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -419,10 +419,8 @@
if (err)
return err;
- if (microcode_init_cpu(cpu) == UCODE_ERROR) {
- sysfs_remove_group(&dev->kobj, &mc_attr_group);
+ if (microcode_init_cpu(cpu) == UCODE_ERROR)
return -EINVAL;
- }
return err;
}
@@ -528,11 +526,11 @@
microcode_ops = init_intel_microcode();
else if (c->x86_vendor == X86_VENDOR_AMD)
microcode_ops = init_amd_microcode();
-
- if (!microcode_ops) {
+ else
pr_err("no support for this CPU vendor\n");
+
+ if (!microcode_ops)
return -ENODEV;
- }
microcode_pdev = platform_device_register_simple("microcode", -1,
NULL, 0);
diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
index 6ac5782..d0b2fb9 100644
--- a/arch/x86/kernel/pci-calgary_64.c
+++ b/arch/x86/kernel/pci-calgary_64.c
@@ -430,7 +430,7 @@
}
static void* calgary_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
+ dma_addr_t *dma_handle, gfp_t flag, struct dma_attrs *attrs)
{
void *ret = NULL;
dma_addr_t mapping;
@@ -463,7 +463,8 @@
}
static void calgary_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
unsigned int npages;
struct iommu_table *tbl = find_iommu_table(dev);
@@ -476,8 +477,8 @@
}
static struct dma_map_ops calgary_dma_ops = {
- .alloc_coherent = calgary_alloc_coherent,
- .free_coherent = calgary_free_coherent,
+ .alloc = calgary_alloc_coherent,
+ .free = calgary_free_coherent,
.map_sg = calgary_map_sg,
.unmap_sg = calgary_unmap_sg,
.map_page = calgary_map_page,
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 28e5e06..3003250 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -96,7 +96,8 @@
}
}
void *dma_generic_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag)
+ dma_addr_t *dma_addr, gfp_t flag,
+ struct dma_attrs *attrs)
{
unsigned long dma_mask;
struct page *page;
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 3af4af81..f960506 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -75,7 +75,7 @@
}
static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_addr)
+ dma_addr_t dma_addr, struct dma_attrs *attrs)
{
free_pages((unsigned long)vaddr, get_order(size));
}
@@ -96,8 +96,8 @@
}
struct dma_map_ops nommu_dma_ops = {
- .alloc_coherent = dma_generic_alloc_coherent,
- .free_coherent = nommu_free_coherent,
+ .alloc = dma_generic_alloc_coherent,
+ .free = nommu_free_coherent,
.map_sg = nommu_map_sg,
.map_page = nommu_map_page,
.sync_single_for_device = nommu_sync_single_for_device,
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 8f972cb..6c483ba 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -15,21 +15,30 @@
int swiotlb __read_mostly;
static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
+ dma_addr_t *dma_handle, gfp_t flags,
+ struct dma_attrs *attrs)
{
void *vaddr;
- vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags);
+ vaddr = dma_generic_alloc_coherent(hwdev, size, dma_handle, flags,
+ attrs);
if (vaddr)
return vaddr;
return swiotlb_alloc_coherent(hwdev, size, dma_handle, flags);
}
+static void x86_swiotlb_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
+{
+ swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
static struct dma_map_ops swiotlb_dma_ops = {
.mapping_error = swiotlb_dma_mapping_error,
- .alloc_coherent = x86_swiotlb_alloc_coherent,
- .free_coherent = swiotlb_free_coherent,
+ .alloc = x86_swiotlb_alloc_coherent,
+ .free = x86_swiotlb_free_coherent,
.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
.sync_single_for_device = swiotlb_sync_single_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index a33afaa..1d92a5a 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -362,34 +362,10 @@
EXPORT_SYMBOL(pm_idle);
#endif
-#ifdef CONFIG_X86_32
-/*
- * This halt magic was a workaround for ancient floppy DMA
- * wreckage. It should be safe to remove.
- */
-static int hlt_counter;
-void disable_hlt(void)
-{
- hlt_counter++;
-}
-EXPORT_SYMBOL(disable_hlt);
-
-void enable_hlt(void)
-{
- hlt_counter--;
-}
-EXPORT_SYMBOL(enable_hlt);
-
-static inline int hlt_use_halt(void)
-{
- return (!hlt_counter && boot_cpu_data.hlt_works_ok);
-}
-#else
static inline int hlt_use_halt(void)
{
return 1;
}
-#endif
#ifndef CONFIG_SMP
static inline void play_dead(void)
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 733ca39..43d8b48 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -423,6 +423,7 @@
current_thread_info()->status |= TS_COMPAT;
}
}
+EXPORT_SYMBOL_GPL(set_personality_ia32);
unsigned long get_wchan(struct task_struct *p)
{
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 71f4727..5a98aa2 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -185,10 +185,22 @@
#endif
rc = -EINVAL;
if (pcpu_chosen_fc != PCPU_FC_PAGE) {
- const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE;
const size_t dyn_size = PERCPU_MODULE_RESERVE +
PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE;
+ size_t atom_size;
+ /*
+ * On 64bit, use PMD_SIZE for atom_size so that embedded
+ * percpu areas are aligned to PMD. This, in the future,
+ * can also allow using PMD mappings in vmalloc area. Use
+ * PAGE_SIZE on 32bit as vmalloc space is highly contended
+ * and large vmalloc area allocs can easily fail.
+ */
+#ifdef CONFIG_X86_64
+ atom_size = PMD_SIZE;
+#else
+ atom_size = PAGE_SIZE;
+#endif
rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
dyn_size, atom_size,
pcpu_cpu_distance,
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index f386dc4..7515cf0e 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -216,9 +216,9 @@
current_thread_info()->sig_on_uaccess_error = 1;
/*
- * 0 is a valid user pointer (in the access_ok sense) on 32-bit and
+ * NULL is a valid user pointer (in the access_ok sense) on 32-bit and
* 64-bit, so we don't need to special-case it here. For all the
- * vsyscalls, 0 means "don't write anything" not "write it at
+ * vsyscalls, NULL means "don't write anything" not "write it at
* address 0".
*/
ret = -EFAULT;
@@ -247,7 +247,7 @@
ret = sys_getcpu((unsigned __user *)regs->di,
(unsigned __user *)regs->si,
- 0);
+ NULL);
break;
}
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index e9f265f..9cf71d0 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -93,7 +93,6 @@
struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
.early_percpu_clock_init = x86_init_noop,
.setup_percpu_clockev = setup_secondary_APIC_clock,
- .fixup_cpu_id = x86_default_fixup_cpu_id,
};
static void default_nmi_init(void) { };
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index a73f0c1..2e88438 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -369,7 +369,7 @@
case MSR_CORE_PERF_FIXED_CTR_CTRL:
if (pmu->fixed_ctr_ctrl == data)
return 0;
- if (!(data & 0xfffffffffffff444)) {
+ if (!(data & 0xfffffffffffff444ull)) {
reprogram_fixed_counters(pmu, data);
return 0;
}
@@ -459,17 +459,17 @@
pmu->available_event_types = ~entry->ebx & ((1ull << bitmap_len) - 1);
if (pmu->version == 1) {
- pmu->global_ctrl = (1 << pmu->nr_arch_gp_counters) - 1;
- return;
+ pmu->nr_arch_fixed_counters = 0;
+ } else {
+ pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
+ X86_PMC_MAX_FIXED);
+ pmu->counter_bitmask[KVM_PMC_FIXED] =
+ ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
}
- pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
- X86_PMC_MAX_FIXED);
- pmu->counter_bitmask[KVM_PMC_FIXED] =
- ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
- pmu->global_ctrl_mask = ~(((1 << pmu->nr_arch_gp_counters) - 1)
- | (((1ull << pmu->nr_arch_fixed_counters) - 1)
- << X86_PMC_IDX_FIXED));
+ pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+ (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED);
+ pmu->global_ctrl_mask = ~pmu->global_ctrl;
}
void kvm_pmu_init(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 280751c..4ff0ab9 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2210,9 +2210,12 @@
msr = find_msr_entry(vmx, msr_index);
if (msr) {
msr->data = data;
- if (msr - vmx->guest_msrs < vmx->save_nmsrs)
+ if (msr - vmx->guest_msrs < vmx->save_nmsrs) {
+ preempt_disable();
kvm_set_shared_msr(msr->index, msr->data,
msr->mask);
+ preempt_enable();
+ }
break;
}
ret = kvm_set_msr_common(vcpu, msr_index, data);
@@ -3906,7 +3909,9 @@
vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
vmx->vcpu.arch.cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
+ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
vmx_set_cr0(&vmx->vcpu, kvm_read_cr0(vcpu)); /* enter rmode */
+ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
vmx_set_cr4(&vmx->vcpu, 0);
vmx_set_efer(&vmx->vcpu, 0);
vmx_fpu_activate(&vmx->vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4044ce0..185a2b8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6336,13 +6336,11 @@
if (npages && !old.rmap) {
unsigned long userspace_addr;
- down_write(¤t->mm->mmap_sem);
- userspace_addr = do_mmap(NULL, 0,
+ userspace_addr = vm_mmap(NULL, 0,
npages * PAGE_SIZE,
PROT_READ | PROT_WRITE,
map_flags,
0);
- up_write(¤t->mm->mmap_sem);
if (IS_ERR((void *)userspace_addr))
return PTR_ERR((void *)userspace_addr);
@@ -6366,10 +6364,8 @@
if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
int ret;
- down_write(¤t->mm->mmap_sem);
- ret = do_munmap(current->mm, old.userspace_addr,
+ ret = vm_munmap(old.userspace_addr,
old.npages * PAGE_SIZE);
- up_write(¤t->mm->mmap_sem);
if (ret < 0)
printk(KERN_WARNING
"kvm_vm_ioctl_set_memory_region: "
@@ -6585,6 +6581,7 @@
kvm_inject_page_fault(vcpu, &fault);
}
vcpu->arch.apf.halted = false;
+ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
}
bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/lib/insn.c b/arch/x86/lib/insn.c
index 25feb1a..b1e6c4b 100644
--- a/arch/x86/lib/insn.c
+++ b/arch/x86/lib/insn.c
@@ -379,8 +379,8 @@
return;
}
-/* Decode moffset16/32/64 */
-static void __get_moffset(struct insn *insn)
+/* Decode moffset16/32/64. Return 0 if failed */
+static int __get_moffset(struct insn *insn)
{
switch (insn->addr_bytes) {
case 2:
@@ -397,15 +397,19 @@
insn->moffset2.value = get_next(int, insn);
insn->moffset2.nbytes = 4;
break;
+ default: /* opnd_bytes must be modified manually */
+ goto err_out;
}
insn->moffset1.got = insn->moffset2.got = 1;
+ return 1;
+
err_out:
- return;
+ return 0;
}
-/* Decode imm v32(Iz) */
-static void __get_immv32(struct insn *insn)
+/* Decode imm v32(Iz). Return 0 if failed */
+static int __get_immv32(struct insn *insn)
{
switch (insn->opnd_bytes) {
case 2:
@@ -417,14 +421,18 @@
insn->immediate.value = get_next(int, insn);
insn->immediate.nbytes = 4;
break;
+ default: /* opnd_bytes must be modified manually */
+ goto err_out;
}
+ return 1;
+
err_out:
- return;
+ return 0;
}
-/* Decode imm v64(Iv/Ov) */
-static void __get_immv(struct insn *insn)
+/* Decode imm v64(Iv/Ov), Return 0 if failed */
+static int __get_immv(struct insn *insn)
{
switch (insn->opnd_bytes) {
case 2:
@@ -441,15 +449,18 @@
insn->immediate2.value = get_next(int, insn);
insn->immediate2.nbytes = 4;
break;
+ default: /* opnd_bytes must be modified manually */
+ goto err_out;
}
insn->immediate1.got = insn->immediate2.got = 1;
+ return 1;
err_out:
- return;
+ return 0;
}
/* Decode ptr16:16/32(Ap) */
-static void __get_immptr(struct insn *insn)
+static int __get_immptr(struct insn *insn)
{
switch (insn->opnd_bytes) {
case 2:
@@ -462,14 +473,17 @@
break;
case 8:
/* ptr16:64 is not exist (no segment) */
- return;
+ return 0;
+ default: /* opnd_bytes must be modified manually */
+ goto err_out;
}
insn->immediate2.value = get_next(unsigned short, insn);
insn->immediate2.nbytes = 2;
insn->immediate1.got = insn->immediate2.got = 1;
+ return 1;
err_out:
- return;
+ return 0;
}
/**
@@ -489,7 +503,8 @@
insn_get_displacement(insn);
if (inat_has_moffset(insn->attr)) {
- __get_moffset(insn);
+ if (!__get_moffset(insn))
+ goto err_out;
goto done;
}
@@ -517,16 +532,20 @@
insn->immediate2.nbytes = 4;
break;
case INAT_IMM_PTR:
- __get_immptr(insn);
+ if (!__get_immptr(insn))
+ goto err_out;
break;
case INAT_IMM_VWORD32:
- __get_immv32(insn);
+ if (!__get_immv32(insn))
+ goto err_out;
break;
case INAT_IMM_VWORD:
- __get_immv(insn);
+ if (!__get_immv(insn))
+ goto err_out;
break;
default:
- break;
+ /* Here, insn must have an immediate, but failed */
+ goto err_out;
}
if (inat_has_second_immediate(insn->attr)) {
insn->immediate2.value = get_next(char, insn);
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index 97be9cb..d6ae30b 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -7,6 +7,8 @@
#include <linux/highmem.h>
#include <linux/module.h>
+#include <asm/word-at-a-time.h>
+
/*
* best effort, GUP based copy_from_user() that is NMI-safe
*/
@@ -41,3 +43,104 @@
return len;
}
EXPORT_SYMBOL_GPL(copy_from_user_nmi);
+
+static inline unsigned long count_bytes(unsigned long mask)
+{
+ mask = (mask - 1) & ~mask;
+ mask >>= 7;
+ return count_masked_bytes(mask);
+}
+
+/*
+ * Do a strncpy, return length of string without final '\0'.
+ * 'count' is the user-supplied count (return 'count' if we
+ * hit it), 'max' is the address space maximum (and we return
+ * -EFAULT if we hit it).
+ */
+static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
+{
+ long res = 0;
+
+ /*
+ * Truncate 'max' to the user-specified limit, so that
+ * we only have one limit we need to check in the loop
+ */
+ if (max > count)
+ max = count;
+
+ while (max >= sizeof(unsigned long)) {
+ unsigned long c;
+
+ /* Fall back to byte-at-a-time if we get a page fault */
+ if (unlikely(__get_user(c,(unsigned long __user *)(src+res))))
+ break;
+ /* This can write a few bytes past the NUL character, but that's ok */
+ *(unsigned long *)(dst+res) = c;
+ c = has_zero(c);
+ if (c)
+ return res + count_bytes(c);
+ res += sizeof(unsigned long);
+ max -= sizeof(unsigned long);
+ }
+
+ while (max) {
+ char c;
+
+ if (unlikely(__get_user(c,src+res)))
+ return -EFAULT;
+ dst[res] = c;
+ if (!c)
+ return res;
+ res++;
+ max--;
+ }
+
+ /*
+ * Uhhuh. We hit 'max'. But was that the user-specified maximum
+ * too? If so, that's ok - we got as much as the user asked for.
+ */
+ if (res >= count)
+ return res;
+
+ /*
+ * Nope: we hit the address space limit, and we still had more
+ * characters the caller would have wanted. That's an EFAULT.
+ */
+ return -EFAULT;
+}
+
+/**
+ * strncpy_from_user: - Copy a NUL terminated string from userspace.
+ * @dst: Destination address, in kernel space. This buffer must be at
+ * least @count bytes long.
+ * @src: Source address, in user space.
+ * @count: Maximum number of bytes to copy, including the trailing NUL.
+ *
+ * Copies a NUL-terminated string from userspace to kernel space.
+ *
+ * On success, returns the length of the string (not including the trailing
+ * NUL).
+ *
+ * If access to userspace fails, returns -EFAULT (some data may have been
+ * copied).
+ *
+ * If @count is smaller than the length of the string, copies @count bytes
+ * and returns @count.
+ */
+long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+ unsigned long max_addr, src_addr;
+
+ if (unlikely(count <= 0))
+ return 0;
+
+ max_addr = current_thread_info()->addr_limit.seg;
+ src_addr = (unsigned long)src;
+ if (likely(src_addr < max_addr)) {
+ unsigned long max = max_addr - src_addr;
+ return do_strncpy_from_user(dst, src, count, max);
+ }
+ return -EFAULT;
+}
+EXPORT_SYMBOL(strncpy_from_user);
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index d9b094c..ef2a6a5 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -33,93 +33,6 @@
__movsl_is_ok((unsigned long)(a1), (unsigned long)(a2), (n))
/*
- * Copy a null terminated string from userspace.
- */
-
-#define __do_strncpy_from_user(dst, src, count, res) \
-do { \
- int __d0, __d1, __d2; \
- might_fault(); \
- __asm__ __volatile__( \
- " testl %1,%1\n" \
- " jz 2f\n" \
- "0: lodsb\n" \
- " stosb\n" \
- " testb %%al,%%al\n" \
- " jz 1f\n" \
- " decl %1\n" \
- " jnz 0b\n" \
- "1: subl %1,%0\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: movl %5,%0\n" \
- " jmp 2b\n" \
- ".previous\n" \
- _ASM_EXTABLE(0b,3b) \
- : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
- "=&D" (__d2) \
- : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
- : "memory"); \
-} while (0)
-
-/**
- * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking.
- * @dst: Destination address, in kernel space. This buffer must be at
- * least @count bytes long.
- * @src: Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- * Caller must check the specified block with access_ok() before calling
- * this function.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-long
-__strncpy_from_user(char *dst, const char __user *src, long count)
-{
- long res;
- __do_strncpy_from_user(dst, src, count, res);
- return res;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
-
-/**
- * strncpy_from_user: - Copy a NUL terminated string from userspace.
- * @dst: Destination address, in kernel space. This buffer must be at
- * least @count bytes long.
- * @src: Source address, in user space.
- * @count: Maximum number of bytes to copy, including the trailing NUL.
- *
- * Copies a NUL-terminated string from userspace to kernel space.
- *
- * On success, returns the length of the string (not including the trailing
- * NUL).
- *
- * If access to userspace fails, returns -EFAULT (some data may have been
- * copied).
- *
- * If @count is smaller than the length of the string, copies @count bytes
- * and returns @count.
- */
-long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- long res = -EFAULT;
- if (access_ok(VERIFY_READ, src, 1))
- __do_strncpy_from_user(dst, src, count, res);
- return res;
-}
-EXPORT_SYMBOL(strncpy_from_user);
-
-/*
* Zero Userspace
*/
diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
index b7c2849..0d0326f 100644
--- a/arch/x86/lib/usercopy_64.c
+++ b/arch/x86/lib/usercopy_64.c
@@ -9,55 +9,6 @@
#include <asm/uaccess.h>
/*
- * Copy a null terminated string from userspace.
- */
-
-#define __do_strncpy_from_user(dst,src,count,res) \
-do { \
- long __d0, __d1, __d2; \
- might_fault(); \
- __asm__ __volatile__( \
- " testq %1,%1\n" \
- " jz 2f\n" \
- "0: lodsb\n" \
- " stosb\n" \
- " testb %%al,%%al\n" \
- " jz 1f\n" \
- " decq %1\n" \
- " jnz 0b\n" \
- "1: subq %1,%0\n" \
- "2:\n" \
- ".section .fixup,\"ax\"\n" \
- "3: movq %5,%0\n" \
- " jmp 2b\n" \
- ".previous\n" \
- _ASM_EXTABLE(0b,3b) \
- : "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
- "=&D" (__d2) \
- : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
- : "memory"); \
-} while (0)
-
-long
-__strncpy_from_user(char *dst, const char __user *src, long count)
-{
- long res;
- __do_strncpy_from_user(dst, src, count, res);
- return res;
-}
-EXPORT_SYMBOL(__strncpy_from_user);
-
-long
-strncpy_from_user(char *dst, const char __user *src, long count)
-{
- long res = -EFAULT;
- if (access_ok(VERIFY_READ, src, 1))
- return __strncpy_from_user(dst, src, count);
- return res;
-}
-EXPORT_SYMBOL(strncpy_from_user);
-
-/*
* Zero Userspace
*/
diff --git a/arch/x86/net/bpf_jit.S b/arch/x86/net/bpf_jit.S
index 6687022..877b9a1 100644
--- a/arch/x86/net/bpf_jit.S
+++ b/arch/x86/net/bpf_jit.S
@@ -18,17 +18,17 @@
* r9d : hlen = skb->len - skb->data_len
*/
#define SKBDATA %r8
-
-sk_load_word_ind:
- .globl sk_load_word_ind
-
- add %ebx,%esi /* offset += X */
-# test %esi,%esi /* if (offset < 0) goto bpf_error; */
- js bpf_error
+#define SKF_MAX_NEG_OFF $(-0x200000) /* SKF_LL_OFF from filter.h */
sk_load_word:
.globl sk_load_word
+ test %esi,%esi
+ js bpf_slow_path_word_neg
+
+sk_load_word_positive_offset:
+ .globl sk_load_word_positive_offset
+
mov %r9d,%eax # hlen
sub %esi,%eax # hlen - offset
cmp $3,%eax
@@ -37,16 +37,15 @@
bswap %eax /* ntohl() */
ret
-
-sk_load_half_ind:
- .globl sk_load_half_ind
-
- add %ebx,%esi /* offset += X */
- js bpf_error
-
sk_load_half:
.globl sk_load_half
+ test %esi,%esi
+ js bpf_slow_path_half_neg
+
+sk_load_half_positive_offset:
+ .globl sk_load_half_positive_offset
+
mov %r9d,%eax
sub %esi,%eax # hlen - offset
cmp $1,%eax
@@ -55,14 +54,15 @@
rol $8,%ax # ntohs()
ret
-sk_load_byte_ind:
- .globl sk_load_byte_ind
- add %ebx,%esi /* offset += X */
- js bpf_error
-
sk_load_byte:
.globl sk_load_byte
+ test %esi,%esi
+ js bpf_slow_path_byte_neg
+
+sk_load_byte_positive_offset:
+ .globl sk_load_byte_positive_offset
+
cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte */
jle bpf_slow_path_byte
movzbl (SKBDATA,%rsi),%eax
@@ -73,25 +73,21 @@
*
* Implements BPF_S_LDX_B_MSH : ldxb 4*([offset]&0xf)
* Must preserve A accumulator (%eax)
- * Inputs : %esi is the offset value, already known positive
+ * Inputs : %esi is the offset value
*/
-ENTRY(sk_load_byte_msh)
- CFI_STARTPROC
+sk_load_byte_msh:
+ .globl sk_load_byte_msh
+ test %esi,%esi
+ js bpf_slow_path_byte_msh_neg
+
+sk_load_byte_msh_positive_offset:
+ .globl sk_load_byte_msh_positive_offset
cmp %esi,%r9d /* if (offset >= hlen) goto bpf_slow_path_byte_msh */
jle bpf_slow_path_byte_msh
movzbl (SKBDATA,%rsi),%ebx
and $15,%bl
shl $2,%bl
ret
- CFI_ENDPROC
-ENDPROC(sk_load_byte_msh)
-
-bpf_error:
-# force a return 0 from jit handler
- xor %eax,%eax
- mov -8(%rbp),%rbx
- leaveq
- ret
/* rsi contains offset and can be scratched */
#define bpf_slow_path_common(LEN) \
@@ -138,3 +134,67 @@
shl $2,%al
xchg %eax,%ebx
ret
+
+#define sk_negative_common(SIZE) \
+ push %rdi; /* save skb */ \
+ push %r9; \
+ push SKBDATA; \
+/* rsi already has offset */ \
+ mov $SIZE,%ecx; /* size */ \
+ call bpf_internal_load_pointer_neg_helper; \
+ test %rax,%rax; \
+ pop SKBDATA; \
+ pop %r9; \
+ pop %rdi; \
+ jz bpf_error
+
+
+bpf_slow_path_word_neg:
+ cmp SKF_MAX_NEG_OFF, %esi /* test range */
+ jl bpf_error /* offset lower -> error */
+sk_load_word_negative_offset:
+ .globl sk_load_word_negative_offset
+ sk_negative_common(4)
+ mov (%rax), %eax
+ bswap %eax
+ ret
+
+bpf_slow_path_half_neg:
+ cmp SKF_MAX_NEG_OFF, %esi
+ jl bpf_error
+sk_load_half_negative_offset:
+ .globl sk_load_half_negative_offset
+ sk_negative_common(2)
+ mov (%rax),%ax
+ rol $8,%ax
+ movzwl %ax,%eax
+ ret
+
+bpf_slow_path_byte_neg:
+ cmp SKF_MAX_NEG_OFF, %esi
+ jl bpf_error
+sk_load_byte_negative_offset:
+ .globl sk_load_byte_negative_offset
+ sk_negative_common(1)
+ movzbl (%rax), %eax
+ ret
+
+bpf_slow_path_byte_msh_neg:
+ cmp SKF_MAX_NEG_OFF, %esi
+ jl bpf_error
+sk_load_byte_msh_negative_offset:
+ .globl sk_load_byte_msh_negative_offset
+ xchg %eax,%ebx /* dont lose A , X is about to be scratched */
+ sk_negative_common(1)
+ movzbl (%rax),%eax
+ and $15,%al
+ shl $2,%al
+ xchg %eax,%ebx
+ ret
+
+bpf_error:
+# force a return 0 from jit handler
+ xor %eax,%eax
+ mov -8(%rbp),%rbx
+ leaveq
+ ret
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 5671752..0597f95 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -30,7 +30,10 @@
* assembly code in arch/x86/net/bpf_jit.S
*/
extern u8 sk_load_word[], sk_load_half[], sk_load_byte[], sk_load_byte_msh[];
-extern u8 sk_load_word_ind[], sk_load_half_ind[], sk_load_byte_ind[];
+extern u8 sk_load_word_positive_offset[], sk_load_half_positive_offset[];
+extern u8 sk_load_byte_positive_offset[], sk_load_byte_msh_positive_offset[];
+extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[];
+extern u8 sk_load_byte_negative_offset[], sk_load_byte_msh_negative_offset[];
static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
{
@@ -117,6 +120,8 @@
set_fs(old_fs);
}
+#define CHOOSE_LOAD_FUNC(K, func) \
+ ((int)K < 0 ? ((int)K >= SKF_LL_OFF ? func##_negative_offset : func) : func##_positive_offset)
void bpf_jit_compile(struct sk_filter *fp)
{
@@ -289,7 +294,7 @@
EMIT2(0x24, K & 0xFF); /* and imm8,%al */
} else if (K >= 0xFFFF0000) {
EMIT2(0x66, 0x25); /* and imm16,%ax */
- EMIT2(K, 2);
+ EMIT(K, 2);
} else {
EMIT1_off32(0x25, K); /* and imm32,%eax */
}
@@ -473,44 +478,46 @@
#endif
break;
case BPF_S_LD_W_ABS:
- func = sk_load_word;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_word);
common_load: seen |= SEEN_DATAREF;
- if ((int)K < 0) {
- /* Abort the JIT because __load_pointer() is needed. */
- goto out;
- }
t_offset = func - (image + addrs[i]);
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
EMIT1_off32(0xe8, t_offset); /* call */
break;
case BPF_S_LD_H_ABS:
- func = sk_load_half;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_half);
goto common_load;
case BPF_S_LD_B_ABS:
- func = sk_load_byte;
+ func = CHOOSE_LOAD_FUNC(K, sk_load_byte);
goto common_load;
case BPF_S_LDX_B_MSH:
- if ((int)K < 0) {
- /* Abort the JIT because __load_pointer() is needed. */
- goto out;
- }
+ func = CHOOSE_LOAD_FUNC(K, sk_load_byte_msh);
seen |= SEEN_DATAREF | SEEN_XREG;
- t_offset = sk_load_byte_msh - (image + addrs[i]);
+ t_offset = func - (image + addrs[i]);
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
EMIT1_off32(0xe8, t_offset); /* call sk_load_byte_msh */
break;
case BPF_S_LD_W_IND:
- func = sk_load_word_ind;
+ func = sk_load_word;
common_load_ind: seen |= SEEN_DATAREF | SEEN_XREG;
t_offset = func - (image + addrs[i]);
- EMIT1_off32(0xbe, K); /* mov imm32,%esi */
+ if (K) {
+ if (is_imm8(K)) {
+ EMIT3(0x8d, 0x73, K); /* lea imm8(%rbx), %esi */
+ } else {
+ EMIT2(0x8d, 0xb3); /* lea imm32(%rbx),%esi */
+ EMIT(K, 4);
+ }
+ } else {
+ EMIT2(0x89,0xde); /* mov %ebx,%esi */
+ }
EMIT1_off32(0xe8, t_offset); /* call sk_load_xxx_ind */
break;
case BPF_S_LD_H_IND:
- func = sk_load_half_ind;
+ func = sk_load_half;
goto common_load_ind;
case BPF_S_LD_B_IND:
- func = sk_load_byte_ind;
+ func = sk_load_byte;
goto common_load_ind;
case BPF_S_JMP_JA:
t_offset = addrs[i + K] - addrs[i];
diff --git a/arch/x86/platform/geode/net5501.c b/arch/x86/platform/geode/net5501.c
index 66d377e..646e3b5 100644
--- a/arch/x86/platform/geode/net5501.c
+++ b/arch/x86/platform/geode/net5501.c
@@ -63,7 +63,7 @@
.name = "net5501:1",
.gpio = 6,
.default_trigger = "default-on",
- .active_low = 1,
+ .active_low = 0,
},
};
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
index e0a3723..e31bcd8 100644
--- a/arch/x86/platform/mrst/mrst.c
+++ b/arch/x86/platform/mrst/mrst.c
@@ -805,7 +805,7 @@
} else
i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
}
- intel_scu_notifier_post(SCU_AVAILABLE, 0L);
+ intel_scu_notifier_post(SCU_AVAILABLE, NULL);
}
EXPORT_SYMBOL_GPL(intel_scu_devices_create);
@@ -814,7 +814,7 @@
{
int i;
- intel_scu_notifier_post(SCU_DOWN, 0L);
+ intel_scu_notifier_post(SCU_DOWN, NULL);
for (i = 0; i < ipc_next_dev; i++)
platform_device_del(ipc_devs[i]);
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 4793683..218cdb1 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -225,13 +225,13 @@
fix_processor_context();
do_fpu_end();
+ x86_platform.restore_sched_clock_state();
mtrr_bp_restore();
}
/* Needed by apm.c */
void restore_processor_state(void)
{
- x86_platform.restore_sched_clock_state();
__restore_processor_state(&saved_context);
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h
new file mode 100644
index 0000000..7d01b8c
--- /dev/null
+++ b/arch/x86/um/asm/barrier.h
@@ -0,0 +1,75 @@
+#ifndef _ASM_UM_BARRIER_H_
+#define _ASM_UM_BARRIER_H_
+
+#include <asm/asm.h>
+#include <asm/segment.h>
+#include <asm/cpufeature.h>
+#include <asm/cmpxchg.h>
+#include <asm/nops.h>
+
+#include <linux/kernel.h>
+#include <linux/irqflags.h>
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ */
+#ifdef CONFIG_X86_32
+
+#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
+#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
+#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
+
+#else /* CONFIG_X86_32 */
+
+#define mb() asm volatile("mfence" : : : "memory")
+#define rmb() asm volatile("lfence" : : : "memory")
+#define wmb() asm volatile("sfence" : : : "memory")
+
+#endif /* CONFIG_X86_32 */
+
+#define read_barrier_depends() do { } while (0)
+
+#ifdef CONFIG_SMP
+
+#define smp_mb() mb()
+#ifdef CONFIG_X86_PPRO_FENCE
+#define smp_rmb() rmb()
+#else /* CONFIG_X86_PPRO_FENCE */
+#define smp_rmb() barrier()
+#endif /* CONFIG_X86_PPRO_FENCE */
+
+#ifdef CONFIG_X86_OOSTORE
+#define smp_wmb() wmb()
+#else /* CONFIG_X86_OOSTORE */
+#define smp_wmb() barrier()
+#endif /* CONFIG_X86_OOSTORE */
+
+#define smp_read_barrier_depends() read_barrier_depends()
+#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
+
+#else /* CONFIG_SMP */
+
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+#define smp_read_barrier_depends() do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
+
+#endif /* CONFIG_SMP */
+
+/*
+ * Stop RDTSC speculation. This is needed when you need to use RDTSC
+ * (or get_cycles or vread that possibly accesses the TSC) in a defined
+ * code region.
+ *
+ * (Could use an alternative three way for this if there was one.)
+ */
+static inline void rdtsc_barrier(void)
+{
+ alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
+ alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
+}
+
+#endif
diff --git a/arch/x86/um/asm/system.h b/arch/x86/um/asm/system.h
deleted file mode 100644
index a459fd9..0000000
--- a/arch/x86/um/asm/system.h
+++ /dev/null
@@ -1,135 +0,0 @@
-#ifndef _ASM_X86_SYSTEM_H_
-#define _ASM_X86_SYSTEM_H_
-
-#include <asm/asm.h>
-#include <asm/segment.h>
-#include <asm/cpufeature.h>
-#include <asm/cmpxchg.h>
-#include <asm/nops.h>
-
-#include <linux/kernel.h>
-#include <linux/irqflags.h>
-
-/* entries in ARCH_DLINFO: */
-#ifdef CONFIG_IA32_EMULATION
-# define AT_VECTOR_SIZE_ARCH 2
-#else
-# define AT_VECTOR_SIZE_ARCH 1
-#endif
-
-extern unsigned long arch_align_stack(unsigned long sp);
-
-void default_idle(void);
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- */
-#ifdef CONFIG_X86_32
-/*
- * Some non-Intel clones support out of order store. wmb() ceases to be a
- * nop for these.
- */
-#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
-#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)
-#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)
-#else
-#define mb() asm volatile("mfence":::"memory")
-#define rmb() asm volatile("lfence":::"memory")
-#define wmb() asm volatile("sfence" ::: "memory")
-#endif
-
-/**
- * read_barrier_depends - Flush all pending reads that subsequents reads
- * depend on.
- *
- * No data-dependent reads from memory-like regions are ever reordered
- * over this barrier. All reads preceding this primitive are guaranteed
- * to access memory (but not necessarily other CPUs' caches) before any
- * reads following this primitive that depend on the data return by
- * any of the preceding reads. This primitive is much lighter weight than
- * rmb() on most CPUs, and is never heavier weight than is
- * rmb().
- *
- * These ordering constraints are respected by both the local CPU
- * and the compiler.
- *
- * Ordering is not guaranteed by anything other than these primitives,
- * not even by data dependencies. See the documentation for
- * memory_barrier() for examples and URLs to more information.
- *
- * For example, the following code would force ordering (the initial
- * value of "a" is zero, "b" is one, and "p" is "&a"):
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * b = 2;
- * memory_barrier();
- * p = &b; q = p;
- * read_barrier_depends();
- * d = *q;
- * </programlisting>
- *
- * because the read of "*q" depends on the read of "p" and these
- * two reads are separated by a read_barrier_depends(). However,
- * the following code, with the same initial values for "a" and "b":
- *
- * <programlisting>
- * CPU 0 CPU 1
- *
- * a = 2;
- * memory_barrier();
- * b = 3; y = b;
- * read_barrier_depends();
- * x = a;
- * </programlisting>
- *
- * does not enforce ordering, since there is no data dependency between
- * the read of "a" and the read of "b". Therefore, on some CPUs, such
- * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb()
- * in cases like this where there are no data dependencies.
- **/
-
-#define read_barrier_depends() do { } while (0)
-
-#ifdef CONFIG_SMP
-#define smp_mb() mb()
-#ifdef CONFIG_X86_PPRO_FENCE
-# define smp_rmb() rmb()
-#else
-# define smp_rmb() barrier()
-#endif
-#ifdef CONFIG_X86_OOSTORE
-# define smp_wmb() wmb()
-#else
-# define smp_wmb() barrier()
-#endif
-#define smp_read_barrier_depends() read_barrier_depends()
-#define set_mb(var, value) do { (void)xchg(&var, value); } while (0)
-#else
-#define smp_mb() barrier()
-#define smp_rmb() barrier()
-#define smp_wmb() barrier()
-#define smp_read_barrier_depends() do { } while (0)
-#define set_mb(var, value) do { var = value; barrier(); } while (0)
-#endif
-
-/*
- * Stop RDTSC speculation. This is needed when you need to use RDTSC
- * (or get_cycles or vread that possibly accesses the TSC) in a defined
- * code region.
- *
- * (Could use an alternative three way for this if there was one.)
- */
-static inline void rdtsc_barrier(void)
-{
- alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC);
- alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC);
-}
-
-extern void *_switch_to(void *prev, void *next, void *last);
-#define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
-
-#endif
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index b132ade..95dccce 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -63,6 +63,7 @@
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>
#include <asm/mwait.h>
+#include <asm/pci_x86.h>
#ifdef CONFIG_ACPI
#include <linux/acpi.h>
@@ -261,7 +262,8 @@
static bool __init xen_check_mwait(void)
{
-#ifdef CONFIG_ACPI
+#if defined(CONFIG_ACPI) && !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) && \
+ !defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
struct xen_platform_op op = {
.cmd = XENPF_set_processor_pminfo,
.u.set_pminfo.id = -1,
@@ -349,7 +351,6 @@
/* Xen will set CR4.OSXSAVE if supported and not disabled by force */
if ((cx & xsave_mask) != xsave_mask)
cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */
-
if (xen_check_mwait())
cpuid_leaf1_ecx_set_mask = (1 << (X86_FEATURE_MWAIT % 32));
}
@@ -809,9 +810,40 @@
}
#ifdef CONFIG_X86_LOCAL_APIC
+static unsigned long xen_set_apic_id(unsigned int x)
+{
+ WARN_ON(1);
+ return x;
+}
+static unsigned int xen_get_apic_id(unsigned long x)
+{
+ return ((x)>>24) & 0xFFu;
+}
static u32 xen_apic_read(u32 reg)
{
- return 0;
+ struct xen_platform_op op = {
+ .cmd = XENPF_get_cpuinfo,
+ .interface_version = XENPF_INTERFACE_VERSION,
+ .u.pcpu_info.xen_cpuid = 0,
+ };
+ int ret = 0;
+
+ /* Shouldn't need this as APIC is turned off for PV, and we only
+ * get called on the bootup processor. But just in case. */
+ if (!xen_initial_domain() || smp_processor_id())
+ return 0;
+
+ if (reg == APIC_LVR)
+ return 0x10;
+
+ if (reg != APIC_ID)
+ return 0;
+
+ ret = HYPERVISOR_dom0_op(&op);
+ if (ret)
+ return 0;
+
+ return op.u.pcpu_info.apic_id << 24;
}
static void xen_apic_write(u32 reg, u32 val)
@@ -849,6 +881,8 @@
apic->icr_write = xen_apic_icr_write;
apic->wait_icr_idle = xen_apic_wait_icr_idle;
apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle;
+ apic->set_apic_id = xen_set_apic_id;
+ apic->get_apic_id = xen_get_apic_id;
}
#endif
@@ -967,7 +1001,7 @@
xen_setup_mfn_list_list();
}
-/* This is called once we have the cpu_possible_map */
+/* This is called once we have the cpu_possible_mask */
void xen_setup_vcpu_info_placement(void)
{
int cpu;
@@ -1365,8 +1399,10 @@
/* Make sure ACS will be enabled */
pci_request_acs();
}
-
-
+#ifdef CONFIG_PCI
+ /* PCI BIOS service won't work from a PV guest. */
+ pci_probe &= ~PCI_PROBE_BIOS;
+#endif
xen_raw_console_write("about to get started...\n");
xen_setup_runstate_info(0);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 988828b..69f5857 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -353,8 +353,13 @@
{
if (val & _PAGE_PRESENT) {
unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+ unsigned long pfn = mfn_to_pfn(mfn);
+
pteval_t flags = val & PTE_FLAGS_MASK;
- val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+ if (unlikely(pfn == ~0))
+ val = flags & ~_PAGE_PRESENT;
+ else
+ val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
}
return val;
@@ -1859,6 +1864,7 @@
#endif /* CONFIG_X86_64 */
static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
+static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;
static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
{
@@ -1899,7 +1905,7 @@
* We just don't map the IO APIC - all access is via
* hypercalls. Keep the address in the pte for reference.
*/
- pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
+ pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL);
break;
#endif
@@ -2064,6 +2070,7 @@
pv_mmu_ops = xen_mmu_ops;
memset(dummy_mapping, 0xff, PAGE_SIZE);
+ memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);
}
/* Protected by xen_reservation_lock. */
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index b480d42..967633a 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -12,8 +12,8 @@
static struct dma_map_ops xen_swiotlb_dma_ops = {
.mapping_error = xen_swiotlb_dma_mapping_error,
- .alloc_coherent = xen_swiotlb_alloc_coherent,
- .free_coherent = xen_swiotlb_free_coherent,
+ .alloc = xen_swiotlb_alloc_coherent,
+ .free = xen_swiotlb_free_coherent,
.sync_single_for_cpu = xen_swiotlb_sync_single_for_cpu,
.sync_single_for_device = xen_swiotlb_sync_single_for_device,
.sync_sg_for_cpu = xen_swiotlb_sync_sg_for_cpu,
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 02900e8..0503c0c 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -59,7 +59,7 @@
static void __cpuinit cpu_bringup(void)
{
- int cpu = smp_processor_id();
+ int cpu;
cpu_init();
touch_softlockup_watchdog();
@@ -178,6 +178,7 @@
static void __init xen_filter_cpu_maps(void)
{
int i, rc;
+ unsigned int subtract = 0;
if (!xen_initial_domain())
return;
@@ -192,8 +193,22 @@
} else {
set_cpu_possible(i, false);
set_cpu_present(i, false);
+ subtract++;
}
}
+#ifdef CONFIG_HOTPLUG_CPU
+ /* This is akin to using 'nr_cpus' on the Linux command line.
+ * Which is OK as when we use 'dom0_max_vcpus=X' we can only
+ * have up to X, while nr_cpu_ids is greater than X. This
+ * normally is not a problem, except when CPU hotplugging
+ * is involved and then there might be more than X CPUs
+ * in the guest - which will not work as there is no
+ * hypercall to expand the max number of VCPUs an already
+ * running guest has. So cap it up to X. */
+ if (subtract)
+ nr_cpu_ids = nr_cpu_ids - subtract;
+#endif
+
}
static void __init xen_smp_prepare_boot_cpu(void)
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 79d7362..3e45aa0 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -96,7 +96,7 @@
/* check for unmasked and pending */
cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
- jz 1f
+ jnz 1f
2: call check_events
1:
ENDPATCH(xen_restore_fl_direct)
diff --git a/arch/xtensa/include/asm/hardirq.h b/arch/xtensa/include/asm/hardirq.h
index 26664ce..91695a1 100644
--- a/arch/xtensa/include/asm/hardirq.h
+++ b/arch/xtensa/include/asm/hardirq.h
@@ -11,9 +11,6 @@
#ifndef _XTENSA_HARDIRQ_H
#define _XTENSA_HARDIRQ_H
-void ack_bad_irq(unsigned int irq);
-#define ack_bad_irq ack_bad_irq
-
#include <asm-generic/hardirq.h>
#endif /* _XTENSA_HARDIRQ_H */
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index d04cd3a..4beb43c 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -14,6 +14,7 @@
#ifdef __KERNEL__
#include <asm/byteorder.h>
#include <asm/page.h>
+#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/types.h>
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index b69b000..d78869a 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -496,6 +496,7 @@
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
+ int ret;
/* Are we from a system call? */
diff --git a/block/blk-core.c b/block/blk-core.c
index 3a78b00..1f61b74 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -483,7 +483,7 @@
if (!q)
return NULL;
- q->id = ida_simple_get(&blk_queue_ida, 0, 0, GFP_KERNEL);
+ q->id = ida_simple_get(&blk_queue_ida, 0, 0, gfp_mask);
if (q->id < 0)
goto fail_q;
@@ -1277,7 +1277,8 @@
list_for_each_entry_reverse(rq, &plug->list, queuelist) {
int el_ret;
- (*request_count)++;
+ if (rq->q == q)
+ (*request_count)++;
if (rq->q != q || !blk_rq_merge_ok(rq, bio))
continue;
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 5eed6a7..f2ddb94 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -1218,7 +1218,7 @@
struct bio_list bl;
struct bio *bio;
- WARN_ON_ONCE(!queue_is_locked(q));
+ queue_lockdep_assert_held(q);
bio_list_init(&bl);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index 4572952..3c38536 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -295,6 +295,7 @@
unsigned int cfq_slice_idle;
unsigned int cfq_group_idle;
unsigned int cfq_latency;
+ unsigned int cfq_target_latency;
/*
* Fallback dummy cfqq for extreme OOM conditions
@@ -604,7 +605,7 @@
{
struct cfq_rb_root *st = &cfqd->grp_service_tree;
- return cfq_target_latency * cfqg->weight / st->total_weight;
+ return cfqd->cfq_target_latency * cfqg->weight / st->total_weight;
}
static inline unsigned
@@ -2271,7 +2272,8 @@
* to have higher weight. A more accurate thing would be to
* calculate system wide asnc/sync ratio.
*/
- tmp = cfq_target_latency * cfqg_busy_async_queues(cfqd, cfqg);
+ tmp = cfqd->cfq_target_latency *
+ cfqg_busy_async_queues(cfqd, cfqg);
tmp = tmp/cfqd->busy_queues;
slice = min_t(unsigned, slice, tmp);
@@ -3737,6 +3739,7 @@
cfqd->cfq_back_penalty = cfq_back_penalty;
cfqd->cfq_slice[0] = cfq_slice_async;
cfqd->cfq_slice[1] = cfq_slice_sync;
+ cfqd->cfq_target_latency = cfq_target_latency;
cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
cfqd->cfq_slice_idle = cfq_slice_idle;
cfqd->cfq_group_idle = cfq_group_idle;
@@ -3788,6 +3791,7 @@
SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0);
+SHOW_FUNCTION(cfq_target_latency_show, cfqd->cfq_target_latency, 1);
#undef SHOW_FUNCTION
#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \
@@ -3821,6 +3825,7 @@
STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
UINT_MAX, 0);
STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0);
+STORE_FUNCTION(cfq_target_latency_store, &cfqd->cfq_target_latency, 1, UINT_MAX, 1);
#undef STORE_FUNCTION
#define CFQ_ATTR(name) \
@@ -3838,6 +3843,7 @@
CFQ_ATTR(slice_idle),
CFQ_ATTR(group_idle),
CFQ_ATTR(low_latency),
+ CFQ_ATTR(target_latency),
__ATTR_NULL
};
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 21ff9d0..8e84225 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -627,7 +627,7 @@
config CRYPTO_BLOWFISH_X86_64
tristate "Blowfish cipher algorithm (x86_64)"
- depends on (X86 || UML_X86) && 64BIT
+ depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_BLOWFISH_COMMON
help
@@ -657,7 +657,7 @@
config CRYPTO_CAMELLIA_X86_64
tristate "Camellia cipher algorithm (x86_64)"
- depends on (X86 || UML_X86) && 64BIT
+ depends on X86 && 64BIT
depends on CRYPTO
select CRYPTO_ALGAPI
select CRYPTO_LRW
@@ -893,7 +893,7 @@
config CRYPTO_TWOFISH_X86_64_3WAY
tristate "Twofish cipher algorithm (x86_64, 3-way parallel)"
- depends on (X86 || UML_X86) && 64BIT
+ depends on X86 && 64BIT
select CRYPTO_ALGAPI
select CRYPTO_TWOFISH_COMMON
select CRYPTO_TWOFISH_X86_64
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index a0f768c..8d3a056 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -613,8 +613,7 @@
return err;
}
-static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
- u32 mask)
+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
@@ -652,6 +651,7 @@
return ERR_PTR(crypto_givcipher_default(alg, type, mask));
}
+EXPORT_SYMBOL_GPL(crypto_lookup_skcipher);
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
u32 type, u32 mask)
diff --git a/crypto/aead.c b/crypto/aead.c
index 04add3dc..e4cb351 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -470,8 +470,7 @@
return err;
}
-static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
- u32 mask)
+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
@@ -503,6 +502,7 @@
return ERR_PTR(crypto_nivaead_default(alg, type, mask));
}
+EXPORT_SYMBOL_GPL(crypto_lookup_aead);
int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
u32 type, u32 mask)
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index f76e42b..f1ea0a0 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -21,9 +21,13 @@
#include <linux/module.h>
#include <linux/crypto.h>
#include <linux/cryptouser.h>
+#include <linux/sched.h>
#include <net/netlink.h>
#include <linux/security.h>
#include <net/net_namespace.h>
+#include <crypto/internal/aead.h>
+#include <crypto/internal/skcipher.h>
+
#include "internal.h"
DEFINE_MUTEX(crypto_cfg_mutex);
@@ -301,6 +305,60 @@
return crypto_unregister_instance(alg);
}
+static struct crypto_alg *crypto_user_skcipher_alg(const char *name, u32 type,
+ u32 mask)
+{
+ int err;
+ struct crypto_alg *alg;
+
+ type = crypto_skcipher_type(type);
+ mask = crypto_skcipher_mask(mask);
+
+ for (;;) {
+ alg = crypto_lookup_skcipher(name, type, mask);
+ if (!IS_ERR(alg))
+ return alg;
+
+ err = PTR_ERR(alg);
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+
+static struct crypto_alg *crypto_user_aead_alg(const char *name, u32 type,
+ u32 mask)
+{
+ int err;
+ struct crypto_alg *alg;
+
+ type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ type |= CRYPTO_ALG_TYPE_AEAD;
+ mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
+ mask |= CRYPTO_ALG_TYPE_MASK;
+
+ for (;;) {
+ alg = crypto_lookup_aead(name, type, mask);
+ if (!IS_ERR(alg))
+ return alg;
+
+ err = PTR_ERR(alg);
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+
static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs)
{
@@ -325,7 +383,19 @@
else
name = p->cru_name;
- alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+ switch (p->cru_type & p->cru_mask & CRYPTO_ALG_TYPE_MASK) {
+ case CRYPTO_ALG_TYPE_AEAD:
+ alg = crypto_user_aead_alg(name, p->cru_type, p->cru_mask);
+ break;
+ case CRYPTO_ALG_TYPE_GIVCIPHER:
+ case CRYPTO_ALG_TYPE_BLKCIPHER:
+ case CRYPTO_ALG_TYPE_ABLKCIPHER:
+ alg = crypto_user_skcipher_alg(name, p->cru_type, p->cru_mask);
+ break;
+ default:
+ alg = crypto_alg_mod_lookup(name, p->cru_type, p->cru_mask);
+ }
+
if (IS_ERR(alg))
return PTR_ERR(alg);
@@ -387,12 +457,20 @@
if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
(nlh->nlmsg_flags & NLM_F_DUMP))) {
+ struct crypto_alg *alg;
+ u16 dump_alloc = 0;
+
if (link->dump == NULL)
return -EINVAL;
+
+ list_for_each_entry(alg, &crypto_alg_list, cra_list)
+ dump_alloc += CRYPTO_REPORT_MAXSIZE;
+
{
struct netlink_dump_control c = {
.dump = link->dump,
.done = link->done,
+ .min_dump_alloc = dump_alloc,
};
return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
}
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
index 29a89da..b2c99dc 100644
--- a/crypto/pcrypt.c
+++ b/crypto/pcrypt.c
@@ -280,11 +280,11 @@
ictx->tfm_count++;
- cpu_index = ictx->tfm_count % cpumask_weight(cpu_active_mask);
+ cpu_index = ictx->tfm_count % cpumask_weight(cpu_online_mask);
- ctx->cb_cpu = cpumask_first(cpu_active_mask);
+ ctx->cb_cpu = cpumask_first(cpu_online_mask);
for (cpu = 0; cpu < cpu_index; cpu++)
- ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_active_mask);
+ ctx->cb_cpu = cpumask_next(ctx->cb_cpu, cpu_online_mask);
cipher = crypto_spawn_aead(crypto_instance_ctx(inst));
@@ -472,7 +472,7 @@
goto err_free_padata;
}
- cpumask_and(mask->mask, cpu_possible_mask, cpu_active_mask);
+ cpumask_and(mask->mask, cpu_possible_mask, cpu_online_mask);
rcu_assign_pointer(pcrypt->cb_cpumask, mask);
pcrypt->nblock.notifier_call = pcrypt_cpumask_change_notify;
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 107f6f7..dd30f40 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -174,7 +174,7 @@
index = sctx->count[0] & 0x7f;
/* Update number of bytes */
- if (!(sctx->count[0] += len))
+ if ((sctx->count[0] += len) < len)
sctx->count[1]++;
part_len = 128 - index;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 6f0459c..d236aef 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -50,6 +50,8 @@
source "drivers/spi/Kconfig"
+source "drivers/hsi/Kconfig"
+
source "drivers/pps/Kconfig"
source "drivers/ptp/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 262b19d..95952c8 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -53,6 +53,7 @@
obj-$(CONFIG_TARGET_CORE) += target/
obj-$(CONFIG_MTD) += mtd/
obj-$(CONFIG_SPI) += spi/
+obj-y += hsi/
obj-y += net/
obj-$(CONFIG_ATM) += atm/
obj-$(CONFIG_FUSION) += message/
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c
index ab513a9..a716fed 100644
--- a/drivers/acpi/acpica/hwxface.c
+++ b/drivers/acpi/acpica/hwxface.c
@@ -74,7 +74,8 @@
/* Check if the reset register is supported */
- if (!reset_reg->address) {
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
+ !reset_reg->address) {
return_ACPI_STATUS(AE_NOT_EXIST);
}
diff --git a/drivers/acpi/ec_sys.c b/drivers/acpi/ec_sys.c
index b258cab..7586544 100644
--- a/drivers/acpi/ec_sys.c
+++ b/drivers/acpi/ec_sys.c
@@ -27,12 +27,6 @@
static struct dentry *acpi_ec_debugfs_dir;
-static int acpi_ec_open_io(struct inode *i, struct file *f)
-{
- f->private_data = i->i_private;
- return 0;
-}
-
static ssize_t acpi_ec_read_io(struct file *f, char __user *buf,
size_t count, loff_t *off)
{
@@ -95,7 +89,7 @@
static const struct file_operations acpi_ec_io_ops = {
.owner = THIS_MODULE,
- .open = acpi_ec_open_io,
+ .open = simple_open,
.read = acpi_ec_read_io,
.write = acpi_ec_write_io,
.llseek = default_llseek,
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index ba14fb9..c3881b2 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -607,8 +607,7 @@
acpi_irq_handler = handler;
acpi_irq_context = context;
- if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi",
- acpi_irq)) {
+ if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 7049a7d..330bb4d 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -631,7 +631,7 @@
* We know a device's inferred power state when all the resources
* required for a given D-state are 'on'.
*/
- for (i = ACPI_STATE_D0; i < ACPI_STATE_D3; i++) {
+ for (i = ACPI_STATE_D0; i < ACPI_STATE_D3_HOT; i++) {
list = &device->power.states[i].resources;
if (list->count < 1)
continue;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index b3447f6..f3decb3 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -786,7 +786,7 @@
while (1) {
if (cx->entry_method == ACPI_CSTATE_HALT)
- halt();
+ safe_halt();
else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) {
inb(cx->address);
/* See comment in acpi_idle_do_entry() */
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c
index c1d6124..a6c77e8b 100644
--- a/drivers/acpi/reboot.c
+++ b/drivers/acpi/reboot.c
@@ -23,7 +23,8 @@
/* Is the reset register supported? The spec says we should be
* checking the bit width and bit offset, but Windows ignores
* these fields */
- /* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
+ return;
reset_value = acpi_gbl_FADT.reset_value;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 767e2dc..7417267 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -869,7 +869,7 @@
/*
* Enumerate supported power management states
*/
- for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3; i++) {
+ for (i = ACPI_STATE_D0; i <= ACPI_STATE_D3_HOT; i++) {
struct acpi_device_power_state *ps = &device->power.states[i];
char object_name[5] = { '_', 'P', 'R', '0' + i, '\0' };
@@ -884,21 +884,18 @@
acpi_bus_add_power_resource(ps->resources.handles[j]);
}
- /* The exist of _PR3 indicates D3Cold support */
- if (i == ACPI_STATE_D3) {
- status = acpi_get_handle(device->handle, object_name, &handle);
- if (ACPI_SUCCESS(status))
- device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1;
- }
-
/* Evaluate "_PSx" to see if we can do explicit sets */
object_name[2] = 'S';
status = acpi_get_handle(device->handle, object_name, &handle);
if (ACPI_SUCCESS(status))
ps->flags.explicit_set = 1;
- /* State is valid if we have some power control */
- if (ps->resources.count || ps->flags.explicit_set)
+ /*
+ * State is valid if there are means to put the device into it.
+ * D3hot is only valid if _PR3 present.
+ */
+ if (ps->resources.count ||
+ (ps->flags.explicit_set && i < ACPI_STATE_D3_HOT))
ps->flags.valid = 1;
ps->power = -1; /* Unknown - driver assigned */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 1d661b5..eb6fd23 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -28,24 +28,34 @@
#include "internal.h"
#include "sleep.h"
+u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS;
static unsigned int gts, bfs;
-module_param(gts, uint, 0644);
-module_param(bfs, uint, 0644);
+static int set_param_wake_flag(const char *val, struct kernel_param *kp)
+{
+ int ret = param_set_int(val, kp);
+
+ if (ret)
+ return ret;
+
+ if (kp->arg == (const char *)>s) {
+ if (gts)
+ wake_sleep_flags |= ACPI_EXECUTE_GTS;
+ else
+ wake_sleep_flags &= ~ACPI_EXECUTE_GTS;
+ }
+ if (kp->arg == (const char *)&bfs) {
+ if (bfs)
+ wake_sleep_flags |= ACPI_EXECUTE_BFS;
+ else
+ wake_sleep_flags &= ~ACPI_EXECUTE_BFS;
+ }
+ return ret;
+}
+module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644);
+module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644);
MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend.");
MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".);
-static u8 wake_sleep_flags(void)
-{
- u8 flags = ACPI_NO_OPTIONAL_METHODS;
-
- if (gts)
- flags |= ACPI_EXECUTE_GTS;
- if (bfs)
- flags |= ACPI_EXECUTE_BFS;
-
- return flags;
-}
-
static u8 sleep_states[ACPI_S_STATE_COUNT];
static void acpi_sleep_tts_switch(u32 acpi_state)
@@ -263,7 +273,6 @@
{
acpi_status status = AE_OK;
u32 acpi_state = acpi_target_sleep_state;
- u8 flags = wake_sleep_flags();
int error;
ACPI_FLUSH_CPU_CACHE();
@@ -271,7 +280,7 @@
switch (acpi_state) {
case ACPI_STATE_S1:
barrier();
- status = acpi_enter_sleep_state(acpi_state, flags);
+ status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags);
break;
case ACPI_STATE_S3:
@@ -286,7 +295,7 @@
acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1);
/* Reprogram control registers and execute _BFS */
- acpi_leave_sleep_state_prep(acpi_state, flags);
+ acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags);
/* ACPI 3.0 specs (P62) says that it's the responsibility
* of the OSPM to clear the status bit [ implying that the
@@ -550,30 +559,27 @@
static int acpi_hibernation_enter(void)
{
- u8 flags = wake_sleep_flags();
acpi_status status = AE_OK;
ACPI_FLUSH_CPU_CACHE();
/* This shouldn't return. If it returns, we have a problem */
- status = acpi_enter_sleep_state(ACPI_STATE_S4, flags);
+ status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags);
/* Reprogram control registers and execute _BFS */
- acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
+ acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags);
return ACPI_SUCCESS(status) ? 0 : -EFAULT;
}
static void acpi_hibernation_leave(void)
{
- u8 flags = wake_sleep_flags();
-
/*
* If ACPI is not enabled by the BIOS and the boot kernel, we need to
* enable it here.
*/
acpi_enable();
/* Reprogram control registers and execute _BFS */
- acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags);
+ acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags);
/* Check the hardware signature */
if (facs && s4_hardware_signature != facs->hardware_signature) {
printk(KERN_EMERG "ACPI: Hardware changed while hibernated, "
@@ -828,12 +834,10 @@
static void acpi_power_off(void)
{
- u8 flags = wake_sleep_flags();
-
/* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */
printk(KERN_DEBUG "%s called\n", __func__);
local_irq_disable();
- acpi_enter_sleep_state(ACPI_STATE_S5, flags);
+ acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags);
}
/*
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 01c2cf4..cc27322 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -247,8 +247,7 @@
/*
* Hooks to provide runtime PM of the pclk (bus clock). It is safe to
* enable/disable the bus clock at runtime PM suspend/resume as this
- * does not result in loss of context. However, disabling vcore power
- * would do, so we leave that to the driver.
+ * does not result in loss of context.
*/
static int amba_pm_runtime_suspend(struct device *dev)
{
@@ -354,39 +353,6 @@
clk_put(pclk);
}
-static int amba_get_enable_vcore(struct amba_device *pcdev)
-{
- struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
- int ret;
-
- pcdev->vcore = vcore;
-
- if (IS_ERR(vcore)) {
- /* It is OK not to supply a vcore regulator */
- if (PTR_ERR(vcore) == -ENODEV)
- return 0;
- return PTR_ERR(vcore);
- }
-
- ret = regulator_enable(vcore);
- if (ret) {
- regulator_put(vcore);
- pcdev->vcore = ERR_PTR(-ENODEV);
- }
-
- return ret;
-}
-
-static void amba_put_disable_vcore(struct amba_device *pcdev)
-{
- struct regulator *vcore = pcdev->vcore;
-
- if (!IS_ERR(vcore)) {
- regulator_disable(vcore);
- regulator_put(vcore);
- }
-}
-
/*
* These are the device model conversion veneers; they convert the
* device model structures to our more specific structures.
@@ -399,10 +365,6 @@
int ret;
do {
- ret = amba_get_enable_vcore(pcdev);
- if (ret)
- break;
-
ret = amba_get_enable_pclk(pcdev);
if (ret)
break;
@@ -420,7 +382,6 @@
pm_runtime_put_noidle(dev);
amba_put_disable_pclk(pcdev);
- amba_put_disable_vcore(pcdev);
} while (0);
return ret;
@@ -442,7 +403,6 @@
pm_runtime_put_noidle(dev);
amba_put_disable_pclk(pcdev);
- amba_put_disable_vcore(pcdev);
return ret;
}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 79a1e9d..ebaf67e 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -394,6 +394,8 @@
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
{ PCI_DEVICE(0x1b4b, 0x9125),
.driver_data = board_ahci_yes_fbs }, /* 88se9125 */
+ { PCI_DEVICE(0x1b4b, 0x917a),
+ .driver_data = board_ahci_yes_fbs }, /* 88se9172 */
{ PCI_DEVICE(0x1b4b, 0x91a3),
.driver_data = board_ahci_yes_fbs },
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 0c86c77..9e419e1 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -280,6 +280,7 @@
static const struct of_device_id ahci_of_match[] = {
{ .compatible = "calxeda,hb-ahci", },
+ { .compatible = "snps,spear-ahci", },
{},
};
MODULE_DEVICE_TABLE(of, ahci_of_match);
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index 68013f9..7857e8f 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -329,6 +329,8 @@
{ 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Lynx Point) */
{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ /* SATA Controller IDE (DH89xxCC) */
+ { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
{ } /* terminate list */
};
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e0bda9f..23763a1 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -95,7 +95,7 @@
static void ata_dev_xfermask(struct ata_device *dev);
static unsigned long ata_dev_blacklisted(const struct ata_device *dev);
-unsigned int ata_print_id = 1;
+atomic_t ata_print_id = ATOMIC_INIT(0);
struct ata_force_param {
const char *name;
@@ -6029,7 +6029,7 @@
/* give ports names and add SCSI hosts */
for (i = 0; i < host->n_ports; i++)
- host->ports[i]->print_id = ata_print_id++;
+ host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
/* Create associated sysfs transport objects */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index c61316e..d1fbd59 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3501,7 +3501,8 @@
u64 now = get_jiffies_64();
int *trials = void_arg;
- if (ent->timestamp < now - min(now, interval))
+ if ((ent->eflags & ATA_EFLAG_OLD_ER) ||
+ (ent->timestamp < now - min(now, interval)))
return -1;
(*trials)++;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 1ee00c8..2222635 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3399,7 +3399,8 @@
*/
shost->max_host_blocked = 1;
- rc = scsi_add_host(ap->scsi_host, &ap->tdev);
+ rc = scsi_add_host_with_dma(ap->scsi_host,
+ &ap->tdev, ap->host->dev);
if (rc)
goto err_add;
}
@@ -3838,18 +3839,25 @@
}
EXPORT_SYMBOL_GPL(ata_sas_port_stop);
-int ata_sas_async_port_init(struct ata_port *ap)
+/**
+ * ata_sas_async_probe - simply schedule probing and return
+ * @ap: Port to probe
+ *
+ * For batch scheduling of probe for sas attached ata devices, assumes
+ * the port has already been through ata_sas_port_init()
+ */
+void ata_sas_async_probe(struct ata_port *ap)
{
- int rc = ap->ops->port_start(ap);
-
- if (!rc) {
- ap->print_id = ata_print_id++;
- __ata_port_probe(ap);
- }
-
- return rc;
+ __ata_port_probe(ap);
}
-EXPORT_SYMBOL_GPL(ata_sas_async_port_init);
+EXPORT_SYMBOL_GPL(ata_sas_async_probe);
+
+int ata_sas_sync_probe(struct ata_port *ap)
+{
+ return ata_port_probe(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_sync_probe);
+
/**
* ata_sas_port_init - Initialize a SATA device
@@ -3866,12 +3874,10 @@
{
int rc = ap->ops->port_start(ap);
- if (!rc) {
- ap->print_id = ata_print_id++;
- rc = ata_port_probe(ap);
- }
-
- return rc;
+ if (rc)
+ return rc;
+ ap->print_id = atomic_inc_return(&ata_print_id);
+ return 0;
}
EXPORT_SYMBOL_GPL(ata_sas_port_init);
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index 74aaee3..c341904 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -294,6 +294,7 @@
device_enable_async_suspend(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
+ pm_runtime_forbid(dev);
transport_add_device(dev);
transport_configure_device(dev);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 2e26fca..9d0fd0b 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -53,7 +53,7 @@
ATA_DNXFER_QUIET = (1 << 31),
};
-extern unsigned int ata_print_id;
+extern atomic_t ata_print_id;
extern int atapi_passthru16;
extern int libata_fua;
extern int libata_noacpi;
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c
index fc2db2a..3239517f 100644
--- a/drivers/ata/pata_arasan_cf.c
+++ b/drivers/ata/pata_arasan_cf.c
@@ -943,9 +943,9 @@
return 0;
}
+#endif
static SIMPLE_DEV_PM_OPS(arasan_cf_pm_ops, arasan_cf_suspend, arasan_cf_resume);
-#endif
static struct platform_driver arasan_cf_driver = {
.probe = arasan_cf_probe,
@@ -953,9 +953,7 @@
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
-#ifdef CONFIG_PM
.pm = &arasan_cf_pm_ops,
-#endif
},
};
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 38950ea..7336d4a 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4025,7 +4025,8 @@
struct ata_host *host;
struct mv_host_priv *hpriv;
struct resource *res;
- int n_ports, rc;
+ int n_ports = 0;
+ int rc;
ata_print_version_once(&pdev->dev, DRV_VERSION);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 6c9387d..5401814 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -16,10 +16,11 @@
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
#include <linux/highmem.h>
#include <linux/firmware.h>
#include <linux/slab.h>
+#include <linux/sched.h>
#define to_dev(obj) container_of(obj, struct device, kobj)
@@ -81,6 +82,11 @@
static int loading_timeout = 60; /* In seconds */
+static inline long firmware_loading_timeout(void)
+{
+ return loading_timeout > 0 ? loading_timeout * HZ : MAX_SCHEDULE_TIMEOUT;
+}
+
/* fw_lock could be moved to 'struct firmware_priv' but since it is just
* guarding for corner cases a global lock should be OK */
static DEFINE_MUTEX(fw_lock);
@@ -440,13 +446,11 @@
{
struct firmware_priv *fw_priv;
struct device *f_dev;
- int error;
fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL);
if (!fw_priv) {
dev_err(device, "%s: kmalloc failed\n", __func__);
- error = -ENOMEM;
- goto err_out;
+ return ERR_PTR(-ENOMEM);
}
fw_priv->fw = firmware;
@@ -463,98 +467,80 @@
f_dev->parent = device;
f_dev->class = &firmware_class;
- dev_set_uevent_suppress(f_dev, true);
-
- /* Need to pin this module until class device is destroyed */
- __module_get(THIS_MODULE);
-
- error = device_add(f_dev);
- if (error) {
- dev_err(device, "%s: device_register failed\n", __func__);
- goto err_put_dev;
- }
-
- error = device_create_bin_file(f_dev, &firmware_attr_data);
- if (error) {
- dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__);
- goto err_del_dev;
- }
-
- error = device_create_file(f_dev, &dev_attr_loading);
- if (error) {
- dev_err(device, "%s: device_create_file failed\n", __func__);
- goto err_del_bin_attr;
- }
-
- if (uevent)
- dev_set_uevent_suppress(f_dev, false);
-
return fw_priv;
-
-err_del_bin_attr:
- device_remove_bin_file(f_dev, &firmware_attr_data);
-err_del_dev:
- device_del(f_dev);
-err_put_dev:
- put_device(f_dev);
-err_out:
- return ERR_PTR(error);
}
-static void fw_destroy_instance(struct firmware_priv *fw_priv)
+static struct firmware_priv *
+_request_firmware_prepare(const struct firmware **firmware_p, const char *name,
+ struct device *device, bool uevent, bool nowait)
{
- struct device *f_dev = &fw_priv->dev;
-
- device_remove_file(f_dev, &dev_attr_loading);
- device_remove_bin_file(f_dev, &firmware_attr_data);
- device_unregister(f_dev);
-}
-
-static int _request_firmware(const struct firmware **firmware_p,
- const char *name, struct device *device,
- bool uevent, bool nowait)
-{
- struct firmware_priv *fw_priv;
struct firmware *firmware;
- int retval = 0;
+ struct firmware_priv *fw_priv;
if (!firmware_p)
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
*firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
dev_err(device, "%s: kmalloc(struct firmware) failed\n",
__func__);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
if (fw_get_builtin_firmware(firmware, name)) {
dev_dbg(device, "firmware: using built-in firmware %s\n", name);
- return 0;
+ return NULL;
}
- read_lock_usermodehelper();
-
- if (WARN_ON(usermodehelper_is_disabled())) {
- dev_err(device, "firmware: %s will not be loaded\n", name);
- retval = -EBUSY;
- goto out;
- }
-
- if (uevent)
- dev_dbg(device, "firmware: requesting %s\n", name);
-
fw_priv = fw_create_instance(firmware, name, device, uevent, nowait);
if (IS_ERR(fw_priv)) {
- retval = PTR_ERR(fw_priv);
- goto out;
+ release_firmware(firmware);
+ *firmware_p = NULL;
+ }
+ return fw_priv;
+}
+
+static void _request_firmware_cleanup(const struct firmware **firmware_p)
+{
+ release_firmware(*firmware_p);
+ *firmware_p = NULL;
+}
+
+static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
+ long timeout)
+{
+ int retval = 0;
+ struct device *f_dev = &fw_priv->dev;
+
+ dev_set_uevent_suppress(f_dev, true);
+
+ /* Need to pin this module until class device is destroyed */
+ __module_get(THIS_MODULE);
+
+ retval = device_add(f_dev);
+ if (retval) {
+ dev_err(f_dev, "%s: device_register failed\n", __func__);
+ goto err_put_dev;
+ }
+
+ retval = device_create_bin_file(f_dev, &firmware_attr_data);
+ if (retval) {
+ dev_err(f_dev, "%s: sysfs_create_bin_file failed\n", __func__);
+ goto err_del_dev;
+ }
+
+ retval = device_create_file(f_dev, &dev_attr_loading);
+ if (retval) {
+ dev_err(f_dev, "%s: device_create_file failed\n", __func__);
+ goto err_del_bin_attr;
}
if (uevent) {
- if (loading_timeout > 0)
+ dev_set_uevent_suppress(f_dev, false);
+ dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id);
+ if (timeout != MAX_SCHEDULE_TIMEOUT)
mod_timer(&fw_priv->timeout,
- round_jiffies_up(jiffies +
- loading_timeout * HZ));
+ round_jiffies_up(jiffies + timeout));
kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
}
@@ -570,16 +556,13 @@
fw_priv->fw = NULL;
mutex_unlock(&fw_lock);
- fw_destroy_instance(fw_priv);
-
-out:
- read_unlock_usermodehelper();
-
- if (retval) {
- release_firmware(firmware);
- *firmware_p = NULL;
- }
-
+ device_remove_file(f_dev, &dev_attr_loading);
+err_del_bin_attr:
+ device_remove_bin_file(f_dev, &firmware_attr_data);
+err_del_dev:
+ device_del(f_dev);
+err_put_dev:
+ put_device(f_dev);
return retval;
}
@@ -602,7 +585,26 @@
request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device)
{
- return _request_firmware(firmware_p, name, device, true, false);
+ struct firmware_priv *fw_priv;
+ int ret;
+
+ fw_priv = _request_firmware_prepare(firmware_p, name, device, true,
+ false);
+ if (IS_ERR_OR_NULL(fw_priv))
+ return PTR_RET(fw_priv);
+
+ ret = usermodehelper_read_trylock();
+ if (WARN_ON(ret)) {
+ dev_err(device, "firmware: %s will not be loaded\n", name);
+ } else {
+ ret = _request_firmware_load(fw_priv, true,
+ firmware_loading_timeout());
+ usermodehelper_read_unlock();
+ }
+ if (ret)
+ _request_firmware_cleanup(firmware_p);
+
+ return ret;
}
/**
@@ -629,25 +631,39 @@
bool uevent;
};
-static int request_firmware_work_func(void *arg)
+static void request_firmware_work_func(struct work_struct *work)
{
- struct firmware_work *fw_work = arg;
+ struct firmware_work *fw_work;
const struct firmware *fw;
+ struct firmware_priv *fw_priv;
+ long timeout;
int ret;
- if (!arg) {
- WARN_ON(1);
- return 0;
+ fw_work = container_of(work, struct firmware_work, work);
+ fw_priv = _request_firmware_prepare(&fw, fw_work->name, fw_work->device,
+ fw_work->uevent, true);
+ if (IS_ERR_OR_NULL(fw_priv)) {
+ ret = PTR_RET(fw_priv);
+ goto out;
}
- ret = _request_firmware(&fw, fw_work->name, fw_work->device,
- fw_work->uevent, true);
+ timeout = usermodehelper_read_lock_wait(firmware_loading_timeout());
+ if (timeout) {
+ ret = _request_firmware_load(fw_priv, fw_work->uevent, timeout);
+ usermodehelper_read_unlock();
+ } else {
+ dev_dbg(fw_work->device, "firmware: %s loading timed out\n",
+ fw_work->name);
+ ret = -EAGAIN;
+ }
+ if (ret)
+ _request_firmware_cleanup(&fw);
+
+ out:
fw_work->cont(fw, fw_work->context);
module_put(fw_work->module);
kfree(fw_work);
-
- return ret;
}
/**
@@ -673,7 +689,6 @@
const char *name, struct device *device, gfp_t gfp, void *context,
void (*cont)(const struct firmware *fw, void *context))
{
- struct task_struct *task;
struct firmware_work *fw_work;
fw_work = kzalloc(sizeof (struct firmware_work), gfp);
@@ -692,15 +707,8 @@
return -EFAULT;
}
- task = kthread_run(request_firmware_work_func, fw_work,
- "firmware/%s", name);
- if (IS_ERR(task)) {
- fw_work->cont(NULL, fw_work->context);
- module_put(fw_work->module);
- kfree(fw_work);
- return PTR_ERR(task);
- }
-
+ INIT_WORK(&fw_work->work, request_firmware_work_func);
+ schedule_work(&fw_work->work);
return 0;
}
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 541f821..bd0f394 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -532,6 +532,8 @@
dev->power.suspend_time = ktime_set(0, 0);
dev->power.max_time_suspended_ns = -1;
dev->power.deferred_resume = false;
+ wake_up_all(&dev->power.wait_queue);
+
if (retval == -EAGAIN || retval == -EBUSY) {
dev->power.runtime_error = 0;
@@ -547,7 +549,6 @@
} else {
pm_runtime_cancel_pending(dev);
}
- wake_up_all(&dev->power.wait_queue);
goto out;
}
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 5157fa0..92b779e 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -138,6 +138,7 @@
unsigned int base, top;
int nodes = 0;
int registers = 0;
+ int average;
mutex_lock(&map->lock);
@@ -152,8 +153,13 @@
registers += top - base + 1;
}
+ if (nodes)
+ average = registers / nodes;
+ else
+ average = 0;
+
seq_printf(s, "%d nodes, %d registers, average %d registers\n",
- nodes, registers, registers / nodes);
+ nodes, registers, average);
mutex_unlock(&map->lock);
@@ -396,7 +402,7 @@
map->cache_word_size);
/* Is this the hardware default? If so skip. */
- ret = regcache_lookup_reg(map, i);
+ ret = regcache_lookup_reg(map, regtmp);
if (ret >= 0 && val == map->reg_defaults[ret].def)
continue;
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 87f54db..74b6909 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -346,6 +346,7 @@
return ret;
}
+EXPORT_SYMBOL_GPL(regcache_sync_region);
/**
* regcache_cache_only: Put a register map into cache only mode
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 58517a5..251eb70 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -27,12 +27,6 @@
return strlen(buf);
}
-static int regmap_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t regmap_name_read_file(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos)
@@ -57,7 +51,7 @@
}
static const struct file_operations regmap_name_fops = {
- .open = regmap_open_file,
+ .open = simple_open,
.read = regmap_name_read_file,
.llseek = default_llseek,
};
@@ -174,7 +168,7 @@
#endif
static const struct file_operations regmap_map_fops = {
- .open = regmap_open_file,
+ .open = simple_open,
.read = regmap_map_read_file,
.write = regmap_map_write_file,
.llseek = default_llseek,
@@ -243,7 +237,7 @@
}
static const struct file_operations regmap_access_fops = {
- .open = regmap_open_file,
+ .open = simple_open,
.read = regmap_access_read_file,
.llseek = default_llseek,
};
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 7a3f535..bb80853 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -775,9 +775,11 @@
map->format.parse_val(val + i);
} else {
for (i = 0; i < val_count; i++) {
- ret = regmap_read(map, reg + i, val + (i * val_bytes));
+ unsigned int ival;
+ ret = regmap_read(map, reg + i, &ival);
if (ret != 0)
return ret;
+ memcpy(val + (i * val_bytes), &ival, val_bytes);
}
}
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index 05f1503..ba29b2e 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -15,7 +15,7 @@
#include <linux/sys_soc.h>
#include <linux/err.h>
-static DEFINE_IDR(soc_ida);
+static DEFINE_IDA(soc_ida);
static DEFINE_SPINLOCK(soc_lock);
static ssize_t soc_info_get(struct device *dev,
@@ -168,8 +168,6 @@
static int __init soc_bus_register(void)
{
- spin_lock_init(&soc_lock);
-
return bus_register(&soc_bus_type);
}
core_initcall(soc_bus_register);
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index c1172da..fb7c80f 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -29,7 +29,7 @@
config BCMA_DRIVER_PCI_HOSTMODE
bool "Driver for PCI core working in hostmode"
- depends on BCMA && MIPS
+ depends on BCMA && MIPS && BCMA_HOST_PCI
help
PCI core hostmode operation (external PCI bus).
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index 4e20bcf..d2097a1 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -10,6 +10,7 @@
*/
#include "bcma_private.h"
+#include <linux/pci.h>
#include <linux/export.h>
#include <linux/bcma/bcma.h>
#include <asm/paccess.h>
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
index cdcf75c..3e2a600 100644
--- a/drivers/bcma/sprom.c
+++ b/drivers/bcma/sprom.c
@@ -404,16 +404,19 @@
return -EOPNOTSUPP;
if (!bcma_sprom_ext_available(bus)) {
+ bool sprom_onchip;
+
/*
* External SPROM takes precedence so check
* on-chip OTP only when no external SPROM
* is present.
*/
- if (bcma_sprom_onchip_available(bus)) {
+ sprom_onchip = bcma_sprom_onchip_available(bus);
+ if (sprom_onchip) {
/* determine offset */
offset = bcma_sprom_onchip_offset(bus);
}
- if (!offset) {
+ if (!offset || !sprom_onchip) {
/*
* Maybe there is no SPROM on the device?
* Now we ask the arch code if there is some sprom
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index e820b68..acda773 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -866,6 +866,7 @@
sh->can_queue = cciss_tape_cmds;
sh->sg_tablesize = h->maxsgentries;
sh->max_cmd_len = MAX_COMMAND_SIZE;
+ sh->max_sectors = h->cciss_max_sectors;
((struct cciss_scsi_adapter_data_t *)
h->scsi_ctlr)->scsi_host = sh;
@@ -1410,7 +1411,7 @@
/* track how many SG entries we are using */
if (request_nsgs > h->maxSG)
h->maxSG = request_nsgs;
- c->Header.SGTotal = (__u8) request_nsgs + chained;
+ c->Header.SGTotal = (u16) request_nsgs + chained;
if (request_nsgs > h->max_cmd_sgentries)
c->Header.SGList = h->max_cmd_sgentries;
else
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 76a0823..b0b00d7 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -1030,37 +1030,6 @@
return 0;
}
-static DEFINE_SPINLOCK(floppy_hlt_lock);
-static int hlt_disabled;
-static void floppy_disable_hlt(void)
-{
- unsigned long flags;
-
- WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012");
- spin_lock_irqsave(&floppy_hlt_lock, flags);
- if (!hlt_disabled) {
- hlt_disabled = 1;
-#ifdef HAVE_DISABLE_HLT
- disable_hlt();
-#endif
- }
- spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
-static void floppy_enable_hlt(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&floppy_hlt_lock, flags);
- if (hlt_disabled) {
- hlt_disabled = 0;
-#ifdef HAVE_DISABLE_HLT
- enable_hlt();
-#endif
- }
- spin_unlock_irqrestore(&floppy_hlt_lock, flags);
-}
-
static void setup_DMA(void)
{
unsigned long f;
@@ -1105,7 +1074,6 @@
fd_enable_dma();
release_dma_lock(f);
#endif
- floppy_disable_hlt();
}
static void show_floppy(void);
@@ -1707,7 +1675,6 @@
fd_disable_dma();
release_dma_lock(f);
- floppy_enable_hlt();
do_floppy = NULL;
if (fdc >= N_FDC || FDCS->address == -1) {
/* we don't even know which FDC is the culprit */
@@ -1856,8 +1823,6 @@
show_floppy();
cancel_activity();
- floppy_enable_hlt();
-
flags = claim_dma_lock();
fd_disable_dma();
release_dma_lock(flags);
@@ -4508,7 +4473,6 @@
#if N_FDC > 1
set_dor(1, ~8, 0);
#endif
- floppy_enable_hlt();
if (floppy_track_buffer && max_buffer_sectors) {
tmpsize = max_buffer_sectors * 1024;
diff --git a/drivers/block/mtip32xx/Kconfig b/drivers/block/mtip32xx/Kconfig
index b5dd14e..0ba837f 100644
--- a/drivers/block/mtip32xx/Kconfig
+++ b/drivers/block/mtip32xx/Kconfig
@@ -4,6 +4,6 @@
config BLK_DEV_PCIESSD_MTIP32XX
tristate "Block Device Driver for Micron PCIe SSDs"
- depends on HOTPLUG_PCI_PCIE
+ depends on PCI
help
This enables the block driver for Micron PCIe SSDs.
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 8eb81c9..00f9fc9 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -36,6 +36,7 @@
#include <linux/idr.h>
#include <linux/kthread.h>
#include <../drivers/ata/ahci.h>
+#include <linux/export.h>
#include "mtip32xx.h"
#define HW_CMD_SLOT_SZ (MTIP_MAX_COMMAND_SLOTS * 32)
@@ -44,6 +45,7 @@
#define HW_PORT_PRIV_DMA_SZ \
(HW_CMD_SLOT_SZ + HW_CMD_TBL_AR_SZ + AHCI_RX_FIS_SZ)
+#define HOST_CAP_NZDMA (1 << 19)
#define HOST_HSORG 0xFC
#define HSORG_DISABLE_SLOTGRP_INTR (1<<24)
#define HSORG_DISABLE_SLOTGRP_PXIS (1<<16)
@@ -139,6 +141,12 @@
int group = 0, commandslot = 0, commandindex = 0;
struct mtip_cmd *command;
struct mtip_port *port = dd->port;
+ static int in_progress;
+
+ if (in_progress)
+ return;
+
+ in_progress = 1;
for (group = 0; group < 4; group++) {
for (commandslot = 0; commandslot < 32; commandslot++) {
@@ -165,7 +173,8 @@
up(&port->cmd_slot);
- atomic_set(&dd->drv_cleanup_done, true);
+ set_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag);
+ in_progress = 0;
}
/*
@@ -262,6 +271,9 @@
&& time_before(jiffies, timeout))
mdelay(1);
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
+ return -1;
+
if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
return -1;
@@ -294,6 +306,10 @@
port->cmd_issue[MTIP_TAG_INDEX(tag)]);
spin_unlock_irqrestore(&port->cmd_issue_lock, flags);
+
+ /* Set the command's timeout value.*/
+ port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
+ MTIP_NCQ_COMMAND_TIMEOUT_MS);
}
/*
@@ -420,7 +436,12 @@
writel(0xFFFFFFFF, port->completed[i]);
/* Clear any pending interrupts for this port */
- writel(readl(port->mmio + PORT_IRQ_STAT), port->mmio + PORT_IRQ_STAT);
+ writel(readl(port->dd->mmio + PORT_IRQ_STAT),
+ port->dd->mmio + PORT_IRQ_STAT);
+
+ /* Clear any pending interrupts on the HBA. */
+ writel(readl(port->dd->mmio + HOST_IRQ_STAT),
+ port->dd->mmio + HOST_IRQ_STAT);
/* Enable port interrupts */
writel(DEF_PORT_IRQ, port->mmio + PORT_IRQ_MASK);
@@ -447,6 +468,9 @@
&& time_before(jiffies, timeout))
;
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+ return;
+
/*
* Chip quirk: escalate to hba reset if
* PxCMD.CR not clear after 500 ms
@@ -475,6 +499,9 @@
while (time_before(jiffies, timeout))
;
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+ return;
+
/* Clear PxSCTL.DET */
writel(readl(port->mmio + PORT_SCR_CTL) & ~1,
port->mmio + PORT_SCR_CTL);
@@ -486,15 +513,35 @@
&& time_before(jiffies, timeout))
;
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+ return;
+
if ((readl(port->mmio + PORT_SCR_STAT) & 0x01) == 0)
dev_warn(&port->dd->pdev->dev,
"COM reset failed\n");
- /* Clear SError, the PxSERR.DIAG.x should be set so clear it */
- writel(readl(port->mmio + PORT_SCR_ERR), port->mmio + PORT_SCR_ERR);
+ mtip_init_port(port);
+ mtip_start_port(port);
- /* Enable the DMA engine */
- mtip_enable_engine(port, 1);
+}
+
+/*
+ * Helper function for tag logging
+ */
+static void print_tags(struct driver_data *dd,
+ char *msg,
+ unsigned long *tagbits,
+ int cnt)
+{
+ unsigned char tagmap[128];
+ int group, tagmap_len = 0;
+
+ memset(tagmap, 0, sizeof(tagmap));
+ for (group = SLOTBITS_IN_LONGS; group > 0; group--)
+ tagmap_len = sprintf(tagmap + tagmap_len, "%016lX ",
+ tagbits[group-1]);
+ dev_warn(&dd->pdev->dev,
+ "%d command(s) %s: tagmap [%s]", cnt, msg, tagmap);
}
/*
@@ -514,15 +561,18 @@
int tag, cmdto_cnt = 0;
unsigned int bit, group;
unsigned int num_command_slots = port->dd->slot_groups * 32;
+ unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
if (unlikely(!port))
return;
- if (atomic_read(&port->dd->resumeflag) == true) {
+ if (test_bit(MTIP_DDF_RESUME_BIT, &port->dd->dd_flag)) {
mod_timer(&port->cmd_timer,
jiffies + msecs_to_jiffies(30000));
return;
}
+ /* clear the tag accumulator */
+ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
for (tag = 0; tag < num_command_slots; tag++) {
/*
@@ -540,12 +590,10 @@
command = &port->commands[tag];
fis = (struct host_to_dev_fis *) command->command;
- dev_warn(&port->dd->pdev->dev,
- "Timeout for command tag %d\n", tag);
-
+ set_bit(tag, tagaccum);
cmdto_cnt++;
if (cmdto_cnt == 1)
- set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
/*
* Clear the completed bit. This should prevent
@@ -578,15 +626,29 @@
}
}
- if (cmdto_cnt) {
- dev_warn(&port->dd->pdev->dev,
- "%d commands timed out: restarting port",
- cmdto_cnt);
+ if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+ print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
+
mtip_restart_port(port);
- clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
wake_up_interruptible(&port->svc_wait);
}
+ if (port->ic_pause_timer) {
+ to = port->ic_pause_timer + msecs_to_jiffies(1000);
+ if (time_after(jiffies, to)) {
+ if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
+ port->ic_pause_timer = 0;
+ clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+ }
+
+
+ }
+ }
+
/* Restart the timer */
mod_timer(&port->cmd_timer,
jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
@@ -681,23 +743,18 @@
complete(waiting);
}
-/*
- * Helper function for tag logging
- */
-static void print_tags(struct driver_data *dd,
- char *msg,
- unsigned long *tagbits)
+static void mtip_null_completion(struct mtip_port *port,
+ int tag,
+ void *data,
+ int status)
{
- unsigned int tag, count = 0;
-
- for (tag = 0; tag < (dd->slot_groups) * 32; tag++) {
- if (test_bit(tag, tagbits))
- count++;
- }
- if (count)
- dev_info(&dd->pdev->dev, "%s [%i tags]\n", msg, count);
+ return;
}
+static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
+ dma_addr_t buffer_dma, unsigned int sectors);
+static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
+ struct smart_attr *attrib);
/*
* Handle an error.
*
@@ -708,12 +765,16 @@
*/
static void mtip_handle_tfe(struct driver_data *dd)
{
- int group, tag, bit, reissue;
+ int group, tag, bit, reissue, rv;
struct mtip_port *port;
- struct mtip_cmd *command;
+ struct mtip_cmd *cmd;
u32 completed;
struct host_to_dev_fis *fis;
unsigned long tagaccum[SLOTBITS_IN_LONGS];
+ unsigned int cmd_cnt = 0;
+ unsigned char *buf;
+ char *fail_reason = NULL;
+ int fail_all_ncq_write = 0, fail_all_ncq_cmds = 0;
dev_warn(&dd->pdev->dev, "Taskfile error\n");
@@ -722,8 +783,11 @@
/* Stop the timer to prevent command timeouts. */
del_timer(&port->cmd_timer);
+ /* clear the tag accumulator */
+ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+
/* Set eh_active */
- set_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
/* Loop through all the groups */
for (group = 0; group < dd->slot_groups; group++) {
@@ -732,9 +796,6 @@
/* clear completed status register in the hardware.*/
writel(completed, port->completed[group]);
- /* clear the tag accumulator */
- memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
-
/* Process successfully completed commands */
for (bit = 0; bit < 32 && completed; bit++) {
if (!(completed & (1<<bit)))
@@ -745,13 +806,14 @@
if (tag == MTIP_TAG_INTERNAL)
continue;
- command = &port->commands[tag];
- if (likely(command->comp_func)) {
+ cmd = &port->commands[tag];
+ if (likely(cmd->comp_func)) {
set_bit(tag, tagaccum);
- atomic_set(&port->commands[tag].active, 0);
- command->comp_func(port,
+ cmd_cnt++;
+ atomic_set(&cmd->active, 0);
+ cmd->comp_func(port,
tag,
- command->comp_data,
+ cmd->comp_data,
0);
} else {
dev_err(&port->dd->pdev->dev,
@@ -765,12 +827,45 @@
}
}
}
- print_tags(dd, "TFE tags completed:", tagaccum);
+
+ print_tags(dd, "completed (TFE)", tagaccum, cmd_cnt);
/* Restart the port */
mdelay(20);
mtip_restart_port(port);
+ /* Trying to determine the cause of the error */
+ rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
+ dd->port->log_buf,
+ dd->port->log_buf_dma, 1);
+ if (rv) {
+ dev_warn(&dd->pdev->dev,
+ "Error in READ LOG EXT (10h) command\n");
+ /* non-critical error, don't fail the load */
+ } else {
+ buf = (unsigned char *)dd->port->log_buf;
+ if (buf[259] & 0x1) {
+ dev_info(&dd->pdev->dev,
+ "Write protect bit is set.\n");
+ set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag);
+ fail_all_ncq_write = 1;
+ fail_reason = "write protect";
+ }
+ if (buf[288] == 0xF7) {
+ dev_info(&dd->pdev->dev,
+ "Exceeded Tmax, drive in thermal shutdown.\n");
+ set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag);
+ fail_all_ncq_cmds = 1;
+ fail_reason = "thermal shutdown";
+ }
+ if (buf[288] == 0xBF) {
+ dev_info(&dd->pdev->dev,
+ "Drive indicates rebuild has failed.\n");
+ fail_all_ncq_cmds = 1;
+ fail_reason = "rebuild failed";
+ }
+ }
+
/* clear the tag accumulator */
memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
@@ -779,32 +874,47 @@
for (bit = 0; bit < 32; bit++) {
reissue = 1;
tag = (group << 5) + bit;
+ cmd = &port->commands[tag];
/* If the active bit is set re-issue the command */
- if (atomic_read(&port->commands[tag].active) == 0)
+ if (atomic_read(&cmd->active) == 0)
continue;
- fis = (struct host_to_dev_fis *)
- port->commands[tag].command;
+ fis = (struct host_to_dev_fis *)cmd->command;
/* Should re-issue? */
if (tag == MTIP_TAG_INTERNAL ||
fis->command == ATA_CMD_SET_FEATURES)
reissue = 0;
+ else {
+ if (fail_all_ncq_cmds ||
+ (fail_all_ncq_write &&
+ fis->command == ATA_CMD_FPDMA_WRITE)) {
+ dev_warn(&dd->pdev->dev,
+ " Fail: %s w/tag %d [%s].\n",
+ fis->command == ATA_CMD_FPDMA_WRITE ?
+ "write" : "read",
+ tag,
+ fail_reason != NULL ?
+ fail_reason : "unknown");
+ atomic_set(&cmd->active, 0);
+ if (cmd->comp_func) {
+ cmd->comp_func(port, tag,
+ cmd->comp_data,
+ -ENODATA);
+ }
+ continue;
+ }
+ }
/*
* First check if this command has
* exceeded its retries.
*/
- if (reissue &&
- (port->commands[tag].retries-- > 0)) {
+ if (reissue && (cmd->retries-- > 0)) {
set_bit(tag, tagaccum);
- /* Update the timeout value. */
- port->commands[tag].comp_time =
- jiffies + msecs_to_jiffies(
- MTIP_NCQ_COMMAND_TIMEOUT_MS);
/* Re-issue the command. */
mtip_issue_ncq_command(port, tag);
@@ -814,13 +924,13 @@
/* Retire a command that will not be reissued */
dev_warn(&port->dd->pdev->dev,
"retiring tag %d\n", tag);
- atomic_set(&port->commands[tag].active, 0);
+ atomic_set(&cmd->active, 0);
- if (port->commands[tag].comp_func)
- port->commands[tag].comp_func(
+ if (cmd->comp_func)
+ cmd->comp_func(
port,
tag,
- port->commands[tag].comp_data,
+ cmd->comp_data,
PORT_IRQ_TF_ERR);
else
dev_warn(&port->dd->pdev->dev,
@@ -828,10 +938,10 @@
tag);
}
}
- print_tags(dd, "TFE tags reissued:", tagaccum);
+ print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
/* clear eh_active */
- clear_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
wake_up_interruptible(&port->svc_wait);
mod_timer(&port->cmd_timer,
@@ -899,7 +1009,7 @@
struct mtip_port *port = dd->port;
struct mtip_cmd *cmd = &port->commands[MTIP_TAG_INTERNAL];
- if (test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
+ if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags) &&
(cmd != NULL) && !(readl(port->cmd_issue[MTIP_TAG_INTERNAL])
& (1 << MTIP_TAG_INTERNAL))) {
if (cmd->comp_func) {
@@ -911,8 +1021,6 @@
}
}
- dev_warn(&dd->pdev->dev, "IRQ status 0x%x ignored.\n", port_stat);
-
return;
}
@@ -968,6 +1076,9 @@
/* don't proceed further */
return IRQ_HANDLED;
}
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &dd->dd_flag))
+ return rv;
mtip_process_errors(dd, port_stat & PORT_IRQ_ERR);
}
@@ -1015,6 +1126,39 @@
port->cmd_issue[MTIP_TAG_INDEX(tag)]);
}
+static bool mtip_pause_ncq(struct mtip_port *port,
+ struct host_to_dev_fis *fis)
+{
+ struct host_to_dev_fis *reply;
+ unsigned long task_file_data;
+
+ reply = port->rxfis + RX_FIS_D2H_REG;
+ task_file_data = readl(port->mmio+PORT_TFDATA);
+
+ if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT))
+ return false;
+
+ if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
+ set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+ port->ic_pause_timer = jiffies;
+ return true;
+ } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
+ (fis->features == 0x03)) {
+ set_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
+ port->ic_pause_timer = jiffies;
+ return true;
+ } else if ((fis->command == ATA_CMD_SEC_ERASE_UNIT) ||
+ ((fis->command == 0xFC) &&
+ (fis->features == 0x27 || fis->features == 0x72 ||
+ fis->features == 0x62 || fis->features == 0x26))) {
+ /* Com reset after secure erase or lowlevel format */
+ mtip_restart_port(port);
+ return false;
+ }
+
+ return false;
+}
+
/*
* Wait for port to quiesce
*
@@ -1033,11 +1177,13 @@
to = jiffies + msecs_to_jiffies(timeout);
do {
- if (test_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags) &&
- test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+ if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
+ test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
msleep(20);
continue; /* svc thd is actively issuing commands */
}
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+ return -EFAULT;
/*
* Ignore s_active bit 0 of array element 0.
* This bit will always be set
@@ -1074,7 +1220,7 @@
* -EAGAIN Time out waiting for command to complete.
*/
static int mtip_exec_internal_command(struct mtip_port *port,
- void *fis,
+ struct host_to_dev_fis *fis,
int fis_len,
dma_addr_t buffer,
int buf_len,
@@ -1084,8 +1230,9 @@
{
struct mtip_cmd_sg *command_sg;
DECLARE_COMPLETION_ONSTACK(wait);
- int rv = 0;
+ int rv = 0, ready2go = 1;
struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
+ unsigned long to;
/* Make sure the buffer is 8 byte aligned. This is asic specific. */
if (buffer & 0x00000007) {
@@ -1094,23 +1241,38 @@
return -EFAULT;
}
- /* Only one internal command should be running at a time */
- if (test_and_set_bit(MTIP_TAG_INTERNAL, port->allocated)) {
+ to = jiffies + msecs_to_jiffies(timeout);
+ do {
+ ready2go = !test_and_set_bit(MTIP_TAG_INTERNAL,
+ port->allocated);
+ if (ready2go)
+ break;
+ mdelay(100);
+ } while (time_before(jiffies, to));
+ if (!ready2go) {
dev_warn(&port->dd->pdev->dev,
- "Internal command already active\n");
+ "Internal cmd active. new cmd [%02X]\n", fis->command);
return -EBUSY;
}
- set_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+ set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+ port->ic_pause_timer = 0;
+
+ if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
+ clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+ else if (fis->command == ATA_CMD_DOWNLOAD_MICRO)
+ clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
if (atomic == GFP_KERNEL) {
- /* wait for io to complete if non atomic */
- if (mtip_quiesce_io(port, 5000) < 0) {
- dev_warn(&port->dd->pdev->dev,
- "Failed to quiesce IO\n");
- release_slot(port, MTIP_TAG_INTERNAL);
- clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
- wake_up_interruptible(&port->svc_wait);
- return -EBUSY;
+ if (fis->command != ATA_CMD_STANDBYNOW1) {
+ /* wait for io to complete if non atomic */
+ if (mtip_quiesce_io(port, 5000) < 0) {
+ dev_warn(&port->dd->pdev->dev,
+ "Failed to quiesce IO\n");
+ release_slot(port, MTIP_TAG_INTERNAL);
+ clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
+ wake_up_interruptible(&port->svc_wait);
+ return -EBUSY;
+ }
}
/* Set the completion function and data for the command. */
@@ -1120,7 +1282,7 @@
} else {
/* Clear completion - we're going to poll */
int_cmd->comp_data = NULL;
- int_cmd->comp_func = NULL;
+ int_cmd->comp_func = mtip_null_completion;
}
/* Copy the command to the command table */
@@ -1159,6 +1321,12 @@
"Internal command did not complete [%d] "
"within timeout of %lu ms\n",
atomic, timeout);
+ if (mtip_check_surprise_removal(port->dd->pdev) ||
+ test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &port->dd->dd_flag)) {
+ rv = -ENXIO;
+ goto exec_ic_exit;
+ }
rv = -EAGAIN;
}
@@ -1166,31 +1334,59 @@
& (1 << MTIP_TAG_INTERNAL)) {
dev_warn(&port->dd->pdev->dev,
"Retiring internal command but CI is 1.\n");
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &port->dd->dd_flag)) {
+ hba_reset_nosleep(port->dd);
+ rv = -ENXIO;
+ } else {
+ mtip_restart_port(port);
+ rv = -EAGAIN;
+ }
+ goto exec_ic_exit;
}
} else {
/* Spin for <timeout> checking if command still outstanding */
timeout = jiffies + msecs_to_jiffies(timeout);
-
- while ((readl(
- port->cmd_issue[MTIP_TAG_INTERNAL])
- & (1 << MTIP_TAG_INTERNAL))
- && time_before(jiffies, timeout))
- ;
+ while ((readl(port->cmd_issue[MTIP_TAG_INTERNAL])
+ & (1 << MTIP_TAG_INTERNAL))
+ && time_before(jiffies, timeout)) {
+ if (mtip_check_surprise_removal(port->dd->pdev)) {
+ rv = -ENXIO;
+ goto exec_ic_exit;
+ }
+ if ((fis->command != ATA_CMD_STANDBYNOW1) &&
+ test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &port->dd->dd_flag)) {
+ rv = -ENXIO;
+ goto exec_ic_exit;
+ }
+ }
if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
& (1 << MTIP_TAG_INTERNAL)) {
dev_err(&port->dd->pdev->dev,
- "Internal command did not complete [%d]\n",
- atomic);
+ "Internal command did not complete [atomic]\n");
rv = -EAGAIN;
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &port->dd->dd_flag)) {
+ hba_reset_nosleep(port->dd);
+ rv = -ENXIO;
+ } else {
+ mtip_restart_port(port);
+ rv = -EAGAIN;
+ }
}
}
-
+exec_ic_exit:
/* Clear the allocated and active bits for the internal command. */
atomic_set(&int_cmd->active, 0);
release_slot(port, MTIP_TAG_INTERNAL);
- clear_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags);
+ if (rv >= 0 && mtip_pause_ncq(port, fis)) {
+ /* NCQ paused */
+ return rv;
+ }
+ clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
wake_up_interruptible(&port->svc_wait);
return rv;
@@ -1240,6 +1436,9 @@
int rv = 0;
struct host_to_dev_fis fis;
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
+ return -EFAULT;
+
/* Build the FIS. */
memset(&fis, 0, sizeof(struct host_to_dev_fis));
fis.type = 0x27;
@@ -1313,6 +1512,7 @@
{
int rv;
struct host_to_dev_fis fis;
+ unsigned long start;
/* Build the FIS. */
memset(&fis, 0, sizeof(struct host_to_dev_fis));
@@ -1320,15 +1520,150 @@
fis.opts = 1 << 7;
fis.command = ATA_CMD_STANDBYNOW1;
- /* Execute the command. Use a 15-second timeout for large drives. */
+ start = jiffies;
rv = mtip_exec_internal_command(port,
&fis,
5,
0,
0,
0,
- GFP_KERNEL,
+ GFP_ATOMIC,
15000);
+ dbg_printk(MTIP_DRV_NAME "Time taken to complete standby cmd: %d ms\n",
+ jiffies_to_msecs(jiffies - start));
+ if (rv)
+ dev_warn(&port->dd->pdev->dev,
+ "STANDBY IMMEDIATE command failed.\n");
+
+ return rv;
+}
+
+/*
+ * Issue a READ LOG EXT command to the device.
+ *
+ * @port pointer to the port structure.
+ * @page page number to fetch
+ * @buffer pointer to buffer
+ * @buffer_dma dma address corresponding to @buffer
+ * @sectors page length to fetch, in sectors
+ *
+ * return value
+ * @rv return value from mtip_exec_internal_command()
+ */
+static int mtip_read_log_page(struct mtip_port *port, u8 page, u16 *buffer,
+ dma_addr_t buffer_dma, unsigned int sectors)
+{
+ struct host_to_dev_fis fis;
+
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = ATA_CMD_READ_LOG_EXT;
+ fis.sect_count = sectors & 0xFF;
+ fis.sect_cnt_ex = (sectors >> 8) & 0xFF;
+ fis.lba_low = page;
+ fis.lba_mid = 0;
+ fis.device = ATA_DEVICE_OBS;
+
+ memset(buffer, 0, sectors * ATA_SECT_SIZE);
+
+ return mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ buffer_dma,
+ sectors * ATA_SECT_SIZE,
+ 0,
+ GFP_ATOMIC,
+ MTIP_INTERNAL_COMMAND_TIMEOUT_MS);
+}
+
+/*
+ * Issue a SMART READ DATA command to the device.
+ *
+ * @port pointer to the port structure.
+ * @buffer pointer to buffer
+ * @buffer_dma dma address corresponding to @buffer
+ *
+ * return value
+ * @rv return value from mtip_exec_internal_command()
+ */
+static int mtip_get_smart_data(struct mtip_port *port, u8 *buffer,
+ dma_addr_t buffer_dma)
+{
+ struct host_to_dev_fis fis;
+
+ memset(&fis, 0, sizeof(struct host_to_dev_fis));
+ fis.type = 0x27;
+ fis.opts = 1 << 7;
+ fis.command = ATA_CMD_SMART;
+ fis.features = 0xD0;
+ fis.sect_count = 1;
+ fis.lba_mid = 0x4F;
+ fis.lba_hi = 0xC2;
+ fis.device = ATA_DEVICE_OBS;
+
+ return mtip_exec_internal_command(port,
+ &fis,
+ 5,
+ buffer_dma,
+ ATA_SECT_SIZE,
+ 0,
+ GFP_ATOMIC,
+ 15000);
+}
+
+/*
+ * Get the value of a smart attribute
+ *
+ * @port pointer to the port structure
+ * @id attribute number
+ * @attrib pointer to return attrib information corresponding to @id
+ *
+ * return value
+ * -EINVAL NULL buffer passed or unsupported attribute @id.
+ * -EPERM Identify data not valid, SMART not supported or not enabled
+ */
+static int mtip_get_smart_attr(struct mtip_port *port, unsigned int id,
+ struct smart_attr *attrib)
+{
+ int rv, i;
+ struct smart_attr *pattr;
+
+ if (!attrib)
+ return -EINVAL;
+
+ if (!port->identify_valid) {
+ dev_warn(&port->dd->pdev->dev, "IDENTIFY DATA not valid\n");
+ return -EPERM;
+ }
+ if (!(port->identify[82] & 0x1)) {
+ dev_warn(&port->dd->pdev->dev, "SMART not supported\n");
+ return -EPERM;
+ }
+ if (!(port->identify[85] & 0x1)) {
+ dev_warn(&port->dd->pdev->dev, "SMART not enabled\n");
+ return -EPERM;
+ }
+
+ memset(port->smart_buf, 0, ATA_SECT_SIZE);
+ rv = mtip_get_smart_data(port, port->smart_buf, port->smart_buf_dma);
+ if (rv) {
+ dev_warn(&port->dd->pdev->dev, "Failed to ge SMART data\n");
+ return rv;
+ }
+
+ pattr = (struct smart_attr *)(port->smart_buf + 2);
+ for (i = 0; i < 29; i++, pattr++)
+ if (pattr->attr_id == id) {
+ memcpy(attrib, pattr, sizeof(struct smart_attr));
+ break;
+ }
+
+ if (i == 29) {
+ dev_warn(&port->dd->pdev->dev,
+ "Query for invalid SMART attribute ID\n");
+ rv = -EINVAL;
+ }
return rv;
}
@@ -1504,10 +1839,7 @@
fis.cyl_hi = command[5];
fis.device = command[6] & ~0x10; /* Clear the dev bit*/
-
- dbg_printk(MTIP_DRV_NAME "%s: User Command: cmd %x, feat %x, "
- "nsect %x, sect %x, lcyl %x, "
- "hcyl %x, sel %x\n",
+ dbg_printk(MTIP_DRV_NAME " %s: User Command: cmd %x, feat %x, nsect %x, sect %x, lcyl %x, hcyl %x, sel %x\n",
__func__,
command[0],
command[1],
@@ -1534,8 +1866,7 @@
command[4] = reply->cyl_low;
command[5] = reply->cyl_hi;
- dbg_printk(MTIP_DRV_NAME "%s: Completion Status: stat %x, "
- "err %x , cyl_lo %x cyl_hi %x\n",
+ dbg_printk(MTIP_DRV_NAME " %s: Completion Status: stat %x, err %x , cyl_lo %x cyl_hi %x\n",
__func__,
command[0],
command[1],
@@ -1578,7 +1909,7 @@
}
dbg_printk(MTIP_DRV_NAME
- "%s: User Command: cmd %x, sect %x, "
+ " %s: User Command: cmd %x, sect %x, "
"feat %x, sectcnt %x\n",
__func__,
command[0],
@@ -1607,7 +1938,7 @@
command[2] = command[3];
dbg_printk(MTIP_DRV_NAME
- "%s: Completion Status: stat %x, "
+ " %s: Completion Status: stat %x, "
"err %x, cmd %x\n",
__func__,
command[0],
@@ -1810,9 +2141,10 @@
}
dbg_printk(MTIP_DRV_NAME
- "taskfile: cmd %x, feat %x, nsect %x,"
+ " %s: cmd %x, feat %x, nsect %x,"
" sect/lbal %x, lcyl/lbam %x, hcyl/lbah %x,"
" head/dev %x\n",
+ __func__,
fis.command,
fis.features,
fis.sect_count,
@@ -1823,8 +2155,8 @@
switch (fis.command) {
case ATA_CMD_DOWNLOAD_MICRO:
- /* Change timeout for Download Microcode to 60 seconds.*/
- timeout = 60000;
+ /* Change timeout for Download Microcode to 2 minutes */
+ timeout = 120000;
break;
case ATA_CMD_SEC_ERASE_UNIT:
/* Change timeout for Security Erase Unit to 4 minutes.*/
@@ -1840,8 +2172,8 @@
timeout = 10000;
break;
case ATA_CMD_SMART:
- /* Change timeout for vendor unique command to 10 secs */
- timeout = 10000;
+ /* Change timeout for vendor unique command to 15 secs */
+ timeout = 15000;
break;
default:
timeout = MTIP_IOCTL_COMMAND_TIMEOUT_MS;
@@ -1903,18 +2235,8 @@
req_task->hob_ports[1] = reply->features_ex;
req_task->hob_ports[2] = reply->sect_cnt_ex;
}
-
- /* Com rest after secure erase or lowlevel format */
- if (((fis.command == ATA_CMD_SEC_ERASE_UNIT) ||
- ((fis.command == 0xFC) &&
- (fis.features == 0x27 || fis.features == 0x72 ||
- fis.features == 0x62 || fis.features == 0x26))) &&
- !(reply->command & 1)) {
- mtip_restart_port(dd->port);
- }
-
dbg_printk(MTIP_DRV_NAME
- "%s: Completion: stat %x,"
+ " %s: Completion: stat %x,"
"err %x, sect_cnt %x, lbalo %x,"
"lbamid %x, lbahi %x, dev %x\n",
__func__,
@@ -2080,14 +2402,10 @@
struct host_to_dev_fis *fis;
struct mtip_port *port = dd->port;
struct mtip_cmd *command = &port->commands[tag];
+ int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
/* Map the scatter list for DMA access */
- if (dir == READ)
- nents = dma_map_sg(&dd->pdev->dev, command->sg,
- nents, DMA_FROM_DEVICE);
- else
- nents = dma_map_sg(&dd->pdev->dev, command->sg,
- nents, DMA_TO_DEVICE);
+ nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
command->scatter_ents = nents;
@@ -2127,7 +2445,7 @@
*/
command->comp_data = dd;
command->comp_func = mtip_async_complete;
- command->direction = (dir == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ command->direction = dma_dir;
/*
* Set the completion function and data for the command passed
@@ -2140,19 +2458,16 @@
* To prevent this command from being issued
* if an internal command is in progress or error handling is active.
*/
- if (unlikely(test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) ||
- test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags))) {
+ if (port->flags & MTIP_PF_PAUSE_IO) {
set_bit(tag, port->cmds_to_issue);
- set_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
+ set_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags);
return;
}
/* Issue the command to the hardware */
mtip_issue_ncq_command(port, tag);
- /* Set the command's timeout value.*/
- port->commands[tag].comp_time = jiffies + msecs_to_jiffies(
- MTIP_NCQ_COMMAND_TIMEOUT_MS);
+ return;
}
/*
@@ -2191,6 +2506,10 @@
down(&dd->port->cmd_slot);
*tag = get_slot(dd->port);
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) {
+ up(&dd->port->cmd_slot);
+ return NULL;
+ }
if (unlikely(*tag < 0))
return NULL;
@@ -2207,7 +2526,7 @@
* return value
* The size, in bytes, of the data copied into buf.
*/
-static ssize_t hw_show_registers(struct device *dev,
+static ssize_t mtip_hw_show_registers(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -2216,7 +2535,7 @@
int size = 0;
int n;
- size += sprintf(&buf[size], "%s:\ns_active:\n", __func__);
+ size += sprintf(&buf[size], "S ACTive:\n");
for (n = 0; n < dd->slot_groups; n++)
size += sprintf(&buf[size], "0x%08x\n",
@@ -2240,20 +2559,39 @@
group_allocated);
}
- size += sprintf(&buf[size], "completed:\n");
+ size += sprintf(&buf[size], "Completed:\n");
for (n = 0; n < dd->slot_groups; n++)
size += sprintf(&buf[size], "0x%08x\n",
readl(dd->port->completed[n]));
- size += sprintf(&buf[size], "PORT_IRQ_STAT 0x%08x\n",
+ size += sprintf(&buf[size], "PORT IRQ STAT : 0x%08x\n",
readl(dd->port->mmio + PORT_IRQ_STAT));
- size += sprintf(&buf[size], "HOST_IRQ_STAT 0x%08x\n",
+ size += sprintf(&buf[size], "HOST IRQ STAT : 0x%08x\n",
readl(dd->mmio + HOST_IRQ_STAT));
return size;
}
-static DEVICE_ATTR(registers, S_IRUGO, hw_show_registers, NULL);
+
+static ssize_t mtip_hw_show_status(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct driver_data *dd = dev_to_disk(dev)->private_data;
+ int size = 0;
+
+ if (test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag))
+ size += sprintf(buf, "%s", "thermal_shutdown\n");
+ else if (test_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag))
+ size += sprintf(buf, "%s", "write_protect\n");
+ else
+ size += sprintf(buf, "%s", "online\n");
+
+ return size;
+}
+
+static DEVICE_ATTR(registers, S_IRUGO, mtip_hw_show_registers, NULL);
+static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
/*
* Create the sysfs related attributes.
@@ -2272,7 +2610,10 @@
if (sysfs_create_file(kobj, &dev_attr_registers.attr))
dev_warn(&dd->pdev->dev,
- "Error creating registers sysfs entry\n");
+ "Error creating 'registers' sysfs entry\n");
+ if (sysfs_create_file(kobj, &dev_attr_status.attr))
+ dev_warn(&dd->pdev->dev,
+ "Error creating 'status' sysfs entry\n");
return 0;
}
@@ -2292,6 +2633,7 @@
return -EINVAL;
sysfs_remove_file(kobj, &dev_attr_registers.attr);
+ sysfs_remove_file(kobj, &dev_attr_status.attr);
return 0;
}
@@ -2384,10 +2726,12 @@
"FTL rebuild in progress. Polling for completion.\n");
start = jiffies;
- dd->ftlrebuildflag = 1;
timeout = jiffies + msecs_to_jiffies(MTIP_FTL_REBUILD_TIMEOUT_MS);
do {
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &dd->dd_flag)))
+ return -EFAULT;
if (mtip_check_surprise_removal(dd->pdev))
return -EFAULT;
@@ -2408,22 +2752,17 @@
dev_warn(&dd->pdev->dev,
"FTL rebuild complete (%d secs).\n",
jiffies_to_msecs(jiffies - start) / 1000);
- dd->ftlrebuildflag = 0;
mtip_block_initialize(dd);
- break;
+ return 0;
}
ssleep(10);
} while (time_before(jiffies, timeout));
/* Check for timeout */
- if (dd->ftlrebuildflag) {
- dev_err(&dd->pdev->dev,
+ dev_err(&dd->pdev->dev,
"Timed out waiting for FTL rebuild to complete (%d secs).\n",
jiffies_to_msecs(jiffies - start) / 1000);
- return -EFAULT;
- }
-
- return 0;
+ return -EFAULT;
}
/*
@@ -2448,14 +2787,17 @@
* is in progress nor error handling is active
*/
wait_event_interruptible(port->svc_wait, (port->flags) &&
- !test_bit(MTIP_FLAG_IC_ACTIVE_BIT, &port->flags) &&
- !test_bit(MTIP_FLAG_EH_ACTIVE_BIT, &port->flags));
+ !(port->flags & MTIP_PF_PAUSE_IO));
if (kthread_should_stop())
break;
- set_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
- if (test_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags)) {
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &dd->dd_flag)))
+ break;
+
+ set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
+ if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
slot = 1;
/* used to restrict the loop to one iteration */
slot_start = num_cmd_slots;
@@ -2480,21 +2822,19 @@
/* Issue the command to the hardware */
mtip_issue_ncq_command(port, slot);
- /* Set the command's timeout value.*/
- port->commands[slot].comp_time = jiffies +
- msecs_to_jiffies(MTIP_NCQ_COMMAND_TIMEOUT_MS);
-
clear_bit(slot, port->cmds_to_issue);
}
- clear_bit(MTIP_FLAG_ISSUE_CMDS_BIT, &port->flags);
- } else if (test_bit(MTIP_FLAG_REBUILD_BIT, &port->flags)) {
- mtip_ftl_rebuild_poll(dd);
- clear_bit(MTIP_FLAG_REBUILD_BIT, &port->flags);
+ clear_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags);
+ } else if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
+ if (!mtip_ftl_rebuild_poll(dd))
+ set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
+ &dd->dd_flag);
+ clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
}
- clear_bit(MTIP_FLAG_SVC_THD_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
- if (test_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &port->flags))
+ if (test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
break;
}
return 0;
@@ -2513,6 +2853,9 @@
int i;
int rv;
unsigned int num_command_slots;
+ unsigned long timeout, timetaken;
+ unsigned char *buf;
+ struct smart_attr attr242;
dd->mmio = pcim_iomap_table(dd->pdev)[MTIP_ABAR];
@@ -2547,7 +2890,7 @@
/* Allocate memory for the command list. */
dd->port->command_list =
dmam_alloc_coherent(&dd->pdev->dev,
- HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
&dd->port->command_list_dma,
GFP_KERNEL);
if (!dd->port->command_list) {
@@ -2560,7 +2903,7 @@
/* Clear the memory we have allocated. */
memset(dd->port->command_list,
0,
- HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2));
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4));
/* Setup the addresse of the RX FIS. */
dd->port->rxfis = dd->port->command_list + HW_CMD_SLOT_SZ;
@@ -2576,10 +2919,19 @@
dd->port->identify_dma = dd->port->command_tbl_dma +
HW_CMD_TBL_AR_SZ;
- /* Setup the address of the sector buffer. */
+ /* Setup the address of the sector buffer - for some non-ncq cmds */
dd->port->sector_buffer = (void *) dd->port->identify + ATA_SECT_SIZE;
dd->port->sector_buffer_dma = dd->port->identify_dma + ATA_SECT_SIZE;
+ /* Setup the address of the log buf - for read log command */
+ dd->port->log_buf = (void *)dd->port->sector_buffer + ATA_SECT_SIZE;
+ dd->port->log_buf_dma = dd->port->sector_buffer_dma + ATA_SECT_SIZE;
+
+ /* Setup the address of the smart buf - for smart read data command */
+ dd->port->smart_buf = (void *)dd->port->log_buf + ATA_SECT_SIZE;
+ dd->port->smart_buf_dma = dd->port->log_buf_dma + ATA_SECT_SIZE;
+
+
/* Point the command headers at the command tables. */
for (i = 0; i < num_command_slots; i++) {
dd->port->commands[i].command_header =
@@ -2623,14 +2975,43 @@
dd->port->mmio + i*0x80 + PORT_SDBV;
}
- /* Reset the HBA. */
- if (mtip_hba_reset(dd) < 0) {
- dev_err(&dd->pdev->dev,
- "Card did not reset within timeout\n");
- rv = -EIO;
+ timetaken = jiffies;
+ timeout = jiffies + msecs_to_jiffies(30000);
+ while (((readl(dd->port->mmio + PORT_SCR_STAT) & 0x0F) != 0x03) &&
+ time_before(jiffies, timeout)) {
+ mdelay(100);
+ }
+ if (unlikely(mtip_check_surprise_removal(dd->pdev))) {
+ timetaken = jiffies - timetaken;
+ dev_warn(&dd->pdev->dev,
+ "Surprise removal detected at %u ms\n",
+ jiffies_to_msecs(timetaken));
+ rv = -ENODEV;
+ goto out2 ;
+ }
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))) {
+ timetaken = jiffies - timetaken;
+ dev_warn(&dd->pdev->dev,
+ "Removal detected at %u ms\n",
+ jiffies_to_msecs(timetaken));
+ rv = -EFAULT;
goto out2;
}
+ /* Conditionally reset the HBA. */
+ if (!(readl(dd->mmio + HOST_CAP) & HOST_CAP_NZDMA)) {
+ if (mtip_hba_reset(dd) < 0) {
+ dev_err(&dd->pdev->dev,
+ "Card did not reset within timeout\n");
+ rv = -EIO;
+ goto out2;
+ }
+ } else {
+ /* Clear any pending interrupts on the HBA */
+ writel(readl(dd->mmio + HOST_IRQ_STAT),
+ dd->mmio + HOST_IRQ_STAT);
+ }
+
mtip_init_port(dd->port);
mtip_start_port(dd->port);
@@ -2660,6 +3041,12 @@
mod_timer(&dd->port->cmd_timer,
jiffies + msecs_to_jiffies(MTIP_TIMEOUT_CHECK_PERIOD));
+
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) {
+ rv = -EFAULT;
+ goto out3;
+ }
+
if (mtip_get_identify(dd->port, NULL) < 0) {
rv = -EFAULT;
goto out3;
@@ -2667,10 +3054,47 @@
if (*(dd->port->identify + MTIP_FTL_REBUILD_OFFSET) ==
MTIP_FTL_REBUILD_MAGIC) {
- set_bit(MTIP_FLAG_REBUILD_BIT, &dd->port->flags);
+ set_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags);
return MTIP_FTL_REBUILD_MAGIC;
}
mtip_dump_identify(dd->port);
+
+ /* check write protect, over temp and rebuild statuses */
+ rv = mtip_read_log_page(dd->port, ATA_LOG_SATA_NCQ,
+ dd->port->log_buf,
+ dd->port->log_buf_dma, 1);
+ if (rv) {
+ dev_warn(&dd->pdev->dev,
+ "Error in READ LOG EXT (10h) command\n");
+ /* non-critical error, don't fail the load */
+ } else {
+ buf = (unsigned char *)dd->port->log_buf;
+ if (buf[259] & 0x1) {
+ dev_info(&dd->pdev->dev,
+ "Write protect bit is set.\n");
+ set_bit(MTIP_DDF_WRITE_PROTECT_BIT, &dd->dd_flag);
+ }
+ if (buf[288] == 0xF7) {
+ dev_info(&dd->pdev->dev,
+ "Exceeded Tmax, drive in thermal shutdown.\n");
+ set_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag);
+ }
+ if (buf[288] == 0xBF) {
+ dev_info(&dd->pdev->dev,
+ "Drive indicates rebuild has failed.\n");
+ /* TODO */
+ }
+ }
+
+ /* get write protect progess */
+ memset(&attr242, 0, sizeof(struct smart_attr));
+ if (mtip_get_smart_attr(dd->port, 242, &attr242))
+ dev_warn(&dd->pdev->dev,
+ "Unable to check write protect progress\n");
+ else
+ dev_info(&dd->pdev->dev,
+ "Write protect progress: %d%% (%d blocks)\n",
+ attr242.cur, attr242.data);
return rv;
out3:
@@ -2688,7 +3112,7 @@
/* Free the command/command header memory. */
dmam_free_coherent(&dd->pdev->dev,
- HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
dd->port->command_list,
dd->port->command_list_dma);
out1:
@@ -2712,9 +3136,12 @@
* Send standby immediate (E0h) to the drive so that it
* saves its state.
*/
- if (atomic_read(&dd->drv_cleanup_done) != true) {
+ if (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
- mtip_standby_immediate(dd->port);
+ if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags))
+ if (mtip_standby_immediate(dd->port))
+ dev_warn(&dd->pdev->dev,
+ "STANDBY IMMEDIATE failed\n");
/* de-initialize the port. */
mtip_deinit_port(dd->port);
@@ -2734,7 +3161,7 @@
/* Free the command/command header memory. */
dmam_free_coherent(&dd->pdev->dev,
- HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 2),
+ HW_PORT_PRIV_DMA_SZ + (ATA_SECT_SIZE * 4),
dd->port->command_list,
dd->port->command_list_dma);
/* Free the memory allocated for the for structure. */
@@ -2892,6 +3319,9 @@
if (!dd)
return -ENOTTY;
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
+ return -ENOTTY;
+
switch (cmd) {
case BLKFLSBUF:
return -ENOTTY;
@@ -2927,6 +3357,9 @@
if (!dd)
return -ENOTTY;
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)))
+ return -ENOTTY;
+
switch (cmd) {
case BLKFLSBUF:
return -ENOTTY;
@@ -3049,6 +3482,24 @@
int nents = 0;
int tag = 0;
+ if (unlikely(dd->dd_flag & MTIP_DDF_STOP_IO)) {
+ if (unlikely(test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
+ &dd->dd_flag))) {
+ bio_endio(bio, -ENXIO);
+ return;
+ }
+ if (unlikely(test_bit(MTIP_DDF_OVER_TEMP_BIT, &dd->dd_flag))) {
+ bio_endio(bio, -ENODATA);
+ return;
+ }
+ if (unlikely(test_bit(MTIP_DDF_WRITE_PROTECT_BIT,
+ &dd->dd_flag) &&
+ bio_data_dir(bio))) {
+ bio_endio(bio, -ENODATA);
+ return;
+ }
+ }
+
if (unlikely(!bio_has_data(bio))) {
blk_queue_flush(queue, 0);
bio_endio(bio, 0);
@@ -3061,7 +3512,7 @@
if (unlikely((bio)->bi_vcnt > MTIP_MAX_SG)) {
dev_warn(&dd->pdev->dev,
- "Maximum number of SGL entries exceeded");
+ "Maximum number of SGL entries exceeded\n");
bio_io_error(bio);
mtip_hw_release_scatterlist(dd, tag);
return;
@@ -3210,8 +3661,10 @@
kobject_put(kobj);
}
- if (dd->mtip_svc_handler)
+ if (dd->mtip_svc_handler) {
+ set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
return rv; /* service thread created for handling rebuild */
+ }
start_service_thread:
sprintf(thd_name, "mtip_svc_thd_%02d", index);
@@ -3220,12 +3673,15 @@
dd, thd_name);
if (IS_ERR(dd->mtip_svc_handler)) {
- printk(KERN_ERR "mtip32xx: service thread failed to start\n");
+ dev_err(&dd->pdev->dev, "service thread failed to start\n");
dd->mtip_svc_handler = NULL;
rv = -EFAULT;
goto kthread_run_error;
}
+ if (wait_for_rebuild == MTIP_FTL_REBUILD_MAGIC)
+ rv = wait_for_rebuild;
+
return rv;
kthread_run_error:
@@ -3266,16 +3722,18 @@
struct kobject *kobj;
if (dd->mtip_svc_handler) {
- set_bit(MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT, &dd->port->flags);
+ set_bit(MTIP_PF_SVC_THD_STOP_BIT, &dd->port->flags);
wake_up_interruptible(&dd->port->svc_wait);
kthread_stop(dd->mtip_svc_handler);
}
- /* Clean up the sysfs attributes managed by the protocol layer. */
- kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
- if (kobj) {
- mtip_hw_sysfs_exit(dd, kobj);
- kobject_put(kobj);
+ /* Clean up the sysfs attributes, if created */
+ if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag)) {
+ kobj = kobject_get(&disk_to_dev(dd->disk)->kobj);
+ if (kobj) {
+ mtip_hw_sysfs_exit(dd, kobj);
+ kobject_put(kobj);
+ }
}
/*
@@ -3283,6 +3741,11 @@
* from /dev
*/
del_gendisk(dd->disk);
+
+ spin_lock(&rssd_index_lock);
+ ida_remove(&rssd_index_ida, dd->index);
+ spin_unlock(&rssd_index_lock);
+
blk_cleanup_queue(dd->queue);
dd->disk = NULL;
dd->queue = NULL;
@@ -3312,6 +3775,11 @@
/* Delete our gendisk structure, and cleanup the blk queue. */
del_gendisk(dd->disk);
+
+ spin_lock(&rssd_index_lock);
+ ida_remove(&rssd_index_ida, dd->index);
+ spin_unlock(&rssd_index_lock);
+
blk_cleanup_queue(dd->queue);
dd->disk = NULL;
dd->queue = NULL;
@@ -3359,11 +3827,6 @@
return -ENOMEM;
}
- /* Set the atomic variable as 1 in case of SRSI */
- atomic_set(&dd->drv_cleanup_done, true);
-
- atomic_set(&dd->resumeflag, false);
-
/* Attach the private data to this PCI device. */
pci_set_drvdata(pdev, dd);
@@ -3420,7 +3883,8 @@
* instance number.
*/
instance++;
-
+ if (rv != MTIP_FTL_REBUILD_MAGIC)
+ set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
goto done;
block_initialize_err:
@@ -3434,9 +3898,6 @@
pci_set_drvdata(pdev, NULL);
return rv;
done:
- /* Set the atomic variable as 0 in case of SRSI */
- atomic_set(&dd->drv_cleanup_done, true);
-
return rv;
}
@@ -3452,8 +3913,10 @@
struct driver_data *dd = pci_get_drvdata(pdev);
int counter = 0;
+ set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
+
if (mtip_check_surprise_removal(pdev)) {
- while (atomic_read(&dd->drv_cleanup_done) == false) {
+ while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
counter++;
msleep(20);
if (counter == 10) {
@@ -3463,8 +3926,6 @@
}
}
}
- /* Set the atomic variable as 1 in case of SRSI */
- atomic_set(&dd->drv_cleanup_done, true);
/* Clean up the block layer. */
mtip_block_remove(dd);
@@ -3493,7 +3954,7 @@
return -EFAULT;
}
- atomic_set(&dd->resumeflag, true);
+ set_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag);
/* Disable ports & interrupts then send standby immediate */
rv = mtip_block_suspend(dd);
@@ -3559,7 +4020,7 @@
dev_err(&pdev->dev, "Unable to resume\n");
err:
- atomic_set(&dd->resumeflag, false);
+ clear_bit(MTIP_DDF_RESUME_BIT, &dd->dd_flag);
return rv;
}
@@ -3608,18 +4069,25 @@
*/
static int __init mtip_init(void)
{
+ int error;
+
printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
/* Allocate a major block device number to use with this driver. */
- mtip_major = register_blkdev(0, MTIP_DRV_NAME);
- if (mtip_major < 0) {
+ error = register_blkdev(0, MTIP_DRV_NAME);
+ if (error <= 0) {
printk(KERN_ERR "Unable to register block device (%d)\n",
- mtip_major);
+ error);
return -EBUSY;
}
+ mtip_major = error;
/* Register our PCI operations. */
- return pci_register_driver(&mtip_pci_driver);
+ error = pci_register_driver(&mtip_pci_driver);
+ if (error)
+ unregister_blkdev(mtip_major, MTIP_DRV_NAME);
+
+ return error;
}
/*
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index e0554a8..4ef5833 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -34,8 +34,8 @@
/* offset of Device Control register in PCIe extended capabilites space */
#define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48
-/* # of times to retry timed out IOs */
-#define MTIP_MAX_RETRIES 5
+/* # of times to retry timed out/failed IOs */
+#define MTIP_MAX_RETRIES 2
/* Various timeout values in ms */
#define MTIP_NCQ_COMMAND_TIMEOUT_MS 5000
@@ -114,12 +114,41 @@
#define __force_bit2int (unsigned int __force)
/* below are bit numbers in 'flags' defined in mtip_port */
-#define MTIP_FLAG_IC_ACTIVE_BIT 0
-#define MTIP_FLAG_EH_ACTIVE_BIT 1
-#define MTIP_FLAG_SVC_THD_ACTIVE_BIT 2
-#define MTIP_FLAG_ISSUE_CMDS_BIT 4
-#define MTIP_FLAG_REBUILD_BIT 5
-#define MTIP_FLAG_SVC_THD_SHOULD_STOP_BIT 8
+#define MTIP_PF_IC_ACTIVE_BIT 0 /* pio/ioctl */
+#define MTIP_PF_EH_ACTIVE_BIT 1 /* error handling */
+#define MTIP_PF_SE_ACTIVE_BIT 2 /* secure erase */
+#define MTIP_PF_DM_ACTIVE_BIT 3 /* download microcde */
+#define MTIP_PF_PAUSE_IO ((1 << MTIP_PF_IC_ACTIVE_BIT) | \
+ (1 << MTIP_PF_EH_ACTIVE_BIT) | \
+ (1 << MTIP_PF_SE_ACTIVE_BIT) | \
+ (1 << MTIP_PF_DM_ACTIVE_BIT))
+
+#define MTIP_PF_SVC_THD_ACTIVE_BIT 4
+#define MTIP_PF_ISSUE_CMDS_BIT 5
+#define MTIP_PF_REBUILD_BIT 6
+#define MTIP_PF_SVC_THD_STOP_BIT 8
+
+/* below are bit numbers in 'dd_flag' defined in driver_data */
+#define MTIP_DDF_REMOVE_PENDING_BIT 1
+#define MTIP_DDF_OVER_TEMP_BIT 2
+#define MTIP_DDF_WRITE_PROTECT_BIT 3
+#define MTIP_DDF_STOP_IO ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
+ (1 << MTIP_DDF_OVER_TEMP_BIT) | \
+ (1 << MTIP_DDF_WRITE_PROTECT_BIT))
+
+#define MTIP_DDF_CLEANUP_BIT 5
+#define MTIP_DDF_RESUME_BIT 6
+#define MTIP_DDF_INIT_DONE_BIT 7
+#define MTIP_DDF_REBUILD_FAILED_BIT 8
+
+__packed struct smart_attr{
+ u8 attr_id;
+ u16 flags;
+ u8 cur;
+ u8 worst;
+ u32 data;
+ u8 res[3];
+};
/* Register Frame Information Structure (FIS), host to device. */
struct host_to_dev_fis {
@@ -345,6 +374,12 @@
* when the command slot and all associated data structures
* are no longer needed.
*/
+ u16 *log_buf;
+ dma_addr_t log_buf_dma;
+
+ u8 *smart_buf;
+ dma_addr_t smart_buf_dma;
+
unsigned long allocated[SLOTBITS_IN_LONGS];
/*
* used to queue commands when an internal command is in progress
@@ -368,6 +403,7 @@
* Timer used to complete commands that have been active for too long.
*/
struct timer_list cmd_timer;
+ unsigned long ic_pause_timer;
/*
* Semaphore used to block threads if there are no
* command slots available.
@@ -404,13 +440,9 @@
unsigned slot_groups; /* number of slot groups the product supports */
- atomic_t drv_cleanup_done; /* Atomic variable for SRSI */
-
unsigned long index; /* Index to determine the disk name */
- unsigned int ftlrebuildflag; /* FTL rebuild flag */
-
- atomic_t resumeflag; /* Atomic variable to track suspend/resume */
+ unsigned long dd_flag; /* NOTE: use atomic bit operations on this */
struct task_struct *mtip_svc_handler; /* task_struct of svc thd */
};
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index c4a60ba..0d39f2f 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -351,6 +351,7 @@
cap_str_10, cap_str_2);
set_capacity(vblk->disk, capacity);
+ revalidate_disk(vblk->disk);
done:
mutex_unlock(&vblk->config_lock);
}
@@ -374,6 +375,34 @@
return err;
}
+/*
+ * Legacy naming scheme used for virtio devices. We are stuck with it for
+ * virtio blk but don't ever use it for any new driver.
+ */
+static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
+{
+ const int base = 'z' - 'a' + 1;
+ char *begin = buf + strlen(prefix);
+ char *end = buf + buflen;
+ char *p;
+ int unit;
+
+ p = end - 1;
+ *p = '\0';
+ unit = base;
+ do {
+ if (p == begin)
+ return -EINVAL;
+ *--p = 'a' + (index % unit);
+ index = (index / unit) - 1;
+ } while (index >= 0);
+
+ memmove(begin, p, end - p);
+ memcpy(buf, prefix, strlen(prefix));
+
+ return 0;
+}
+
static int __devinit virtblk_probe(struct virtio_device *vdev)
{
struct virtio_blk *vblk;
@@ -442,18 +471,7 @@
q->queuedata = vblk;
- if (index < 26) {
- sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
- } else if (index < (26 + 1) * 26) {
- sprintf(vblk->disk->disk_name, "vd%c%c",
- 'a' + index / 26 - 1, 'a' + index % 26);
- } else {
- const unsigned int m1 = (index / 26 - 1) / 26 - 1;
- const unsigned int m2 = (index / 26 - 1) % 26;
- const unsigned int m3 = index % 26;
- sprintf(vblk->disk->disk_name, "vd%c%c%c",
- 'a' + m1, 'a' + m2, 'a' + m3);
- }
+ virtblk_name_format("vd", index, vblk->disk->disk_name, DISK_NAME_LEN);
vblk->disk->major = major;
vblk->disk->first_minor = index_to_minor(index);
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 0088bf6..73f196c 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -321,6 +321,7 @@
static void xen_blkbk_unmap(struct pending_req *req)
{
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
unsigned int i, invcount = 0;
grant_handle_t handle;
int ret;
@@ -332,25 +333,12 @@
gnttab_set_unmap_op(&unmap[invcount], vaddr(req, i),
GNTMAP_host_map, handle);
pending_handle(req, i) = BLKBACK_INVALID_HANDLE;
+ pages[invcount] = virt_to_page(vaddr(req, i));
invcount++;
}
- ret = HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, invcount);
+ ret = gnttab_unmap_refs(unmap, pages, invcount, false);
BUG_ON(ret);
- /*
- * Note, we use invcount, so nr->pages, so we can't index
- * using vaddr(req, i).
- */
- for (i = 0; i < invcount; i++) {
- ret = m2p_remove_override(
- virt_to_page(unmap[i].host_addr), false);
- if (ret) {
- pr_alert(DRV_PFX "Failed to remove M2P override for %lx\n",
- (unsigned long)unmap[i].host_addr);
- continue;
- }
- }
}
static int xen_blkbk_map(struct blkif_request *req,
@@ -378,7 +366,7 @@
pending_req->blkif->domid);
}
- ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
+ ret = gnttab_map_refs(map, NULL, &blkbk->pending_page(pending_req, 0), nseg);
BUG_ON(ret);
/*
@@ -398,15 +386,6 @@
if (ret)
continue;
- ret = m2p_add_override(PFN_DOWN(map[i].dev_bus_addr),
- blkbk->pending_page(pending_req, i), NULL);
- if (ret) {
- pr_alert(DRV_PFX "Failed to install M2P override for %lx (ret: %d)\n",
- (unsigned long)map[i].dev_bus_addr, ret);
- /* We could switch over to GNTTABOP_copy */
- continue;
- }
-
seg[i].buf = map[i].dev_bus_addr |
(req->u.rw.seg[i].first_sect << 9);
}
@@ -419,21 +398,18 @@
int err = 0;
int status = BLKIF_RSP_OKAY;
struct block_device *bdev = blkif->vbd.bdev;
+ unsigned long secure;
blkif->st_ds_req++;
xen_blkif_get(blkif);
- if (blkif->blk_backend_type == BLKIF_BACKEND_PHY ||
- blkif->blk_backend_type == BLKIF_BACKEND_FILE) {
- unsigned long secure = (blkif->vbd.discard_secure &&
- (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
- BLKDEV_DISCARD_SECURE : 0;
- err = blkdev_issue_discard(bdev,
- req->u.discard.sector_number,
- req->u.discard.nr_sectors,
- GFP_KERNEL, secure);
- } else
- err = -EOPNOTSUPP;
+ secure = (blkif->vbd.discard_secure &&
+ (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ?
+ BLKDEV_DISCARD_SECURE : 0;
+
+ err = blkdev_issue_discard(bdev, req->u.discard.sector_number,
+ req->u.discard.nr_sectors,
+ GFP_KERNEL, secure);
if (err == -EOPNOTSUPP) {
pr_debug(DRV_PFX "discard op failed, not supported\n");
@@ -830,7 +806,7 @@
int i, mmap_pages;
int rc = 0;
- if (!xen_pv_domain())
+ if (!xen_domain())
return -ENODEV;
blkbk = kzalloc(sizeof(struct xen_blkbk), GFP_KERNEL);
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h
index d0ee7ed..773cf27 100644
--- a/drivers/block/xen-blkback/common.h
+++ b/drivers/block/xen-blkback/common.h
@@ -146,11 +146,6 @@
BLKIF_PROTOCOL_X86_64 = 3,
};
-enum blkif_backend_type {
- BLKIF_BACKEND_PHY = 1,
- BLKIF_BACKEND_FILE = 2,
-};
-
struct xen_vbd {
/* What the domain refers to this vbd as. */
blkif_vdev_t handle;
@@ -177,7 +172,6 @@
unsigned int irq;
/* Comms information. */
enum blkif_protocol blk_protocol;
- enum blkif_backend_type blk_backend_type;
union blkif_back_rings blk_rings;
void *blk_ring;
/* The VBD attached to this interface. */
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 24a2fb5..4f66171 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -381,72 +381,49 @@
err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
"%d", state);
if (err)
- xenbus_dev_fatal(dev, err, "writing feature-flush-cache");
+ dev_warn(&dev->dev, "writing feature-flush-cache (%d)", err);
return err;
}
-int xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
+static void xen_blkbk_discard(struct xenbus_transaction xbt, struct backend_info *be)
{
struct xenbus_device *dev = be->dev;
struct xen_blkif *blkif = be->blkif;
- char *type;
int err;
int state = 0;
+ struct block_device *bdev = be->blkif->vbd.bdev;
+ struct request_queue *q = bdev_get_queue(bdev);
- type = xenbus_read(XBT_NIL, dev->nodename, "type", NULL);
- if (!IS_ERR(type)) {
- if (strncmp(type, "file", 4) == 0) {
- state = 1;
- blkif->blk_backend_type = BLKIF_BACKEND_FILE;
+ if (blk_queue_discard(q)) {
+ err = xenbus_printf(xbt, dev->nodename,
+ "discard-granularity", "%u",
+ q->limits.discard_granularity);
+ if (err) {
+ dev_warn(&dev->dev, "writing discard-granularity (%d)", err);
+ return;
}
- if (strncmp(type, "phy", 3) == 0) {
- struct block_device *bdev = be->blkif->vbd.bdev;
- struct request_queue *q = bdev_get_queue(bdev);
- if (blk_queue_discard(q)) {
- err = xenbus_printf(xbt, dev->nodename,
- "discard-granularity", "%u",
- q->limits.discard_granularity);
- if (err) {
- xenbus_dev_fatal(dev, err,
- "writing discard-granularity");
- goto kfree;
- }
- err = xenbus_printf(xbt, dev->nodename,
- "discard-alignment", "%u",
- q->limits.discard_alignment);
- if (err) {
- xenbus_dev_fatal(dev, err,
- "writing discard-alignment");
- goto kfree;
- }
- state = 1;
- blkif->blk_backend_type = BLKIF_BACKEND_PHY;
- }
- /* Optional. */
- err = xenbus_printf(xbt, dev->nodename,
- "discard-secure", "%d",
- blkif->vbd.discard_secure);
- if (err) {
- xenbus_dev_fatal(dev, err,
- "writting discard-secure");
- goto kfree;
- }
+ err = xenbus_printf(xbt, dev->nodename,
+ "discard-alignment", "%u",
+ q->limits.discard_alignment);
+ if (err) {
+ dev_warn(&dev->dev, "writing discard-alignment (%d)", err);
+ return;
}
- } else {
- err = PTR_ERR(type);
- xenbus_dev_fatal(dev, err, "reading type");
- goto out;
+ state = 1;
+ /* Optional. */
+ err = xenbus_printf(xbt, dev->nodename,
+ "discard-secure", "%d",
+ blkif->vbd.discard_secure);
+ if (err) {
+ dev_warn(&dev->dev, "writing discard-secure (%d)", err);
+ return;
+ }
}
-
err = xenbus_printf(xbt, dev->nodename, "feature-discard",
"%d", state);
if (err)
- xenbus_dev_fatal(dev, err, "writing feature-discard");
-kfree:
- kfree(type);
-out:
- return err;
+ dev_warn(&dev->dev, "writing feature-discard (%d)", err);
}
int xen_blkbk_barrier(struct xenbus_transaction xbt,
struct backend_info *be, int state)
@@ -457,7 +434,7 @@
err = xenbus_printf(xbt, dev->nodename, "feature-barrier",
"%d", state);
if (err)
- xenbus_dev_fatal(dev, err, "writing feature-barrier");
+ dev_warn(&dev->dev, "writing feature-barrier (%d)", err);
return err;
}
@@ -689,14 +666,12 @@
return;
}
- err = xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
- if (err)
- goto abort;
-
- err = xen_blkbk_discard(xbt, be);
-
/* If we can't advertise it is OK. */
- err = xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
+ xen_blkbk_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
+
+ xen_blkbk_discard(xbt, be);
+
+ xen_blkbk_barrier(xbt, be, be->blkif->vbd.flush_support);
err = xenbus_printf(xbt, dev->nodename, "sectors", "%llu",
(unsigned long long)vbd_sz(&be->blkif->vbd));
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index d5e1ab9..4e86393 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/scatterlist.h>
+#include <linux/bitmap.h>
#include <xen/xen.h>
#include <xen/xenbus.h>
@@ -81,6 +82,7 @@
*/
struct blkfront_info
{
+ spinlock_t io_lock;
struct mutex mutex;
struct xenbus_device *xbdev;
struct gendisk *gd;
@@ -105,8 +107,6 @@
int is_ready;
};
-static DEFINE_SPINLOCK(blkif_io_lock);
-
static unsigned int nr_minors;
static unsigned long *minors;
static DEFINE_SPINLOCK(minor_lock);
@@ -177,8 +177,7 @@
spin_lock(&minor_lock);
if (find_next_bit(minors, end, minor) >= end) {
- for (; minor < end; ++minor)
- __set_bit(minor, minors);
+ bitmap_set(minors, minor, nr);
rc = 0;
} else
rc = -EBUSY;
@@ -193,8 +192,7 @@
BUG_ON(end > nr_minors);
spin_lock(&minor_lock);
- for (; minor < end; ++minor)
- __clear_bit(minor, minors);
+ bitmap_clear(minors, minor, nr);
spin_unlock(&minor_lock);
}
@@ -419,7 +417,7 @@
struct request_queue *rq;
struct blkfront_info *info = gd->private_data;
- rq = blk_init_queue(do_blkif_request, &blkif_io_lock);
+ rq = blk_init_queue(do_blkif_request, &info->io_lock);
if (rq == NULL)
return -1;
@@ -636,14 +634,14 @@
if (info->rq == NULL)
return;
- spin_lock_irqsave(&blkif_io_lock, flags);
+ spin_lock_irqsave(&info->io_lock, flags);
/* No more blkif_request(). */
blk_stop_queue(info->rq);
/* No more gnttab callback work. */
gnttab_cancel_free_callback(&info->callback);
- spin_unlock_irqrestore(&blkif_io_lock, flags);
+ spin_unlock_irqrestore(&info->io_lock, flags);
/* Flush gnttab callback work. Must be done with no locks held. */
flush_work_sync(&info->work);
@@ -675,16 +673,16 @@
{
struct blkfront_info *info = container_of(work, struct blkfront_info, work);
- spin_lock_irq(&blkif_io_lock);
+ spin_lock_irq(&info->io_lock);
if (info->connected == BLKIF_STATE_CONNECTED)
kick_pending_request_queues(info);
- spin_unlock_irq(&blkif_io_lock);
+ spin_unlock_irq(&info->io_lock);
}
static void blkif_free(struct blkfront_info *info, int suspend)
{
/* Prevent new requests being issued until we fix things up. */
- spin_lock_irq(&blkif_io_lock);
+ spin_lock_irq(&info->io_lock);
info->connected = suspend ?
BLKIF_STATE_SUSPENDED : BLKIF_STATE_DISCONNECTED;
/* No more blkif_request(). */
@@ -692,7 +690,7 @@
blk_stop_queue(info->rq);
/* No more gnttab callback work. */
gnttab_cancel_free_callback(&info->callback);
- spin_unlock_irq(&blkif_io_lock);
+ spin_unlock_irq(&info->io_lock);
/* Flush gnttab callback work. Must be done with no locks held. */
flush_work_sync(&info->work);
@@ -728,10 +726,10 @@
struct blkfront_info *info = (struct blkfront_info *)dev_id;
int error;
- spin_lock_irqsave(&blkif_io_lock, flags);
+ spin_lock_irqsave(&info->io_lock, flags);
if (unlikely(info->connected != BLKIF_STATE_CONNECTED)) {
- spin_unlock_irqrestore(&blkif_io_lock, flags);
+ spin_unlock_irqrestore(&info->io_lock, flags);
return IRQ_HANDLED;
}
@@ -816,7 +814,7 @@
kick_pending_request_queues(info);
- spin_unlock_irqrestore(&blkif_io_lock, flags);
+ spin_unlock_irqrestore(&info->io_lock, flags);
return IRQ_HANDLED;
}
@@ -991,6 +989,7 @@
}
mutex_init(&info->mutex);
+ spin_lock_init(&info->io_lock);
info->xbdev = dev;
info->vdevice = vdevice;
info->connected = BLKIF_STATE_DISCONNECTED;
@@ -1068,7 +1067,7 @@
xenbus_switch_state(info->xbdev, XenbusStateConnected);
- spin_lock_irq(&blkif_io_lock);
+ spin_lock_irq(&info->io_lock);
/* Now safe for us to use the shared ring */
info->connected = BLKIF_STATE_CONNECTED;
@@ -1079,7 +1078,7 @@
/* Kick any other new requests queued since we resumed */
kick_pending_request_queues(info);
- spin_unlock_irq(&blkif_io_lock);
+ spin_unlock_irq(&info->io_lock);
return 0;
}
@@ -1277,10 +1276,10 @@
xenbus_switch_state(info->xbdev, XenbusStateConnected);
/* Kick pending requests. */
- spin_lock_irq(&blkif_io_lock);
+ spin_lock_irq(&info->io_lock);
info->connected = BLKIF_STATE_CONNECTED;
kick_pending_request_queues(info);
- spin_unlock_irq(&blkif_io_lock);
+ spin_unlock_irq(&info->io_lock);
add_disk(info->gd);
@@ -1410,7 +1409,6 @@
mutex_lock(&blkfront_mutex);
bdev = bdget_disk(disk, 0);
- bdput(bdev);
if (bdev->bd_openers)
goto out;
@@ -1441,6 +1439,7 @@
}
out:
+ bdput(bdev);
mutex_unlock(&blkfront_mutex);
return 0;
}
@@ -1475,7 +1474,7 @@
if (!xen_domain())
return -ENODEV;
- if (!xen_platform_pci_unplug)
+ if (xen_hvm_domain() && !xen_platform_pci_unplug)
return -ENODEV;
if (register_blkdev(XENVBD_MAJOR, DEV_NAME)) {
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 48442476..57fd867 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -72,7 +72,11 @@
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3004) },
+ { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x13d3, 0x3375) },
+ { USB_DEVICE(0x04CA, 0x3005) },
+ { USB_DEVICE(0x13d3, 0x3362) },
+ { USB_DEVICE(0x0CF3, 0xE004) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
@@ -89,7 +93,11 @@
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */
};
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 6c20bbb..428dbb7 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -45,12 +45,6 @@
struct dentry *txdnldready;
};
-static int btmrvl_open_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t btmrvl_hscfgcmd_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
@@ -93,7 +87,7 @@
static const struct file_operations btmrvl_hscfgcmd_fops = {
.read = btmrvl_hscfgcmd_read,
.write = btmrvl_hscfgcmd_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -134,7 +128,7 @@
static const struct file_operations btmrvl_psmode_fops = {
.read = btmrvl_psmode_read,
.write = btmrvl_psmode_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -180,7 +174,7 @@
static const struct file_operations btmrvl_pscmd_fops = {
.read = btmrvl_pscmd_read,
.write = btmrvl_pscmd_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -221,7 +215,7 @@
static const struct file_operations btmrvl_gpiogap_fops = {
.read = btmrvl_gpiogap_read,
.write = btmrvl_gpiogap_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -265,7 +259,7 @@
static const struct file_operations btmrvl_hscmd_fops = {
.read = btmrvl_hscmd_read,
.write = btmrvl_hscmd_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -305,7 +299,7 @@
static const struct file_operations btmrvl_hsmode_fops = {
.read = btmrvl_hsmode_read,
.write = btmrvl_hsmode_write,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -323,7 +317,7 @@
static const struct file_operations btmrvl_curpsmode_fops = {
.read = btmrvl_curpsmode_read,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -341,7 +335,7 @@
static const struct file_operations btmrvl_psstate_fops = {
.read = btmrvl_psstate_read,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -359,7 +353,7 @@
static const struct file_operations btmrvl_hsstate_fops = {
.read = btmrvl_hsstate_read,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -378,7 +372,7 @@
static const struct file_operations btmrvl_txdnldready_fops = {
.read = btmrvl_txdnldready_read,
- .open = btmrvl_open_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 480cad9..9217121 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -61,7 +61,7 @@
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Broadcom SoftSailing reporting vendor specific */
- { USB_DEVICE(0x05ac, 0x21e1) },
+ { USB_DEVICE(0x0a5c, 0x21e1) },
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
@@ -101,11 +101,16 @@
{ USB_DEVICE(0x0c10, 0x0000) },
/* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x0a5c, 0x21e3) },
{ USB_DEVICE(0x0a5c, 0x21e6) },
+ { USB_DEVICE(0x0a5c, 0x21e8) },
{ USB_DEVICE(0x0a5c, 0x21f3) },
{ USB_DEVICE(0x413c, 0x8197) },
+ /* Foxconn - Hon Hai */
+ { USB_DEVICE(0x0489, 0xe033) },
+
{ } /* Terminating entry */
};
@@ -129,7 +134,11 @@
/* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index fd5adb4..98a8c05 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -299,11 +299,11 @@
hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
- hu->proto->close(hu);
if (hdev) {
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
+ hu->proto->close(hu);
}
kfree(hu);
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 5da67f1..7ea18a5 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -234,6 +234,7 @@
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG 0x0166
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */
#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A
+#define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG 0x016A
int intel_gmch_probe(struct pci_dev *pdev,
struct agp_bridge_data *bridge);
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 5cf47ac..7f025fb 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -1190,7 +1190,6 @@
{
#ifdef CONFIG_INTEL_IOMMU
const unsigned short gpu_devid = intel_private.pcidev->device;
- extern int intel_iommu_gfx_mapped;
/* Query intel_iommu to see if we need the workaround. Presumably that
* was loaded first.
@@ -1459,6 +1458,8 @@
"Ivybridge", &sandybridge_gtt_driver },
{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG,
"Ivybridge", &sandybridge_gtt_driver },
+ { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG,
+ "Ivybridge", &sandybridge_gtt_driver },
{ 0, NULL, NULL }
};
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 57501ca..46118f8 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -301,7 +301,7 @@
* anything critical, chill a bit on each iteration.
*/
while (wait_event_freezable(apm_suspend_waitqueue,
- as->suspend_state == SUSPEND_DONE))
+ as->suspend_state != SUSPEND_ACKED))
msleep(10);
break;
case SUSPEND_ACKTO:
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 3845ab4..dfd7876 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -906,8 +906,8 @@
hpetp->hp_which, hdp->hd_phys_address,
hpetp->hp_ntimer > 1 ? "s" : "");
for (i = 0; i < hpetp->hp_ntimer; i++)
- printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
- printk("\n");
+ printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
+ printk(KERN_CONT "\n");
temp = hpetp->hp_tick_freq;
remainder = do_div(temp, 1000000);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 54ca8b2..4ec04a7 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1260,10 +1260,15 @@
uuid = table->data;
if (!uuid) {
uuid = tmp_uuid;
- uuid[8] = 0;
- }
- if (uuid[8] == 0)
generate_random_uuid(uuid);
+ } else {
+ static DEFINE_SPINLOCK(bootid_spinlock);
+
+ spin_lock(&bootid_spinlock);
+ if (!uuid[8])
+ generate_random_uuid(uuid);
+ spin_unlock(&bootid_spinlock);
+ }
sprintf(buf, "%pU", uuid);
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
index 4dc0194..3b22a60 100644
--- a/drivers/char/tile-srom.c
+++ b/drivers/char/tile-srom.c
@@ -194,17 +194,17 @@
hv_retval = _srom_read(srom->hv_devhdl, kernbuf,
*f_pos, bytes_this_pass);
- if (hv_retval > 0) {
- if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
- retval = -EFAULT;
- break;
- }
- } else if (hv_retval <= 0) {
+ if (hv_retval <= 0) {
if (retval == 0)
retval = hv_retval;
break;
}
+ if (copy_to_user(buf, kernbuf, hv_retval) != 0) {
+ retval = -EFAULT;
+ break;
+ }
+
retval += hv_retval;
*f_pos += hv_retval;
buf += hv_retval;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index b58b561..ddf86b6 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1038,12 +1038,6 @@
.attrs = port_sysfs_entries,
};
-static int debugfs_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t debugfs_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *offp)
{
@@ -1087,7 +1081,7 @@
static const struct file_operations port_debugfs_ops = {
.owner = THIS_MODULE,
- .open = debugfs_open,
+ .open = simple_open,
.read = debugfs_read,
};
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 82e8820..6b5cf02 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -23,7 +23,6 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <linux/async.h>
#include <asm/io.h>
/*
@@ -180,15 +179,17 @@
/* Number of reads we try to get two different values */
#define ACPI_PM_READ_CHECKS 10000
-static void __init acpi_pm_clocksource_async(void *unused, async_cookie_t cookie)
+static int __init init_acpi_pm_clocksource(void)
{
cycle_t value1, value2;
unsigned int i, j = 0;
+ if (!pmtmr_ioport)
+ return -ENODEV;
/* "verify" this timing source: */
for (j = 0; j < ACPI_PM_MONOTONICITY_CHECKS; j++) {
- usleep_range(100 * j, 100 * j + 100);
+ udelay(100 * j);
value1 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
for (i = 0; i < ACPI_PM_READ_CHECKS; i++) {
value2 = clocksource_acpi_pm.read(&clocksource_acpi_pm);
@@ -202,34 +203,25 @@
" 0x%#llx, 0x%#llx - aborting.\n",
value1, value2);
pmtmr_ioport = 0;
- return;
+ return -EINVAL;
}
if (i == ACPI_PM_READ_CHECKS) {
printk(KERN_INFO "PM-Timer failed consistency check "
" (0x%#llx) - aborting.\n", value1);
pmtmr_ioport = 0;
- return;
+ return -ENODEV;
}
}
if (verify_pmtmr_rate() != 0){
pmtmr_ioport = 0;
- return;
+ return -ENODEV;
}
- clocksource_register_hz(&clocksource_acpi_pm,
+ return clocksource_register_hz(&clocksource_acpi_pm,
PMTMR_TICKS_PER_SEC);
}
-static int __init init_acpi_pm_clocksource(void)
-{
- if (!pmtmr_ioport)
- return -ENODEV;
-
- async_schedule(acpi_pm_clocksource_async, NULL);
- return 0;
-}
-
/* We use fs_initcall because we want the PCI fixups to have run
* but we still need to load before device_initcall
*/
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 32d790d..5961e64 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -4,6 +4,7 @@
config ARM_OMAP2PLUS_CPUFREQ
bool "TI OMAP2+"
+ depends on ARCH_OMAP2PLUS
default ARCH_OMAP2PLUS
select CPU_FREQ_TABLE
@@ -51,9 +52,6 @@
config ARM_EXYNOS_CPUFREQ
bool "SAMSUNG EXYNOS SoCs"
depends on ARCH_EXYNOS
- select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210
- select ARM_EXYNOS4X12_CPUFREQ if (SOC_EXYNOS4212 || SOC_EXYNOS4412)
- select ARM_EXYNOS5250_CPUFREQ if SOC_EXYNOS5250
default y
help
This adds the CPUFreq driver common part for Samsung
@@ -62,20 +60,19 @@
If in doubt, say N.
config ARM_EXYNOS4210_CPUFREQ
- bool "Samsung EXYNOS4210"
- depends on ARCH_EXYNOS
+ def_bool CPU_EXYNOS4210
help
This adds the CPUFreq driver for Samsung EXYNOS4210
SoC (S5PV310 or S5PC210).
config ARM_EXYNOS4X12_CPUFREQ
- bool "Samsung EXYNOS4X12"
+ def_bool (SOC_EXYNOS4212 || SOC_EXYNOS4412)
help
This adds the CPUFreq driver for Samsung EXYNOS4X12
SoC (EXYNOS4212 or EXYNOS4412).
config ARM_EXYNOS5250_CPUFREQ
- bool "Samsung EXYNOS5250"
+ def_bool SOC_EXYNOS5250
help
This adds the CPUFreq driver for Samsung EXYNOS5250
SoC.
diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c
index a22ffa5..0bf1b89 100644
--- a/drivers/cpufreq/db8500-cpufreq.c
+++ b/drivers/cpufreq/db8500-cpufreq.c
@@ -142,7 +142,7 @@
policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
/* policy sharing between dual CPUs */
- cpumask_copy(policy->cpus, &cpu_present_map);
+ cpumask_copy(policy->cpus, cpu_present_mask);
policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 87411ce..2f0083a 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -74,7 +74,7 @@
/**
* cpuidle_play_dead - cpu off-lining
*
- * Only returns in case of an error
+ * Returns in case of an error or no driver
*/
int cpuidle_play_dead(void)
{
@@ -83,6 +83,9 @@
int i, dead_state = -1;
int power_usage = -1;
+ if (!drv)
+ return -ENODEV;
+
/* Find lowest-power state that supports long-term idle */
for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
struct cpuidle_state *s = &drv->states[i];
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 0053d7e..8f3f74c 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/gfp.h>
+#include <linux/module.h>
#include <crypto/ctr.h>
#include <crypto/des.h>
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index dc641c7..921039e 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -124,6 +124,9 @@
void __iomem *reg;
int irq[2];
+ /* SEC global registers lock */
+ spinlock_t reg_lock ____cacheline_aligned;
+
/* SEC version geometry (from device tree node) */
unsigned int num_channels;
unsigned int chfifo_len;
@@ -412,6 +415,7 @@
{ \
struct device *dev = (struct device *)data; \
struct talitos_private *priv = dev_get_drvdata(dev); \
+ unsigned long flags; \
\
if (ch_done_mask & 1) \
flush_channel(dev, 0, 0, 0); \
@@ -427,8 +431,10 @@
out: \
/* At this point, all completed channels have been processed */ \
/* Unmask done interrupts for channels completed later on. */ \
+ spin_lock_irqsave(&priv->reg_lock, flags); \
setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
}
DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
@@ -619,22 +625,28 @@
struct device *dev = data; \
struct talitos_private *priv = dev_get_drvdata(dev); \
u32 isr, isr_lo; \
+ unsigned long flags; \
\
+ spin_lock_irqsave(&priv->reg_lock, flags); \
isr = in_be32(priv->reg + TALITOS_ISR); \
isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
/* Acknowledge interrupt */ \
out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
\
- if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
- talitos_error(dev, isr, isr_lo); \
- else \
+ if (unlikely(isr & ch_err_mask || isr_lo)) { \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ talitos_error(dev, isr & ch_err_mask, isr_lo); \
+ } \
+ else { \
if (likely(isr & ch_done_mask)) { \
/* mask further done interrupts. */ \
clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
/* done_task will unmask done interrupts at exit */ \
tasklet_schedule(&priv->done_task[tlet]); \
} \
+ spin_unlock_irqrestore(&priv->reg_lock, flags); \
+ } \
\
return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
IRQ_NONE; \
@@ -2719,6 +2731,8 @@
priv->ofdev = ofdev;
+ spin_lock_init(&priv->reg_lock);
+
err = talitos_probe_irq(ofdev);
if (err)
goto err_out;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index cf9da36..ef378b5 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -91,11 +91,10 @@
config AT_HDMAC
tristate "Atmel AHB DMA support"
- depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
+ depends on ARCH_AT91
select DMA_ENGINE
help
- Support the Atmel AHB DMA controller. This can be integrated in
- chips such as the Atmel AT91SAM9RL.
+ Support the Atmel AHB DMA controller.
config FSL_DMA
tristate "Freescale Elo and Elo Plus DMA support"
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index c301a8e..3d704ab 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -1429,6 +1429,7 @@
* signal
*/
release_phy_channel(plchan);
+ plchan->phychan_hold = 0;
}
/* Dequeue jobs and free LLIs */
if (plchan->at) {
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 7aa58d2..445fdf8 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -221,10 +221,6 @@
vdbg_dump_regs(atchan);
- /* clear any pending interrupt */
- while (dma_readl(atdma, EBCISR))
- cpu_relax();
-
channel_writel(atchan, SADDR, 0);
channel_writel(atchan, DADDR, 0);
channel_writel(atchan, CTRLA, 0);
diff --git a/drivers/dma/coh901318.c b/drivers/dma/coh901318.c
index dc89455..750925f 100644
--- a/drivers/dma/coh901318.c
+++ b/drivers/dma/coh901318.c
@@ -104,13 +104,6 @@
static struct coh901318_base *debugfs_dma_base;
static struct dentry *dma_dentry;
-static int coh901318_debugfs_open(struct inode *inode, struct file *file)
-{
-
- file->private_data = inode->i_private;
- return 0;
-}
-
static int coh901318_debugfs_read(struct file *file, char __user *buf,
size_t count, loff_t *f_pos)
{
@@ -158,7 +151,7 @@
static const struct file_operations coh901318_debugfs_status_operations = {
.owner = THIS_MODULE,
- .open = coh901318_debugfs_open,
+ .open = simple_open,
.read = coh901318_debugfs_read,
.llseek = default_llseek,
};
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 767bcc3..2397f6f 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -332,6 +332,20 @@
}
EXPORT_SYMBOL(dma_find_channel);
+/*
+ * net_dma_find_channel - find a channel for net_dma
+ * net_dma has alignment requirements
+ */
+struct dma_chan *net_dma_find_channel(void)
+{
+ struct dma_chan *chan = dma_find_channel(DMA_MEMCPY);
+ if (chan && !is_dma_copy_aligned(chan->device, 1, 1, 1))
+ return NULL;
+
+ return chan;
+}
+EXPORT_SYMBOL(net_dma_find_channel);
+
/**
* dma_issue_pending_all - flush all pending operations across all channels
*/
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index a45b5d2..bb787d8 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -571,11 +571,14 @@
if (desc->desc.callback)
desc->desc.callback(desc->desc.callback_param);
- dma_cookie_complete(&desc->desc);
-
- /* If we are dealing with a cyclic descriptor keep it on ld_active */
+ /* If we are dealing with a cyclic descriptor keep it on ld_active
+ * and dont mark the descripor as complete.
+ * Only in non-cyclic cases it would be marked as complete
+ */
if (imxdma_chan_is_doing_cyclic(imxdmac))
goto out;
+ else
+ dma_cookie_complete(&desc->desc);
/* Free 2D slot if it was an interleaved transfer */
if (imxdmac->enabled_2d) {
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 31493d8..73b2b65 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -546,9 +546,9 @@
PCI_DMA_TODEVICE, flags, 0);
}
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan)
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan)
{
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
u64 completion;
completion = *chan->completion;
@@ -569,7 +569,7 @@
}
bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
- unsigned long *phys_complete)
+ dma_addr_t *phys_complete)
{
*phys_complete = ioat_get_current_completion(chan);
if (*phys_complete == chan->last_completion)
@@ -580,14 +580,14 @@
return true;
}
-static void __cleanup(struct ioat_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat_dma_chan *ioat, dma_addr_t phys_complete)
{
struct ioat_chan_common *chan = &ioat->base;
struct list_head *_desc, *n;
struct dma_async_tx_descriptor *tx;
- dev_dbg(to_dev(chan), "%s: phys_complete: %lx\n",
- __func__, phys_complete);
+ dev_dbg(to_dev(chan), "%s: phys_complete: %llx\n",
+ __func__, (unsigned long long) phys_complete);
list_for_each_safe(_desc, n, &ioat->used_desc) {
struct ioat_desc_sw *desc;
@@ -652,7 +652,7 @@
static void ioat1_cleanup(struct ioat_dma_chan *ioat)
{
struct ioat_chan_common *chan = &ioat->base;
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
prefetch(chan->completion);
@@ -698,7 +698,7 @@
mod_timer(&chan->timer, jiffies + COMPLETION_TIMEOUT);
spin_unlock_bh(&ioat->desc_lock);
} else if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
spin_lock_bh(&ioat->desc_lock);
/* if we haven't made progress and we have already
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index c7888bc..5e8fe01 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -88,7 +88,7 @@
struct ioat_chan_common {
struct dma_chan common;
void __iomem *reg_base;
- unsigned long last_completion;
+ dma_addr_t last_completion;
spinlock_t cleanup_lock;
unsigned long state;
#define IOAT_COMPLETION_PENDING 0
@@ -310,7 +310,7 @@
void __devexit ioat_dma_remove(struct ioatdma_device *device);
struct dca_provider * __devinit ioat_dca_init(struct pci_dev *pdev,
void __iomem *iobase);
-unsigned long ioat_get_current_completion(struct ioat_chan_common *chan);
+dma_addr_t ioat_get_current_completion(struct ioat_chan_common *chan);
void ioat_init_channel(struct ioatdma_device *device,
struct ioat_chan_common *chan, int idx);
enum dma_status ioat_dma_tx_status(struct dma_chan *c, dma_cookie_t cookie,
@@ -318,7 +318,7 @@
void ioat_dma_unmap(struct ioat_chan_common *chan, enum dma_ctrl_flags flags,
size_t len, struct ioat_dma_descriptor *hw);
bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
- unsigned long *phys_complete);
+ dma_addr_t *phys_complete);
void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
void ioat_kobject_del(struct ioatdma_device *device);
extern const struct sysfs_ops ioat_sysfs_ops;
diff --git a/drivers/dma/ioat/dma_v2.c b/drivers/dma/ioat/dma_v2.c
index e8e110f..8689576 100644
--- a/drivers/dma/ioat/dma_v2.c
+++ b/drivers/dma/ioat/dma_v2.c
@@ -128,7 +128,7 @@
spin_unlock_bh(&ioat->prep_lock);
}
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
{
struct ioat_chan_common *chan = &ioat->base;
struct dma_async_tx_descriptor *tx;
@@ -179,7 +179,7 @@
static void ioat2_cleanup(struct ioat2_dma_chan *ioat)
{
struct ioat_chan_common *chan = &ioat->base;
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
spin_lock_bh(&chan->cleanup_lock);
if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -260,7 +260,7 @@
static void ioat2_restart_channel(struct ioat2_dma_chan *ioat)
{
struct ioat_chan_common *chan = &ioat->base;
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
ioat2_quiesce(chan, 0);
if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -275,7 +275,7 @@
struct ioat_chan_common *chan = &ioat->base;
if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
u64 status;
status = ioat_chansts(chan);
@@ -572,9 +572,9 @@
*/
struct ioat_chan_common *chan = &ioat->base;
struct dma_chan *c = &chan->common;
- const u16 curr_size = ioat2_ring_size(ioat);
+ const u32 curr_size = ioat2_ring_size(ioat);
const u16 active = ioat2_ring_active(ioat);
- const u16 new_size = 1 << order;
+ const u32 new_size = 1 << order;
struct ioat_ring_ent **ring;
u16 i;
diff --git a/drivers/dma/ioat/dma_v2.h b/drivers/dma/ioat/dma_v2.h
index a2c413b..be2a55b 100644
--- a/drivers/dma/ioat/dma_v2.h
+++ b/drivers/dma/ioat/dma_v2.h
@@ -74,7 +74,7 @@
return container_of(chan, struct ioat2_dma_chan, base);
}
-static inline u16 ioat2_ring_size(struct ioat2_dma_chan *ioat)
+static inline u32 ioat2_ring_size(struct ioat2_dma_chan *ioat)
{
return 1 << ioat->alloc_order;
}
@@ -91,7 +91,7 @@
return CIRC_CNT(ioat->head, ioat->issued, ioat2_ring_size(ioat));
}
-static inline u16 ioat2_ring_space(struct ioat2_dma_chan *ioat)
+static inline u32 ioat2_ring_space(struct ioat2_dma_chan *ioat)
{
return ioat2_ring_size(ioat) - ioat2_ring_active(ioat);
}
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index 2c4476c..f7f1dc6 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -257,7 +257,7 @@
* The difference from the dma_v2.c __cleanup() is that this routine
* handles extended descriptors and dma-unmapping raid operations.
*/
-static void __cleanup(struct ioat2_dma_chan *ioat, unsigned long phys_complete)
+static void __cleanup(struct ioat2_dma_chan *ioat, dma_addr_t phys_complete)
{
struct ioat_chan_common *chan = &ioat->base;
struct ioat_ring_ent *desc;
@@ -314,7 +314,7 @@
static void ioat3_cleanup(struct ioat2_dma_chan *ioat)
{
struct ioat_chan_common *chan = &ioat->base;
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
spin_lock_bh(&chan->cleanup_lock);
if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -333,7 +333,7 @@
static void ioat3_restart_channel(struct ioat2_dma_chan *ioat)
{
struct ioat_chan_common *chan = &ioat->base;
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
ioat2_quiesce(chan, 0);
if (ioat_cleanup_preamble(chan, &phys_complete))
@@ -348,7 +348,7 @@
struct ioat_chan_common *chan = &ioat->base;
if (test_bit(IOAT_COMPLETION_PENDING, &chan->state)) {
- unsigned long phys_complete;
+ dma_addr_t phys_complete;
u64 status;
status = ioat_chansts(chan);
@@ -1149,6 +1149,44 @@
return ioat2_reset_sync(chan, msecs_to_jiffies(200));
}
+static bool is_jf_ioat(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF0:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF1:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF2:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF3:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF4:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF5:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF6:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF7:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF8:
+ case PCI_DEVICE_ID_INTEL_IOAT_JSF9:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool is_snb_ioat(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB0:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB1:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB2:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB3:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB4:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB5:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB6:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB7:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB8:
+ case PCI_DEVICE_ID_INTEL_IOAT_SNB9:
+ return true;
+ default:
+ return false;
+ }
+}
+
int __devinit ioat3_dma_probe(struct ioatdma_device *device, int dca)
{
struct pci_dev *pdev = device->pdev;
@@ -1169,6 +1207,9 @@
dma->device_alloc_chan_resources = ioat2_alloc_chan_resources;
dma->device_free_chan_resources = ioat2_free_chan_resources;
+ if (is_jf_ioat(pdev) || is_snb_ioat(pdev))
+ dma->copy_align = 6;
+
dma_cap_set(DMA_INTERRUPT, dma->cap_mask);
dma->device_prep_dma_interrupt = ioat3_prep_interrupt_lock;
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c
index da6c4c2..79e3eba 100644
--- a/drivers/dma/iop-adma.c
+++ b/drivers/dma/iop-adma.c
@@ -1252,8 +1252,8 @@
struct page **pq_hw = &pq[IOP_ADMA_NUM_SRC_TEST+2];
/* address conversion buffers (dma_map / page_address) */
void *pq_sw[IOP_ADMA_NUM_SRC_TEST+2];
- dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST];
- dma_addr_t pq_dest[2];
+ dma_addr_t pq_src[IOP_ADMA_NUM_SRC_TEST+2];
+ dma_addr_t *pq_dest = &pq_src[IOP_ADMA_NUM_SRC_TEST];
int i;
struct dma_async_tx_descriptor *tx;
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index c81ef7e..655d4ce6 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -201,10 +201,6 @@
static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
{
- struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
-
- mxs_dma_enable_chan(mxs_chan);
-
return dma_cookie_assign(tx);
}
@@ -558,9 +554,9 @@
static void mxs_dma_issue_pending(struct dma_chan *chan)
{
- /*
- * Nothing to do. We only have a single descriptor.
- */
+ struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+
+ mxs_dma_enable_chan(mxs_chan);
}
static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 282caf1..2ee6e23 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2225,12 +2225,9 @@
{
struct dma_pl330_dmac *pdmac;
struct dma_pl330_desc *desc;
- struct dma_pl330_chan *pch;
+ struct dma_pl330_chan *pch = NULL;
unsigned long flags;
- if (list_empty(list))
- return;
-
/* Finish off the work list */
list_for_each_entry(desc, list, node) {
dma_async_tx_callback callback;
@@ -2247,6 +2244,10 @@
desc->pchan = NULL;
}
+ /* pch will be unset if list was empty */
+ if (!pch)
+ return;
+
pdmac = pch->dmac;
spin_lock_irqsave(&pdmac->pool_lock, flags);
@@ -2257,12 +2258,9 @@
static inline void handle_cyclic_desc_list(struct list_head *list)
{
struct dma_pl330_desc *desc;
- struct dma_pl330_chan *pch;
+ struct dma_pl330_chan *pch = NULL;
unsigned long flags;
- if (list_empty(list))
- return;
-
list_for_each_entry(desc, list, node) {
dma_async_tx_callback callback;
@@ -2274,6 +2272,10 @@
callback(desc->txd.callback_param);
}
+ /* pch will be unset if list was empty */
+ if (!pch)
+ return;
+
spin_lock_irqsave(&pch->lock, flags);
list_splice_tail_init(list, &pch->work_list);
spin_unlock_irqrestore(&pch->lock, flags);
@@ -2926,8 +2928,11 @@
INIT_LIST_HEAD(&pd->channels);
/* Initialize channel parameters */
- num_chan = max(pdat ? pdat->nr_valid_peri : (u8)pi->pcfg.num_peri,
- (u8)pi->pcfg.num_chan);
+ if (pdat)
+ num_chan = max_t(int, pdat->nr_valid_peri, pi->pcfg.num_chan);
+ else
+ num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
+
pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
for (i = 0; i < num_chan; i++) {
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c
index 16a6b48..ec78cce 100644
--- a/drivers/dma/sa11x0-dma.c
+++ b/drivers/dma/sa11x0-dma.c
@@ -585,7 +585,7 @@
static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg(
struct dma_chan *chan, struct scatterlist *sg, unsigned int sglen,
- enum dma_transfer_direction dir, unsigned long flags)
+ enum dma_transfer_direction dir, unsigned long flags, void *context)
{
struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan);
struct sa11x0_dma_desc *txd;
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index bdd41d4..2ed1ac3 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <linux/amba/bus.h>
+#include <linux/regulator/consumer.h>
#include <plat/ste_dma40.h>
@@ -69,6 +70,22 @@
};
/*
+ * enum d40_events - The different Event Enables for the event lines.
+ *
+ * @D40_DEACTIVATE_EVENTLINE: De-activate Event line, stopping the logical chan.
+ * @D40_ACTIVATE_EVENTLINE: Activate the Event line, to start a logical chan.
+ * @D40_SUSPEND_REQ_EVENTLINE: Requesting for suspending a event line.
+ * @D40_ROUND_EVENTLINE: Status check for event line.
+ */
+
+enum d40_events {
+ D40_DEACTIVATE_EVENTLINE = 0,
+ D40_ACTIVATE_EVENTLINE = 1,
+ D40_SUSPEND_REQ_EVENTLINE = 2,
+ D40_ROUND_EVENTLINE = 3
+};
+
+/*
* These are the registers that has to be saved and later restored
* when the DMA hw is powered off.
* TODO: Add save/restore of D40_DREG_GCC on dma40 v3 or later, if that works.
@@ -870,8 +887,8 @@
}
#endif
-static int d40_channel_execute_command(struct d40_chan *d40c,
- enum d40_command command)
+static int __d40_execute_command_phy(struct d40_chan *d40c,
+ enum d40_command command)
{
u32 status;
int i;
@@ -880,6 +897,12 @@
unsigned long flags;
u32 wmask;
+ if (command == D40_DMA_STOP) {
+ ret = __d40_execute_command_phy(d40c, D40_DMA_SUSPEND_REQ);
+ if (ret)
+ return ret;
+ }
+
spin_lock_irqsave(&d40c->base->execmd_lock, flags);
if (d40c->phy_chan->num % 2 == 0)
@@ -973,67 +996,109 @@
}
d40c->pending_tx = 0;
- d40c->busy = false;
}
-static void __d40_config_set_event(struct d40_chan *d40c, bool enable,
- u32 event, int reg)
+static void __d40_config_set_event(struct d40_chan *d40c,
+ enum d40_events event_type, u32 event,
+ int reg)
{
void __iomem *addr = chan_base(d40c) + reg;
int tries;
+ u32 status;
- if (!enable) {
+ switch (event_type) {
+
+ case D40_DEACTIVATE_EVENTLINE:
+
writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
| ~D40_EVENTLINE_MASK(event), addr);
- return;
- }
+ break;
+ case D40_SUSPEND_REQ_EVENTLINE:
+ status = (readl(addr) & D40_EVENTLINE_MASK(event)) >>
+ D40_EVENTLINE_POS(event);
+
+ if (status == D40_DEACTIVATE_EVENTLINE ||
+ status == D40_SUSPEND_REQ_EVENTLINE)
+ break;
+
+ writel((D40_SUSPEND_REQ_EVENTLINE << D40_EVENTLINE_POS(event))
+ | ~D40_EVENTLINE_MASK(event), addr);
+
+ for (tries = 0 ; tries < D40_SUSPEND_MAX_IT; tries++) {
+
+ status = (readl(addr) & D40_EVENTLINE_MASK(event)) >>
+ D40_EVENTLINE_POS(event);
+
+ cpu_relax();
+ /*
+ * Reduce the number of bus accesses while
+ * waiting for the DMA to suspend.
+ */
+ udelay(3);
+
+ if (status == D40_DEACTIVATE_EVENTLINE)
+ break;
+ }
+
+ if (tries == D40_SUSPEND_MAX_IT) {
+ chan_err(d40c,
+ "unable to stop the event_line chl %d (log: %d)"
+ "status %x\n", d40c->phy_chan->num,
+ d40c->log_num, status);
+ }
+ break;
+
+ case D40_ACTIVATE_EVENTLINE:
/*
* The hardware sometimes doesn't register the enable when src and dst
* event lines are active on the same logical channel. Retry to ensure
* it does. Usually only one retry is sufficient.
*/
- tries = 100;
- while (--tries) {
- writel((D40_ACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
- | ~D40_EVENTLINE_MASK(event), addr);
+ tries = 100;
+ while (--tries) {
+ writel((D40_ACTIVATE_EVENTLINE <<
+ D40_EVENTLINE_POS(event)) |
+ ~D40_EVENTLINE_MASK(event), addr);
- if (readl(addr) & D40_EVENTLINE_MASK(event))
- break;
+ if (readl(addr) & D40_EVENTLINE_MASK(event))
+ break;
+ }
+
+ if (tries != 99)
+ dev_dbg(chan2dev(d40c),
+ "[%s] workaround enable S%cLNK (%d tries)\n",
+ __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
+ 100 - tries);
+
+ WARN_ON(!tries);
+ break;
+
+ case D40_ROUND_EVENTLINE:
+ BUG();
+ break;
+
}
-
- if (tries != 99)
- dev_dbg(chan2dev(d40c),
- "[%s] workaround enable S%cLNK (%d tries)\n",
- __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
- 100 - tries);
-
- WARN_ON(!tries);
}
-static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
+static void d40_config_set_event(struct d40_chan *d40c,
+ enum d40_events event_type)
{
- unsigned long flags;
-
- spin_lock_irqsave(&d40c->phy_chan->lock, flags);
-
/* Enable event line connected to device (or memcpy) */
if ((d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) ||
(d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) {
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
- __d40_config_set_event(d40c, do_enable, event,
+ __d40_config_set_event(d40c, event_type, event,
D40_CHAN_REG_SSLNK);
}
if (d40c->dma_cfg.dir != STEDMA40_PERIPH_TO_MEM) {
u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
- __d40_config_set_event(d40c, do_enable, event,
+ __d40_config_set_event(d40c, event_type, event,
D40_CHAN_REG_SDLNK);
}
-
- spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
}
static u32 d40_chan_has_events(struct d40_chan *d40c)
@@ -1047,6 +1112,64 @@
return val;
}
+static int
+__d40_execute_command_log(struct d40_chan *d40c, enum d40_command command)
+{
+ unsigned long flags;
+ int ret = 0;
+ u32 active_status;
+ void __iomem *active_reg;
+
+ if (d40c->phy_chan->num % 2 == 0)
+ active_reg = d40c->base->virtbase + D40_DREG_ACTIVE;
+ else
+ active_reg = d40c->base->virtbase + D40_DREG_ACTIVO;
+
+
+ spin_lock_irqsave(&d40c->phy_chan->lock, flags);
+
+ switch (command) {
+ case D40_DMA_STOP:
+ case D40_DMA_SUSPEND_REQ:
+
+ active_status = (readl(active_reg) &
+ D40_CHAN_POS_MASK(d40c->phy_chan->num)) >>
+ D40_CHAN_POS(d40c->phy_chan->num);
+
+ if (active_status == D40_DMA_RUN)
+ d40_config_set_event(d40c, D40_SUSPEND_REQ_EVENTLINE);
+ else
+ d40_config_set_event(d40c, D40_DEACTIVATE_EVENTLINE);
+
+ if (!d40_chan_has_events(d40c) && (command == D40_DMA_STOP))
+ ret = __d40_execute_command_phy(d40c, command);
+
+ break;
+
+ case D40_DMA_RUN:
+
+ d40_config_set_event(d40c, D40_ACTIVATE_EVENTLINE);
+ ret = __d40_execute_command_phy(d40c, command);
+ break;
+
+ case D40_DMA_SUSPENDED:
+ BUG();
+ break;
+ }
+
+ spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
+ return ret;
+}
+
+static int d40_channel_execute_command(struct d40_chan *d40c,
+ enum d40_command command)
+{
+ if (chan_is_logical(d40c))
+ return __d40_execute_command_log(d40c, command);
+ else
+ return __d40_execute_command_phy(d40c, command);
+}
+
static u32 d40_get_prmo(struct d40_chan *d40c)
{
static const unsigned int phy_map[] = {
@@ -1149,15 +1272,7 @@
spin_lock_irqsave(&d40c->lock, flags);
res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
- if (res == 0) {
- if (chan_is_logical(d40c)) {
- d40_config_set_event(d40c, false);
- /* Resume the other logical channels if any */
- if (d40_chan_has_events(d40c))
- res = d40_channel_execute_command(d40c,
- D40_DMA_RUN);
- }
- }
+
pm_runtime_mark_last_busy(d40c->base->dev);
pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
@@ -1174,45 +1289,17 @@
spin_lock_irqsave(&d40c->lock, flags);
pm_runtime_get_sync(d40c->base->dev);
- if (d40c->base->rev == 0)
- if (chan_is_logical(d40c)) {
- res = d40_channel_execute_command(d40c,
- D40_DMA_SUSPEND_REQ);
- goto no_suspend;
- }
/* If bytes left to transfer or linked tx resume job */
- if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
-
- if (chan_is_logical(d40c))
- d40_config_set_event(d40c, true);
-
+ if (d40_residue(d40c) || d40_tx_is_linked(d40c))
res = d40_channel_execute_command(d40c, D40_DMA_RUN);
- }
-no_suspend:
pm_runtime_mark_last_busy(d40c->base->dev);
pm_runtime_put_autosuspend(d40c->base->dev);
spin_unlock_irqrestore(&d40c->lock, flags);
return res;
}
-static int d40_terminate_all(struct d40_chan *chan)
-{
- unsigned long flags;
- int ret = 0;
-
- ret = d40_pause(chan);
- if (!ret && chan_is_physical(chan))
- ret = d40_channel_execute_command(chan, D40_DMA_STOP);
-
- spin_lock_irqsave(&chan->lock, flags);
- d40_term_all(chan);
- spin_unlock_irqrestore(&chan->lock, flags);
-
- return ret;
-}
-
static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
{
struct d40_chan *d40c = container_of(tx->chan,
@@ -1232,20 +1319,6 @@
static int d40_start(struct d40_chan *d40c)
{
- if (d40c->base->rev == 0) {
- int err;
-
- if (chan_is_logical(d40c)) {
- err = d40_channel_execute_command(d40c,
- D40_DMA_SUSPEND_REQ);
- if (err)
- return err;
- }
- }
-
- if (chan_is_logical(d40c))
- d40_config_set_event(d40c, true);
-
return d40_channel_execute_command(d40c, D40_DMA_RUN);
}
@@ -1258,10 +1331,10 @@
d40d = d40_first_queued(d40c);
if (d40d != NULL) {
- if (!d40c->busy)
+ if (!d40c->busy) {
d40c->busy = true;
-
- pm_runtime_get_sync(d40c->base->dev);
+ pm_runtime_get_sync(d40c->base->dev);
+ }
/* Remove from queue */
d40_desc_remove(d40d);
@@ -1388,8 +1461,8 @@
return;
- err:
- /* Rescue manoeuvre if receiving double interrupts */
+err:
+ /* Rescue manouver if receiving double interrupts */
if (d40c->pending_tx > 0)
d40c->pending_tx--;
spin_unlock_irqrestore(&d40c->lock, flags);
@@ -1770,7 +1843,6 @@
return 0;
}
-
static int d40_free_dma(struct d40_chan *d40c)
{
@@ -1806,44 +1878,19 @@
}
pm_runtime_get_sync(d40c->base->dev);
- res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
- if (res) {
- chan_err(d40c, "suspend failed\n");
- goto out;
- }
-
- if (chan_is_logical(d40c)) {
- /* Release logical channel, deactivate the event line */
-
- d40_config_set_event(d40c, false);
- d40c->base->lookup_log_chans[d40c->log_num] = NULL;
-
- /*
- * Check if there are more logical allocation
- * on this phy channel.
- */
- if (!d40_alloc_mask_free(phy, is_src, event)) {
- /* Resume the other logical channels if any */
- if (d40_chan_has_events(d40c)) {
- res = d40_channel_execute_command(d40c,
- D40_DMA_RUN);
- if (res)
- chan_err(d40c,
- "Executing RUN command\n");
- }
- goto out;
- }
- } else {
- (void) d40_alloc_mask_free(phy, is_src, 0);
- }
-
- /* Release physical channel */
res = d40_channel_execute_command(d40c, D40_DMA_STOP);
if (res) {
- chan_err(d40c, "Failed to stop channel\n");
+ chan_err(d40c, "stop failed\n");
goto out;
}
+ d40_alloc_mask_free(phy, is_src, chan_is_logical(d40c) ? event : 0);
+
+ if (chan_is_logical(d40c))
+ d40c->base->lookup_log_chans[d40c->log_num] = NULL;
+ else
+ d40c->base->lookup_phy_chans[phy->num] = NULL;
+
if (d40c->busy) {
pm_runtime_mark_last_busy(d40c->base->dev);
pm_runtime_put_autosuspend(d40c->base->dev);
@@ -1852,7 +1899,6 @@
d40c->busy = false;
d40c->phy_chan = NULL;
d40c->configured = false;
- d40c->base->lookup_phy_chans[phy->num] = NULL;
out:
pm_runtime_mark_last_busy(d40c->base->dev);
@@ -2070,7 +2116,7 @@
if (sg_next(&sg_src[sg_len - 1]) == sg_src)
desc->cyclic = true;
- if (direction != DMA_NONE) {
+ if (direction != DMA_TRANS_NONE) {
dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
if (direction == DMA_DEV_TO_MEM)
@@ -2371,6 +2417,31 @@
spin_unlock_irqrestore(&d40c->lock, flags);
}
+static void d40_terminate_all(struct dma_chan *chan)
+{
+ unsigned long flags;
+ struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
+ int ret;
+
+ spin_lock_irqsave(&d40c->lock, flags);
+
+ pm_runtime_get_sync(d40c->base->dev);
+ ret = d40_channel_execute_command(d40c, D40_DMA_STOP);
+ if (ret)
+ chan_err(d40c, "Failed to stop channel\n");
+
+ d40_term_all(d40c);
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
+ if (d40c->busy) {
+ pm_runtime_mark_last_busy(d40c->base->dev);
+ pm_runtime_put_autosuspend(d40c->base->dev);
+ }
+ d40c->busy = false;
+
+ spin_unlock_irqrestore(&d40c->lock, flags);
+}
+
static int
dma40_config_to_halfchannel(struct d40_chan *d40c,
struct stedma40_half_channel_info *info,
@@ -2551,7 +2622,8 @@
switch (cmd) {
case DMA_TERMINATE_ALL:
- return d40_terminate_all(d40c);
+ d40_terminate_all(chan);
+ return 0;
case DMA_PAUSE:
return d40_pause(d40c);
case DMA_RESUME:
@@ -2908,6 +2980,12 @@
dev_info(&pdev->dev, "hardware revision: %d @ 0x%x\n",
rev, res->start);
+ if (rev < 2) {
+ d40_err(&pdev->dev, "hardware revision: %d is not supported",
+ rev);
+ goto failure;
+ }
+
plat_data = pdev->dev.platform_data;
/* Count the number of logical channels in use */
@@ -2998,6 +3076,7 @@
if (base) {
kfree(base->lcla_pool.alloc_map);
+ kfree(base->reg_val_backup_chan);
kfree(base->lookup_log_chans);
kfree(base->lookup_phy_chans);
kfree(base->phy_res);
diff --git a/drivers/dma/ste_dma40_ll.h b/drivers/dma/ste_dma40_ll.h
index 8d3d490..51e8e53 100644
--- a/drivers/dma/ste_dma40_ll.h
+++ b/drivers/dma/ste_dma40_ll.h
@@ -62,8 +62,6 @@
#define D40_SREG_ELEM_LOG_LIDX_MASK (0xFF << D40_SREG_ELEM_LOG_LIDX_POS)
/* Link register */
-#define D40_DEACTIVATE_EVENTLINE 0x0
-#define D40_ACTIVATE_EVENTLINE 0x1
#define D40_EVENTLINE_POS(i) (2 * i)
#define D40_EVENTLINE_MASK(i) (0x3 << D40_EVENTLINE_POS(i))
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 36e1486..d0c372e 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -754,9 +754,7 @@
if (c->x86_vendor != X86_VENDOR_AMD)
return 0;
- if ((c->x86 < 0xf || c->x86 > 0x12) &&
- (c->x86 != 0x14 || c->x86_model > 0xf) &&
- (c->x86 != 0x15 || c->x86_model > 0xf))
+ if (c->x86 < 0xf || c->x86 > 0x15)
return 0;
fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL);
@@ -797,7 +795,7 @@
break;
default:
- printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86);
+ printk(KERN_WARNING "Huh? What family is it: 0x%x?!\n", c->x86);
kfree(fam_ops);
return -EINVAL;
}
diff --git a/drivers/edac/tile_edac.c b/drivers/edac/tile_edac.c
index 1d5cf06..e99d009 100644
--- a/drivers/edac/tile_edac.c
+++ b/drivers/edac/tile_edac.c
@@ -145,7 +145,11 @@
mci->edac_ctl_cap = EDAC_FLAG_SECDED;
mci->mod_name = DRV_NAME;
+#ifdef __tilegx__
+ mci->ctl_name = "TILEGx_Memory_Controller";
+#else
mci->ctl_name = "TILEPro_Memory_Controller";
+#endif
mci->dev_name = dev_name(&pdev->dev);
mci->edac_check = tile_edac_check;
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index d25599f..47408e8 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -191,6 +191,190 @@
}
}
+static bool
+validate_device_path(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ struct efi_generic_dev_path *node;
+ int offset = 0;
+
+ node = (struct efi_generic_dev_path *)buffer;
+
+ if (len < sizeof(*node))
+ return false;
+
+ while (offset <= len - sizeof(*node) &&
+ node->length >= sizeof(*node) &&
+ node->length <= len - offset) {
+ offset += node->length;
+
+ if ((node->type == EFI_DEV_END_PATH ||
+ node->type == EFI_DEV_END_PATH2) &&
+ node->sub_type == EFI_DEV_END_ENTIRE)
+ return true;
+
+ node = (struct efi_generic_dev_path *)(buffer + offset);
+ }
+
+ /*
+ * If we're here then either node->length pointed past the end
+ * of the buffer or we reached the end of the buffer without
+ * finding a device path end node.
+ */
+ return false;
+}
+
+static bool
+validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ /* An array of 16-bit integers */
+ if ((len % 2) != 0)
+ return false;
+
+ return true;
+}
+
+static bool
+validate_load_option(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ u16 filepathlength;
+ int i, desclength = 0, namelen;
+
+ namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
+
+ /* Either "Boot" or "Driver" followed by four digits of hex */
+ for (i = match; i < match+4; i++) {
+ if (var->VariableName[i] > 127 ||
+ hex_to_bin(var->VariableName[i] & 0xff) < 0)
+ return true;
+ }
+
+ /* Reject it if there's 4 digits of hex and then further content */
+ if (namelen > match + 4)
+ return false;
+
+ /* A valid entry must be at least 8 bytes */
+ if (len < 8)
+ return false;
+
+ filepathlength = buffer[4] | buffer[5] << 8;
+
+ /*
+ * There's no stored length for the description, so it has to be
+ * found by hand
+ */
+ desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
+
+ /* Each boot entry must have a descriptor */
+ if (!desclength)
+ return false;
+
+ /*
+ * If the sum of the length of the description, the claimed filepath
+ * length and the original header are greater than the length of the
+ * variable, it's malformed
+ */
+ if ((desclength + filepathlength + 6) > len)
+ return false;
+
+ /*
+ * And, finally, check the filepath
+ */
+ return validate_device_path(var, match, buffer + desclength + 6,
+ filepathlength);
+}
+
+static bool
+validate_uint16(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ /* A single 16-bit integer */
+ if (len != 2)
+ return false;
+
+ return true;
+}
+
+static bool
+validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (buffer[i] > 127)
+ return false;
+
+ if (buffer[i] == 0)
+ return true;
+ }
+
+ return false;
+}
+
+struct variable_validate {
+ char *name;
+ bool (*validate)(struct efi_variable *var, int match, u8 *data,
+ unsigned long len);
+};
+
+static const struct variable_validate variable_validate[] = {
+ { "BootNext", validate_uint16 },
+ { "BootOrder", validate_boot_order },
+ { "DriverOrder", validate_boot_order },
+ { "Boot*", validate_load_option },
+ { "Driver*", validate_load_option },
+ { "ConIn", validate_device_path },
+ { "ConInDev", validate_device_path },
+ { "ConOut", validate_device_path },
+ { "ConOutDev", validate_device_path },
+ { "ErrOut", validate_device_path },
+ { "ErrOutDev", validate_device_path },
+ { "Timeout", validate_uint16 },
+ { "Lang", validate_ascii_string },
+ { "PlatformLang", validate_ascii_string },
+ { "", NULL },
+};
+
+static bool
+validate_var(struct efi_variable *var, u8 *data, unsigned long len)
+{
+ int i;
+ u16 *unicode_name = var->VariableName;
+
+ for (i = 0; variable_validate[i].validate != NULL; i++) {
+ const char *name = variable_validate[i].name;
+ int match;
+
+ for (match = 0; ; match++) {
+ char c = name[match];
+ u16 u = unicode_name[match];
+
+ /* All special variables are plain ascii */
+ if (u > 127)
+ return true;
+
+ /* Wildcard in the matching name means we've matched */
+ if (c == '*')
+ return variable_validate[i].validate(var,
+ match, data, len);
+
+ /* Case sensitive match */
+ if (c != u)
+ break;
+
+ /* Reached the end of the string while matching */
+ if (!c)
+ return variable_validate[i].validate(var,
+ match, data, len);
+ }
+ }
+
+ return true;
+}
+
static efi_status_t
get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
{
@@ -324,6 +508,12 @@
return -EINVAL;
}
+ if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+ validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+
spin_lock(&efivars->lock);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
@@ -626,6 +816,12 @@
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
+ if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+ validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+
spin_lock(&efivars->lock);
/*
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index edadbda..e03653d 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -430,7 +430,7 @@
config GPIO_SODAVILLE
bool "Intel Sodaville GPIO support"
- depends on X86 && PCI && OF && BROKEN
+ depends on X86 && PCI && OF
select GPIO_GENERIC
select GENERIC_IRQ_CHIP
help
diff --git a/drivers/gpio/gpio-adp5588.c b/drivers/gpio/gpio-adp5588.c
index 9ad1703..ae5d7f1 100644
--- a/drivers/gpio/gpio-adp5588.c
+++ b/drivers/gpio/gpio-adp5588.c
@@ -252,7 +252,7 @@
if (ret < 0)
memset(dev->irq_stat, 0, ARRAY_SIZE(dev->irq_stat));
- for (bank = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
+ for (bank = 0, bit = 0; bank <= ADP5588_BANK(ADP5588_MAXGPIO);
bank++, bit = 0) {
pending = dev->irq_stat[bank] & dev->irq_mask[bank];
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 5689ce6..fc3ace3 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -64,6 +64,7 @@
unsigned long irq_mask;
unsigned long irq_edge_rise;
unsigned long irq_edge_fall;
+ int (*set_wake)(unsigned int gpio, unsigned int on);
#ifdef CONFIG_PM
unsigned long saved_gplr;
@@ -269,7 +270,8 @@
(value ? GPSR_OFFSET : GPCR_OFFSET));
}
-static int __devinit pxa_init_gpio_chip(int gpio_end)
+static int __devinit pxa_init_gpio_chip(int gpio_end,
+ int (*set_wake)(unsigned int, unsigned int))
{
int i, gpio, nbanks = gpio_to_bank(gpio_end) + 1;
struct pxa_gpio_chip *chips;
@@ -285,6 +287,7 @@
sprintf(chips[i].label, "gpio-%d", i);
chips[i].regbase = gpio_reg_base + BANK_OFF(i);
+ chips[i].set_wake = set_wake;
c->base = gpio;
c->label = chips[i].label;
@@ -412,6 +415,17 @@
writel_relaxed(gfer, c->regbase + GFER_OFFSET);
}
+static int pxa_gpio_set_wake(struct irq_data *d, unsigned int on)
+{
+ int gpio = pxa_irq_to_gpio(d->irq);
+ struct pxa_gpio_chip *c = gpio_to_pxachip(gpio);
+
+ if (c->set_wake)
+ return c->set_wake(gpio, on);
+ else
+ return 0;
+}
+
static void pxa_unmask_muxed_gpio(struct irq_data *d)
{
int gpio = pxa_irq_to_gpio(d->irq);
@@ -427,6 +441,7 @@
.irq_mask = pxa_mask_muxed_gpio,
.irq_unmask = pxa_unmask_muxed_gpio,
.irq_set_type = pxa_gpio_irq_type,
+ .irq_set_wake = pxa_gpio_set_wake,
};
static int pxa_gpio_nums(void)
@@ -471,6 +486,7 @@
struct pxa_gpio_chip *c;
struct resource *res;
struct clk *clk;
+ struct pxa_gpio_platform_data *info;
int gpio, irq, ret;
int irq0 = 0, irq1 = 0, irq_mux, gpio_offset = 0;
@@ -516,7 +532,8 @@
}
/* Initialize GPIO chips */
- pxa_init_gpio_chip(pxa_last_gpio);
+ info = dev_get_platdata(&pdev->dev);
+ pxa_init_gpio_chip(pxa_last_gpio, info ? info->gpio_set_wake : NULL);
/* clear all GPIO edge detects */
for_each_gpio_chip(gpio, c) {
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 4627787..19d6fc0 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -2382,8 +2382,8 @@
#endif
};
-static struct samsung_gpio_chip exynos5_gpios_1[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_1[] = {
{
.chip = {
.base = EXYNOS5_GPA0(0),
@@ -2541,11 +2541,11 @@
.to_irq = samsung_gpiolib_to_irq,
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_2[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_2[] = {
{
.chip = {
.base = EXYNOS5_GPE0(0),
@@ -2602,11 +2602,11 @@
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_3[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_3[] = {
{
.chip = {
.base = EXYNOS5_GPV0(0),
@@ -2638,11 +2638,11 @@
.label = "GPV4",
},
},
-#endif
};
+#endif
-static struct samsung_gpio_chip exynos5_gpios_4[] = {
#ifdef CONFIG_ARCH_EXYNOS5
+static struct samsung_gpio_chip exynos5_gpios_4[] = {
{
.chip = {
.base = EXYNOS5_GPZ(0),
@@ -2650,8 +2650,8 @@
.label = "GPZ",
},
},
-#endif
};
+#endif
#if defined(CONFIG_ARCH_EXYNOS) && defined(CONFIG_OF)
diff --git a/drivers/gpio/gpio-sodaville.c b/drivers/gpio/gpio-sodaville.c
index 9ba15d3..031e5d2 100644
--- a/drivers/gpio/gpio-sodaville.c
+++ b/drivers/gpio/gpio-sodaville.c
@@ -41,7 +41,7 @@
struct sdv_gpio_chip_data {
int irq_base;
void __iomem *gpio_pub_base;
- struct irq_domain id;
+ struct irq_domain *id;
struct irq_chip_generic *gc;
struct bgpio_chip bgpio;
};
@@ -51,10 +51,9 @@
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct sdv_gpio_chip_data *sd = gc->private;
void __iomem *type_reg;
- u32 irq_offs = d->irq - sd->irq_base;
u32 reg;
- if (irq_offs < 8)
+ if (d->hwirq < 8)
type_reg = sd->gpio_pub_base + GPIT1R0;
else
type_reg = sd->gpio_pub_base + GPIT1R1;
@@ -63,11 +62,11 @@
switch (type) {
case IRQ_TYPE_LEVEL_HIGH:
- reg &= ~BIT(4 * (irq_offs % 8));
+ reg &= ~BIT(4 * (d->hwirq % 8));
break;
case IRQ_TYPE_LEVEL_LOW:
- reg |= BIT(4 * (irq_offs % 8));
+ reg |= BIT(4 * (d->hwirq % 8));
break;
default:
@@ -91,7 +90,7 @@
u32 irq_bit = __fls(irq_stat);
irq_stat &= ~BIT(irq_bit);
- generic_handle_irq(sd->irq_base + irq_bit);
+ generic_handle_irq(irq_find_mapping(sd->id, irq_bit));
}
return IRQ_HANDLED;
@@ -127,7 +126,7 @@
}
static struct irq_domain_ops irq_domain_sdv_ops = {
- .dt_translate = sdv_xlate,
+ .xlate = sdv_xlate,
};
static __devinit int sdv_register_irqsupport(struct sdv_gpio_chip_data *sd,
@@ -149,10 +148,6 @@
if (ret)
goto out_free_desc;
- sd->id.irq_base = sd->irq_base;
- sd->id.of_node = of_node_get(pdev->dev.of_node);
- sd->id.ops = &irq_domain_sdv_ops;
-
/*
* This gpio irq controller latches level irqs. Testing shows that if
* we unmask & ACK the IRQ before the source of the interrupt is gone
@@ -179,7 +174,10 @@
IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST,
IRQ_LEVEL | IRQ_NOPROBE);
- irq_domain_add(&sd->id);
+ sd->id = irq_domain_add_legacy(pdev->dev.of_node, SDV_NUM_PUB_GPIOS,
+ sd->irq_base, 0, &irq_domain_sdv_ops, sd);
+ if (!sd->id)
+ goto out_free_irq;
return 0;
out_free_irq:
free_irq(pdev->irq, sd);
@@ -260,7 +258,6 @@
{
struct sdv_gpio_chip_data *sd = pci_get_drvdata(pdev);
- irq_domain_del(&sd->id);
free_irq(pdev->irq, sd);
irq_free_descs(sd->irq_base, SDV_NUM_PUB_GPIOS);
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 32de670..12f349b3 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -22,7 +22,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/gpio.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/irqdomain.h>
@@ -37,7 +37,8 @@
#define GPIO_PORT(x) (((x) >> 3) & 0x3)
#define GPIO_BIT(x) ((x) & 0x7)
-#define GPIO_REG(x) (GPIO_BANK(x) * 0x80 + GPIO_PORT(x) * 4)
+#define GPIO_REG(x) (GPIO_BANK(x) * tegra_gpio_bank_stride + \
+ GPIO_PORT(x) * 4)
#define GPIO_CNF(x) (GPIO_REG(x) + 0x00)
#define GPIO_OE(x) (GPIO_REG(x) + 0x10)
@@ -48,12 +49,12 @@
#define GPIO_INT_LVL(x) (GPIO_REG(x) + 0x60)
#define GPIO_INT_CLR(x) (GPIO_REG(x) + 0x70)
-#define GPIO_MSK_CNF(x) (GPIO_REG(x) + 0x800)
-#define GPIO_MSK_OE(x) (GPIO_REG(x) + 0x810)
-#define GPIO_MSK_OUT(x) (GPIO_REG(x) + 0X820)
-#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + 0x840)
-#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + 0x850)
-#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + 0x860)
+#define GPIO_MSK_CNF(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x00)
+#define GPIO_MSK_OE(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x10)
+#define GPIO_MSK_OUT(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0X20)
+#define GPIO_MSK_INT_STA(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x40)
+#define GPIO_MSK_INT_ENB(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x50)
+#define GPIO_MSK_INT_LVL(x) (GPIO_REG(x) + tegra_gpio_upper_offset + 0x60)
#define GPIO_INT_LVL_MASK 0x010101
#define GPIO_INT_LVL_EDGE_RISING 0x000101
@@ -78,6 +79,8 @@
static struct irq_domain *irq_domain;
static void __iomem *regs;
static u32 tegra_gpio_bank_count;
+static u32 tegra_gpio_bank_stride;
+static u32 tegra_gpio_upper_offset;
static struct tegra_gpio_bank *tegra_gpio_banks;
static inline void tegra_gpio_writel(u32 val, u32 reg)
@@ -333,6 +336,26 @@
#endif
};
+struct tegra_gpio_soc_config {
+ u32 bank_stride;
+ u32 upper_offset;
+};
+
+static struct tegra_gpio_soc_config tegra20_gpio_config = {
+ .bank_stride = 0x80,
+ .upper_offset = 0x800,
+};
+
+static struct tegra_gpio_soc_config tegra30_gpio_config = {
+ .bank_stride = 0x100,
+ .upper_offset = 0x80,
+};
+
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
+ { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
+ { },
+};
/* This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
@@ -341,6 +364,8 @@
static int __devinit tegra_gpio_probe(struct platform_device *pdev)
{
+ const struct of_device_id *match;
+ struct tegra_gpio_soc_config *config;
int irq_base;
struct resource *res;
struct tegra_gpio_bank *bank;
@@ -348,6 +373,15 @@
int i;
int j;
+ match = of_match_device(tegra_gpio_of_match, &pdev->dev);
+ if (match)
+ config = (struct tegra_gpio_soc_config *)match->data;
+ else
+ config = &tegra20_gpio_config;
+
+ tegra_gpio_bank_stride = config->bank_stride;
+ tegra_gpio_upper_offset = config->upper_offset;
+
for (;;) {
res = platform_get_resource(pdev, IORESOURCE_IRQ, tegra_gpio_bank_count);
if (!res)
@@ -402,7 +436,7 @@
return -ENODEV;
}
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
tegra_gpio_writel(0x00, GPIO_INT_ENB(gpio));
@@ -441,11 +475,6 @@
return 0;
}
-static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
- { .compatible = "nvidia,tegra20-gpio", },
- { },
-};
-
static struct platform_driver tegra_gpio_driver = {
.driver = {
.name = "tegra-gpio",
@@ -485,7 +514,7 @@
int i;
int j;
- for (i = 0; i < 7; i++) {
+ for (i = 0; i < tegra_gpio_bank_count; i++) {
for (j = 0; j < 4; j++) {
int gpio = tegra_gpio_compose(i, j, 0);
seq_printf(s,
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index cc11488..e354bc0 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -9,6 +9,7 @@
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
select I2C
select I2C_ALGOBIT
+ select DMA_SHARED_BUFFER
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a858532..c20da5b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,7 @@
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
drm_crtc.o drm_modes.o drm_edid.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \
- drm_trace_points.o drm_global.o
+ drm_trace_points.o drm_global.o drm_prime.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 30372f7..348b367 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1510,8 +1510,8 @@
* \param arg pointer to a drm_buf_map structure.
* \return zero on success or a negative number on failure.
*
- * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
- * about each buffer into user space. For PCI buffers, it calls do_mmap() with
+ * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
+ * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
* offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
* drm_mmap_dma().
*/
@@ -1553,18 +1553,14 @@
retcode = -EINVAL;
goto done;
}
- down_write(¤t->mm->mmap_sem);
- virtual = do_mmap(file_priv->filp, 0, map->size,
+ virtual = vm_mmap(file_priv->filp, 0, map->size,
PROT_READ | PROT_WRITE,
MAP_SHARED,
token);
- up_write(¤t->mm->mmap_sem);
} else {
- down_write(¤t->mm->mmap_sem);
- virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
+ virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
PROT_READ | PROT_WRITE,
MAP_SHARED, 0);
- up_write(¤t->mm->mmap_sem);
}
if (virtual > -1024UL) {
/* Real error */
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index d3aaeb6..c79870a 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3335,10 +3335,12 @@
ret = crtc->funcs->page_flip(crtc, fb, e);
if (ret) {
- spin_lock_irqsave(&dev->event_lock, flags);
- file_priv->event_space += sizeof e->event;
- spin_unlock_irqrestore(&dev->event_lock, flags);
- kfree(e);
+ if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+ spin_lock_irqsave(&dev->event_lock, flags);
+ file_priv->event_space += sizeof e->event;
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ kfree(e);
+ }
}
out:
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 0b65fbc..6116e3b 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -136,6 +136,10 @@
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED),
+
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 7740dd2..a0d6e89 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -559,9 +559,13 @@
return -EINVAL;
/* Need to resize the fb object !!! */
- if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+ if (var->bits_per_pixel > fb->bits_per_pixel ||
+ var->xres > fb->width || var->yres > fb->height ||
+ var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
- "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+ "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
+ var->xres, var->yres, var->bits_per_pixel,
+ var->xres_virtual, var->yres_virtual,
fb->width, fb->height, fb->bits_per_pixel);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7348a3d..123de28 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -271,6 +271,9 @@
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_open(dev, priv);
+ if (drm_core_check_feature(dev, DRIVER_PRIME))
+ drm_prime_init_file_private(&priv->prime);
+
if (dev->driver->open) {
ret = dev->driver->open(dev, priv);
if (ret < 0)
@@ -504,12 +507,12 @@
drm_events_release(file_priv);
- if (dev->driver->driver_features & DRIVER_GEM)
- drm_gem_release(dev, file_priv);
-
if (dev->driver->driver_features & DRIVER_MODESET)
drm_fb_release(file_priv);
+ if (dev->driver->driver_features & DRIVER_GEM)
+ drm_gem_release(dev, file_priv);
+
mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n;
@@ -571,6 +574,10 @@
if (dev->driver->postclose)
dev->driver->postclose(dev, file_priv);
+
+ if (drm_core_check_feature(dev, DRIVER_PRIME))
+ drm_prime_destroy_file_private(&file_priv->prime);
+
kfree(file_priv);
/* ========================================================
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 0ef358e..83114b5 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -35,6 +35,7 @@
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/shmem_fs.h>
+#include <linux/dma-buf.h>
#include "drmP.h"
/** @file drm_gem.c
@@ -232,6 +233,10 @@
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);
+ if (obj->import_attach)
+ drm_prime_remove_imported_buf_handle(&filp->prime,
+ obj->import_attach->dmabuf);
+
if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, filp);
drm_gem_object_handle_unreference_unlocked(obj);
@@ -527,6 +532,10 @@
struct drm_gem_object *obj = ptr;
struct drm_device *dev = obj->dev;
+ if (obj->import_attach)
+ drm_prime_remove_imported_buf_handle(&file_priv->prime,
+ obj->import_attach->dmabuf);
+
if (dev->driver->gem_close_object)
dev->driver->gem_close_object(obj, file_priv);
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
new file mode 100644
index 0000000..1bdf2b5
--- /dev/null
+++ b/drivers/gpu/drm/drm_prime.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright © 2012 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Rob Clark <rob.clark@linaro.org>
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/dma-buf.h>
+#include "drmP.h"
+
+/*
+ * DMA-BUF/GEM Object references and lifetime overview:
+ *
+ * On the export the dma_buf holds a reference to the exporting GEM
+ * object. It takes this reference in handle_to_fd_ioctl, when it
+ * first calls .prime_export and stores the exporting GEM object in
+ * the dma_buf priv. This reference is released when the dma_buf
+ * object goes away in the driver .release function.
+ *
+ * On the import the importing GEM object holds a reference to the
+ * dma_buf (which in turn holds a ref to the exporting GEM object).
+ * It takes that reference in the fd_to_handle ioctl.
+ * It calls dma_buf_get, creates an attachment to it and stores the
+ * attachment in the GEM object. When this attachment is destroyed
+ * when the imported object is destroyed, we remove the attachment
+ * and drop the reference to the dma_buf.
+ *
+ * Thus the chain of references always flows in one direction
+ * (avoiding loops): importing_gem -> dmabuf -> exporting_gem
+ *
+ * Self-importing: if userspace is using PRIME as a replacement for flink
+ * then it will get a fd->handle request for a GEM object that it created.
+ * Drivers should detect this situation and return back the gem object
+ * from the dma-buf private.
+ */
+
+struct drm_prime_member {
+ struct list_head entry;
+ struct dma_buf *dma_buf;
+ uint32_t handle;
+};
+
+int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+ struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+ int *prime_fd)
+{
+ struct drm_gem_object *obj;
+ void *buf;
+
+ obj = drm_gem_object_lookup(dev, file_priv, handle);
+ if (!obj)
+ return -ENOENT;
+
+ mutex_lock(&file_priv->prime.lock);
+ /* re-export the original imported object */
+ if (obj->import_attach) {
+ get_dma_buf(obj->import_attach->dmabuf);
+ *prime_fd = dma_buf_fd(obj->import_attach->dmabuf, flags);
+ drm_gem_object_unreference_unlocked(obj);
+ mutex_unlock(&file_priv->prime.lock);
+ return 0;
+ }
+
+ if (obj->export_dma_buf) {
+ get_dma_buf(obj->export_dma_buf);
+ *prime_fd = dma_buf_fd(obj->export_dma_buf, flags);
+ drm_gem_object_unreference_unlocked(obj);
+ } else {
+ buf = dev->driver->gem_prime_export(dev, obj, flags);
+ if (IS_ERR(buf)) {
+ /* normally the created dma-buf takes ownership of the ref,
+ * but if that fails then drop the ref
+ */
+ drm_gem_object_unreference_unlocked(obj);
+ mutex_unlock(&file_priv->prime.lock);
+ return PTR_ERR(buf);
+ }
+ obj->export_dma_buf = buf;
+ *prime_fd = dma_buf_fd(buf, flags);
+ }
+ mutex_unlock(&file_priv->prime.lock);
+ return 0;
+}
+EXPORT_SYMBOL(drm_gem_prime_handle_to_fd);
+
+int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+ struct drm_file *file_priv, int prime_fd, uint32_t *handle)
+{
+ struct dma_buf *dma_buf;
+ struct drm_gem_object *obj;
+ int ret;
+
+ dma_buf = dma_buf_get(prime_fd);
+ if (IS_ERR(dma_buf))
+ return PTR_ERR(dma_buf);
+
+ mutex_lock(&file_priv->prime.lock);
+
+ ret = drm_prime_lookup_imported_buf_handle(&file_priv->prime,
+ dma_buf, handle);
+ if (!ret) {
+ ret = 0;
+ goto out_put;
+ }
+
+ /* never seen this one, need to import */
+ obj = dev->driver->gem_prime_import(dev, dma_buf);
+ if (IS_ERR(obj)) {
+ ret = PTR_ERR(obj);
+ goto out_put;
+ }
+
+ ret = drm_gem_handle_create(file_priv, obj, handle);
+ drm_gem_object_unreference_unlocked(obj);
+ if (ret)
+ goto out_put;
+
+ ret = drm_prime_add_imported_buf_handle(&file_priv->prime,
+ dma_buf, *handle);
+ if (ret)
+ goto fail;
+
+ mutex_unlock(&file_priv->prime.lock);
+ return 0;
+
+fail:
+ /* hmm, if driver attached, we are relying on the free-object path
+ * to detach.. which seems ok..
+ */
+ drm_gem_object_handle_unreference_unlocked(obj);
+out_put:
+ dma_buf_put(dma_buf);
+ mutex_unlock(&file_priv->prime.lock);
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_prime_fd_to_handle);
+
+int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_prime_handle *args = data;
+ uint32_t flags;
+
+ if (!drm_core_check_feature(dev, DRIVER_PRIME))
+ return -EINVAL;
+
+ if (!dev->driver->prime_handle_to_fd)
+ return -ENOSYS;
+
+ /* check flags are valid */
+ if (args->flags & ~DRM_CLOEXEC)
+ return -EINVAL;
+
+ /* we only want to pass DRM_CLOEXEC which is == O_CLOEXEC */
+ flags = args->flags & DRM_CLOEXEC;
+
+ return dev->driver->prime_handle_to_fd(dev, file_priv,
+ args->handle, flags, &args->fd);
+}
+
+int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_prime_handle *args = data;
+
+ if (!drm_core_check_feature(dev, DRIVER_PRIME))
+ return -EINVAL;
+
+ if (!dev->driver->prime_fd_to_handle)
+ return -ENOSYS;
+
+ return dev->driver->prime_fd_to_handle(dev, file_priv,
+ args->fd, &args->handle);
+}
+
+/*
+ * drm_prime_pages_to_sg
+ *
+ * this helper creates an sg table object from a set of pages
+ * the driver is responsible for mapping the pages into the
+ * importers address space
+ */
+struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
+{
+ struct sg_table *sg = NULL;
+ struct scatterlist *iter;
+ int i;
+ int ret;
+
+ sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!sg)
+ goto out;
+
+ ret = sg_alloc_table(sg, nr_pages, GFP_KERNEL);
+ if (ret)
+ goto out;
+
+ for_each_sg(sg->sgl, iter, nr_pages, i)
+ sg_set_page(iter, pages[i], PAGE_SIZE, 0);
+
+ return sg;
+out:
+ kfree(sg);
+ return NULL;
+}
+EXPORT_SYMBOL(drm_prime_pages_to_sg);
+
+/* helper function to cleanup a GEM/prime object */
+void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
+{
+ struct dma_buf_attachment *attach;
+ struct dma_buf *dma_buf;
+ attach = obj->import_attach;
+ if (sg)
+ dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
+ dma_buf = attach->dmabuf;
+ dma_buf_detach(attach->dmabuf, attach);
+ /* remove the reference */
+ dma_buf_put(dma_buf);
+}
+EXPORT_SYMBOL(drm_prime_gem_destroy);
+
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
+{
+ INIT_LIST_HEAD(&prime_fpriv->head);
+ mutex_init(&prime_fpriv->lock);
+}
+EXPORT_SYMBOL(drm_prime_init_file_private);
+
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
+{
+ struct drm_prime_member *member, *safe;
+ list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
+ list_del(&member->entry);
+ kfree(member);
+ }
+}
+EXPORT_SYMBOL(drm_prime_destroy_file_private);
+
+int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
+{
+ struct drm_prime_member *member;
+
+ member = kmalloc(sizeof(*member), GFP_KERNEL);
+ if (!member)
+ return -ENOMEM;
+
+ member->dma_buf = dma_buf;
+ member->handle = handle;
+ list_add(&member->entry, &prime_fpriv->head);
+ return 0;
+}
+EXPORT_SYMBOL(drm_prime_add_imported_buf_handle);
+
+int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
+{
+ struct drm_prime_member *member;
+
+ list_for_each_entry(member, &prime_fpriv->head, entry) {
+ if (member->dma_buf == dma_buf) {
+ *handle = member->handle;
+ return 0;
+ }
+ }
+ return -ENOENT;
+}
+EXPORT_SYMBOL(drm_prime_lookup_imported_buf_handle);
+
+void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
+{
+ struct drm_prime_member *member, *safe;
+
+ mutex_lock(&prime_fpriv->lock);
+ list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
+ if (member->dma_buf == dma_buf) {
+ list_del(&member->entry);
+ kfree(member);
+ }
+ }
+ mutex_unlock(&prime_fpriv->lock);
+}
+EXPORT_SYMBOL(drm_prime_remove_imported_buf_handle);
diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c
index c8c83da..37c9a52 100644
--- a/drivers/gpu/drm/drm_usb.c
+++ b/drivers/gpu/drm/drm_usb.c
@@ -1,6 +1,6 @@
#include "drmP.h"
#include <linux/usb.h>
-#include <linux/export.h>
+#include <linux/module.h>
int drm_get_usb_dev(struct usb_interface *interface,
const struct usb_device_id *id,
@@ -114,3 +114,7 @@
usb_deregister(udriver);
}
EXPORT_SYMBOL(drm_usb_exit);
+
+MODULE_AUTHOR("David Airlie");
+MODULE_DESCRIPTION("USB DRM support");
+MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c
index 4a3a5f7..de8d209 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_buf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c
@@ -34,14 +34,14 @@
static int lowlevel_buffer_allocate(struct drm_device *dev,
unsigned int flags, struct exynos_drm_gem_buf *buf)
{
- dma_addr_t start_addr, end_addr;
+ dma_addr_t start_addr;
unsigned int npages, page_size, i = 0;
struct scatterlist *sgl;
int ret = 0;
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (flags & EXYNOS_BO_NONCONTIG) {
+ if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n");
return -EINVAL;
}
@@ -52,13 +52,13 @@
}
if (buf->size >= SZ_1M) {
- npages = (buf->size >> SECTION_SHIFT) + 1;
+ npages = buf->size >> SECTION_SHIFT;
page_size = SECTION_SIZE;
} else if (buf->size >= SZ_64K) {
- npages = (buf->size >> 16) + 1;
+ npages = buf->size >> 16;
page_size = SZ_64K;
} else {
- npages = (buf->size >> PAGE_SHIFT) + 1;
+ npages = buf->size >> PAGE_SHIFT;
page_size = PAGE_SIZE;
}
@@ -76,26 +76,13 @@
return -ENOMEM;
}
- buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
- &buf->dma_addr, GFP_KERNEL);
- if (!buf->kvaddr) {
- DRM_ERROR("failed to allocate buffer.\n");
- ret = -ENOMEM;
- goto err1;
- }
-
- start_addr = buf->dma_addr;
- end_addr = buf->dma_addr + buf->size;
-
- buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
- if (!buf->pages) {
- DRM_ERROR("failed to allocate pages.\n");
- ret = -ENOMEM;
- goto err2;
- }
-
- start_addr = buf->dma_addr;
- end_addr = buf->dma_addr + buf->size;
+ buf->kvaddr = dma_alloc_writecombine(dev->dev, buf->size,
+ &buf->dma_addr, GFP_KERNEL);
+ if (!buf->kvaddr) {
+ DRM_ERROR("failed to allocate buffer.\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
buf->pages = kzalloc(sizeof(struct page) * npages, GFP_KERNEL);
if (!buf->pages) {
@@ -105,23 +92,17 @@
}
sgl = buf->sgt->sgl;
+ start_addr = buf->dma_addr;
while (i < npages) {
buf->pages[i] = phys_to_page(start_addr);
sg_set_page(sgl, buf->pages[i], page_size, 0);
sg_dma_address(sgl) = start_addr;
start_addr += page_size;
- if (end_addr - start_addr < page_size)
- break;
sgl = sg_next(sgl);
i++;
}
- buf->pages[i] = phys_to_page(start_addr);
-
- sgl = sg_next(sgl);
- sg_set_page(sgl, buf->pages[i+1], end_addr - start_addr, 0);
-
DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
(unsigned long)buf->kvaddr,
(unsigned long)buf->dma_addr,
@@ -150,7 +131,7 @@
* non-continuous memory would be released by exynos
* gem framework.
*/
- if (flags & EXYNOS_BO_NONCONTIG) {
+ if (IS_NONCONTIG_BUFFER(flags)) {
DRM_DEBUG_KMS("not support allocation type.\n");
return;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_core.c b/drivers/gpu/drm/exynos/exynos_drm_core.c
index 411832e..eaf630d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_core.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_core.c
@@ -54,16 +54,18 @@
*
* P.S. note that this driver is considered for modularization.
*/
- ret = subdrv->probe(dev, subdrv->manager.dev);
+ ret = subdrv->probe(dev, subdrv->dev);
if (ret)
return ret;
}
- if (subdrv->is_local)
+ if (!subdrv->manager)
return 0;
+ subdrv->manager->dev = subdrv->dev;
+
/* create and initialize a encoder for this sub driver. */
- encoder = exynos_drm_encoder_create(dev, &subdrv->manager,
+ encoder = exynos_drm_encoder_create(dev, subdrv->manager,
(1 << MAX_CRTC) - 1);
if (!encoder) {
DRM_ERROR("failed to create encoder\n");
@@ -186,7 +188,7 @@
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
if (subdrv->open) {
- ret = subdrv->open(dev, subdrv->manager.dev, file);
+ ret = subdrv->open(dev, subdrv->dev, file);
if (ret)
goto err;
}
@@ -197,7 +199,7 @@
err:
list_for_each_entry_reverse(subdrv, &subdrv->list, list) {
if (subdrv->close)
- subdrv->close(dev, subdrv->manager.dev, file);
+ subdrv->close(dev, subdrv->dev, file);
}
return ret;
}
@@ -209,7 +211,7 @@
list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) {
if (subdrv->close)
- subdrv->close(dev, subdrv->manager.dev, file);
+ subdrv->close(dev, subdrv->dev, file);
}
}
EXPORT_SYMBOL_GPL(exynos_drm_subdrv_close);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index fbd0a23..1d81417 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -225,24 +225,25 @@
* Exynos drm sub driver structure.
*
* @list: sub driver has its own list object to register to exynos drm driver.
+ * @dev: pointer to device object for subdrv device driver.
* @drm_dev: pointer to drm_device and this pointer would be set
* when sub driver calls exynos_drm_subdrv_register().
- * @is_local: appear encoder and connector disrelated device.
+ * @manager: subdrv has its own manager to control a hardware appropriately
+ * and we can access a hardware drawing on this manager.
* @probe: this callback would be called by exynos drm driver after
* subdrv is registered to it.
* @remove: this callback is used to release resources created
* by probe callback.
* @open: this would be called with drm device file open.
* @close: this would be called with drm device file close.
- * @manager: subdrv has its own manager to control a hardware appropriately
- * and we can access a hardware drawing on this manager.
* @encoder: encoder object owned by this sub driver.
* @connector: connector object owned by this sub driver.
*/
struct exynos_drm_subdrv {
struct list_head list;
+ struct device *dev;
struct drm_device *drm_dev;
- bool is_local;
+ struct exynos_drm_manager *manager;
int (*probe)(struct drm_device *drm_dev, struct device *dev);
void (*remove)(struct drm_device *dev);
@@ -251,7 +252,6 @@
void (*close)(struct drm_device *drm_dev, struct device *dev,
struct drm_file *file);
- struct exynos_drm_manager manager;
struct drm_encoder *encoder;
struct drm_connector *connector;
};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index ecb6db2..29fdbfe 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -172,7 +172,7 @@
static void fimd_apply(struct device *subdrv_dev)
{
struct fimd_context *ctx = get_fimd_context(subdrv_dev);
- struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
+ struct exynos_drm_manager *mgr = ctx->subdrv.manager;
struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
struct fimd_win_data *win_data;
@@ -577,6 +577,13 @@
.disable = fimd_win_disable,
};
+static struct exynos_drm_manager fimd_manager = {
+ .pipe = -1,
+ .ops = &fimd_manager_ops,
+ .overlay_ops = &fimd_overlay_ops,
+ .display_ops = &fimd_display_ops,
+};
+
static void fimd_finish_pageflip(struct drm_device *drm_dev, int crtc)
{
struct exynos_drm_private *dev_priv = drm_dev->dev_private;
@@ -628,7 +635,7 @@
struct fimd_context *ctx = (struct fimd_context *)dev_id;
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
struct drm_device *drm_dev = subdrv->drm_dev;
- struct exynos_drm_manager *manager = &subdrv->manager;
+ struct exynos_drm_manager *manager = subdrv->manager;
u32 val;
val = readl(ctx->regs + VIDINTCON1);
@@ -744,7 +751,7 @@
static int fimd_power_on(struct fimd_context *ctx, bool enable)
{
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct device *dev = subdrv->manager.dev;
+ struct device *dev = subdrv->dev;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -867,13 +874,10 @@
subdrv = &ctx->subdrv;
+ subdrv->dev = dev;
+ subdrv->manager = &fimd_manager;
subdrv->probe = fimd_subdrv_probe;
subdrv->remove = fimd_subdrv_remove;
- subdrv->manager.pipe = -1;
- subdrv->manager.ops = &fimd_manager_ops;
- subdrv->manager.overlay_ops = &fimd_overlay_ops;
- subdrv->manager.display_ops = &fimd_display_ops;
- subdrv->manager.dev = dev;
mutex_init(&ctx->lock);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index fa1aa94..1dffa83 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -56,9 +56,28 @@
return out_msg;
}
-static unsigned int mask_gem_flags(unsigned int flags)
+static int check_gem_flags(unsigned int flags)
{
- return flags &= EXYNOS_BO_NONCONTIG;
+ if (flags & ~(EXYNOS_BO_MASK)) {
+ DRM_ERROR("invalid flags.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned long roundup_gem_size(unsigned long size, unsigned int flags)
+{
+ if (!IS_NONCONTIG_BUFFER(flags)) {
+ if (size >= SZ_1M)
+ return roundup(size, SECTION_SIZE);
+ else if (size >= SZ_64K)
+ return roundup(size, SZ_64K);
+ else
+ goto out;
+ }
+out:
+ return roundup(size, PAGE_SIZE);
}
static struct page **exynos_gem_get_pages(struct drm_gem_object *obj,
@@ -130,22 +149,12 @@
unsigned long pfn;
if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- unsigned long usize = buf->size;
-
if (!buf->pages)
return -EINTR;
- while (usize > 0) {
- pfn = page_to_pfn(buf->pages[page_offset++]);
- vm_insert_mixed(vma, f_vaddr, pfn);
- f_vaddr += PAGE_SIZE;
- usize -= PAGE_SIZE;
- }
-
- return 0;
- }
-
- pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
+ pfn = page_to_pfn(buf->pages[page_offset++]);
+ } else
+ pfn = (buf->dma_addr >> PAGE_SHIFT) + page_offset;
return vm_insert_mixed(vma, f_vaddr, pfn);
}
@@ -319,10 +328,17 @@
struct exynos_drm_gem_buf *buf;
int ret;
- size = roundup(size, PAGE_SIZE);
- DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+ if (!size) {
+ DRM_ERROR("invalid size.\n");
+ return ERR_PTR(-EINVAL);
+ }
- flags = mask_gem_flags(flags);
+ size = roundup_gem_size(size, flags);
+ DRM_DEBUG_KMS("%s\n", __FILE__);
+
+ ret = check_gem_flags(flags);
+ if (ret)
+ return ERR_PTR(ret);
buf = exynos_drm_init_buf(dev, size);
if (!buf)
@@ -331,7 +347,7 @@
exynos_gem_obj = exynos_drm_gem_init(dev, size);
if (!exynos_gem_obj) {
ret = -ENOMEM;
- goto err;
+ goto err_fini_buf;
}
exynos_gem_obj->buffer = buf;
@@ -347,18 +363,19 @@
ret = exynos_drm_gem_get_pages(&exynos_gem_obj->base);
if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base);
- goto err;
+ goto err_fini_buf;
}
} else {
ret = exynos_drm_alloc_buf(dev, buf, flags);
if (ret < 0) {
drm_gem_object_release(&exynos_gem_obj->base);
- goto err;
+ goto err_fini_buf;
}
}
return exynos_gem_obj;
-err:
+
+err_fini_buf:
exynos_drm_fini_buf(dev, buf);
return ERR_PTR(ret);
}
@@ -497,6 +514,8 @@
if (!buffer->pages)
return -EINVAL;
+ vma->vm_flags |= VM_MIXEDMAP;
+
do {
ret = vm_insert_page(vma, uaddr, buffer->pages[i++]);
if (ret) {
@@ -554,10 +573,8 @@
obj->filp->f_op = &exynos_drm_gem_fops;
obj->filp->private_data = obj;
- down_write(¤t->mm->mmap_sem);
- addr = do_mmap(obj->filp, 0, args->size,
+ addr = vm_mmap(obj->filp, 0, args->size,
PROT_READ | PROT_WRITE, MAP_SHARED, 0);
- up_write(¤t->mm->mmap_sem);
drm_gem_object_unreference_unlocked(obj);
@@ -685,7 +702,6 @@
int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct drm_gem_object *obj = vma->vm_private_data;
- struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
struct drm_device *dev = obj->dev;
unsigned long f_vaddr;
pgoff_t page_offset;
@@ -697,21 +713,10 @@
mutex_lock(&dev->struct_mutex);
- /*
- * allocate all pages as desired size if user wants to allocate
- * physically non-continuous memory.
- */
- if (exynos_gem_obj->flags & EXYNOS_BO_NONCONTIG) {
- ret = exynos_drm_gem_get_pages(obj);
- if (ret < 0)
- goto err;
- }
-
ret = exynos_drm_gem_map_pages(obj, vma, f_vaddr, page_offset);
if (ret < 0)
DRM_ERROR("failed to map pages.\n");
-err:
mutex_unlock(&dev->struct_mutex);
return convert_to_vm_err_msg(ret);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h
index e40fbad..4ed8420 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h
@@ -29,6 +29,8 @@
#define to_exynos_gem_obj(x) container_of(x,\
struct exynos_drm_gem_obj, base)
+#define IS_NONCONTIG_BUFFER(f) (f & EXYNOS_BO_NONCONTIG)
+
/*
* exynos drm gem buffer structure.
*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 14eb26b..3424463 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -30,9 +30,8 @@
struct drm_hdmi_context, subdrv);
/* these callback points shoud be set by specific drivers. */
-static struct exynos_hdmi_display_ops *hdmi_display_ops;
-static struct exynos_hdmi_manager_ops *hdmi_manager_ops;
-static struct exynos_hdmi_overlay_ops *hdmi_overlay_ops;
+static struct exynos_hdmi_ops *hdmi_ops;
+static struct exynos_mixer_ops *mixer_ops;
struct drm_hdmi_context {
struct exynos_drm_subdrv subdrv;
@@ -40,31 +39,20 @@
struct exynos_drm_hdmi_context *mixer_ctx;
};
-void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
- *display_ops)
+void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
{
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (display_ops)
- hdmi_display_ops = display_ops;
+ if (ops)
+ hdmi_ops = ops;
}
-void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
- *manager_ops)
+void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
{
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (manager_ops)
- hdmi_manager_ops = manager_ops;
-}
-
-void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops
- *overlay_ops)
-{
- DRM_DEBUG_KMS("%s\n", __FILE__);
-
- if (overlay_ops)
- hdmi_overlay_ops = overlay_ops;
+ if (ops)
+ mixer_ops = ops;
}
static bool drm_hdmi_is_connected(struct device *dev)
@@ -73,8 +61,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_display_ops && hdmi_display_ops->is_connected)
- return hdmi_display_ops->is_connected(ctx->hdmi_ctx->ctx);
+ if (hdmi_ops && hdmi_ops->is_connected)
+ return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
return false;
}
@@ -86,9 +74,9 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_display_ops && hdmi_display_ops->get_edid)
- return hdmi_display_ops->get_edid(ctx->hdmi_ctx->ctx,
- connector, edid, len);
+ if (hdmi_ops && hdmi_ops->get_edid)
+ return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
+ len);
return 0;
}
@@ -99,9 +87,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_display_ops && hdmi_display_ops->check_timing)
- return hdmi_display_ops->check_timing(ctx->hdmi_ctx->ctx,
- timing);
+ if (hdmi_ops && hdmi_ops->check_timing)
+ return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
return 0;
}
@@ -112,8 +99,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_display_ops && hdmi_display_ops->power_on)
- return hdmi_display_ops->power_on(ctx->hdmi_ctx->ctx, mode);
+ if (hdmi_ops && hdmi_ops->power_on)
+ return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
return 0;
}
@@ -130,13 +117,13 @@
{
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct exynos_drm_manager *manager = &subdrv->manager;
+ struct exynos_drm_manager *manager = subdrv->manager;
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_overlay_ops && hdmi_overlay_ops->enable_vblank)
- return hdmi_overlay_ops->enable_vblank(ctx->mixer_ctx->ctx,
- manager->pipe);
+ if (mixer_ops && mixer_ops->enable_vblank)
+ return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
+ manager->pipe);
return 0;
}
@@ -147,8 +134,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_overlay_ops && hdmi_overlay_ops->disable_vblank)
- return hdmi_overlay_ops->disable_vblank(ctx->mixer_ctx->ctx);
+ if (mixer_ops && mixer_ops->disable_vblank)
+ return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
}
static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
@@ -160,9 +147,9 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_manager_ops && hdmi_manager_ops->mode_fixup)
- hdmi_manager_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector,
- mode, adjusted_mode);
+ if (hdmi_ops && hdmi_ops->mode_fixup)
+ hdmi_ops->mode_fixup(ctx->hdmi_ctx->ctx, connector, mode,
+ adjusted_mode);
}
static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
@@ -171,8 +158,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_manager_ops && hdmi_manager_ops->mode_set)
- hdmi_manager_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
+ if (hdmi_ops && hdmi_ops->mode_set)
+ hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
}
static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
@@ -182,9 +169,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_manager_ops && hdmi_manager_ops->get_max_resol)
- hdmi_manager_ops->get_max_resol(ctx->hdmi_ctx->ctx, width,
- height);
+ if (hdmi_ops && hdmi_ops->get_max_resol)
+ hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
}
static void drm_hdmi_commit(struct device *subdrv_dev)
@@ -193,8 +179,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_manager_ops && hdmi_manager_ops->commit)
- hdmi_manager_ops->commit(ctx->hdmi_ctx->ctx);
+ if (hdmi_ops && hdmi_ops->commit)
+ hdmi_ops->commit(ctx->hdmi_ctx->ctx);
}
static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
@@ -209,8 +195,8 @@
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
- if (hdmi_manager_ops && hdmi_manager_ops->disable)
- hdmi_manager_ops->disable(ctx->hdmi_ctx->ctx);
+ if (hdmi_ops && hdmi_ops->disable)
+ hdmi_ops->disable(ctx->hdmi_ctx->ctx);
break;
default:
DRM_DEBUG_KMS("unkown dps mode: %d\n", mode);
@@ -235,8 +221,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_overlay_ops && hdmi_overlay_ops->win_mode_set)
- hdmi_overlay_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
+ if (mixer_ops && mixer_ops->win_mode_set)
+ mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
}
static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
@@ -245,8 +231,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_overlay_ops && hdmi_overlay_ops->win_commit)
- hdmi_overlay_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
+ if (mixer_ops && mixer_ops->win_commit)
+ mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos);
}
static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
@@ -255,8 +241,8 @@
DRM_DEBUG_KMS("%s\n", __FILE__);
- if (hdmi_overlay_ops && hdmi_overlay_ops->win_disable)
- hdmi_overlay_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
+ if (mixer_ops && mixer_ops->win_disable)
+ mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos);
}
static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
@@ -265,6 +251,12 @@
.disable = drm_mixer_disable,
};
+static struct exynos_drm_manager hdmi_manager = {
+ .pipe = -1,
+ .ops = &drm_hdmi_manager_ops,
+ .overlay_ops = &drm_hdmi_overlay_ops,
+ .display_ops = &drm_hdmi_display_ops,
+};
static int hdmi_subdrv_probe(struct drm_device *drm_dev,
struct device *dev)
@@ -332,12 +324,9 @@
subdrv = &ctx->subdrv;
+ subdrv->dev = dev;
+ subdrv->manager = &hdmi_manager;
subdrv->probe = hdmi_subdrv_probe;
- subdrv->manager.pipe = -1;
- subdrv->manager.ops = &drm_hdmi_manager_ops;
- subdrv->manager.overlay_ops = &drm_hdmi_overlay_ops;
- subdrv->manager.display_ops = &drm_hdmi_display_ops;
- subdrv->manager.dev = dev;
platform_set_drvdata(pdev, subdrv);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 44497cf..f3ae192 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -38,15 +38,15 @@
void *ctx;
};
-struct exynos_hdmi_display_ops {
+struct exynos_hdmi_ops {
+ /* display */
bool (*is_connected)(void *ctx);
int (*get_edid)(void *ctx, struct drm_connector *connector,
u8 *edid, int len);
int (*check_timing)(void *ctx, void *timing);
int (*power_on)(void *ctx, int mode);
-};
-struct exynos_hdmi_manager_ops {
+ /* manager */
void (*mode_fixup)(void *ctx, struct drm_connector *connector,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
@@ -57,22 +57,17 @@
void (*disable)(void *ctx);
};
-struct exynos_hdmi_overlay_ops {
+struct exynos_mixer_ops {
+ /* manager */
int (*enable_vblank)(void *ctx, int pipe);
void (*disable_vblank)(void *ctx);
+
+ /* overlay */
void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
void (*win_commit)(void *ctx, int zpos);
void (*win_disable)(void *ctx, int zpos);
};
-extern struct platform_driver hdmi_driver;
-extern struct platform_driver mixer_driver;
-
-void exynos_drm_display_ops_register(struct exynos_hdmi_display_ops
- *display_ops);
-void exynos_drm_manager_ops_register(struct exynos_hdmi_manager_ops
- *manager_ops);
-void exynos_drm_overlay_ops_register(struct exynos_hdmi_overlay_ops
- *overlay_ops);
-
+void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops);
+void exynos_mixer_ops_register(struct exynos_mixer_ops *ops);
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index c277a3a..f92fe4c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -24,6 +24,10 @@
static const uint32_t formats[] = {
DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV12M,
+ DRM_FORMAT_NV12MT,
};
static int
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 8e1339f..7b9c153 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -199,7 +199,7 @@
static void vidi_apply(struct device *subdrv_dev)
{
struct vidi_context *ctx = get_vidi_context(subdrv_dev);
- struct exynos_drm_manager *mgr = &ctx->subdrv.manager;
+ struct exynos_drm_manager *mgr = ctx->subdrv.manager;
struct exynos_drm_manager_ops *mgr_ops = mgr->ops;
struct exynos_drm_overlay_ops *ovl_ops = mgr->overlay_ops;
struct vidi_win_data *win_data;
@@ -374,6 +374,13 @@
.disable = vidi_win_disable,
};
+static struct exynos_drm_manager vidi_manager = {
+ .pipe = -1,
+ .ops = &vidi_manager_ops,
+ .overlay_ops = &vidi_overlay_ops,
+ .display_ops = &vidi_display_ops,
+};
+
static void vidi_finish_pageflip(struct drm_device *drm_dev, int crtc)
{
struct exynos_drm_private *dev_priv = drm_dev->dev_private;
@@ -425,7 +432,7 @@
struct vidi_context *ctx = container_of(work, struct vidi_context,
work);
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct exynos_drm_manager *manager = &subdrv->manager;
+ struct exynos_drm_manager *manager = subdrv->manager;
if (manager->pipe < 0)
return;
@@ -471,7 +478,7 @@
static int vidi_power_on(struct vidi_context *ctx, bool enable)
{
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
- struct device *dev = subdrv->manager.dev;
+ struct device *dev = subdrv->dev;
DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -611,13 +618,10 @@
ctx->raw_edid = (struct edid *)fake_edid_info;
subdrv = &ctx->subdrv;
+ subdrv->dev = dev;
+ subdrv->manager = &vidi_manager;
subdrv->probe = vidi_subdrv_probe;
subdrv->remove = vidi_subdrv_remove;
- subdrv->manager.pipe = -1;
- subdrv->manager.ops = &vidi_manager_ops;
- subdrv->manager.overlay_ops = &vidi_overlay_ops;
- subdrv->manager.display_ops = &vidi_display_ops;
- subdrv->manager.dev = dev;
mutex_init(&ctx->lock);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 575a8cb..b003538 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -40,7 +40,6 @@
#include "exynos_hdmi.h"
-#define HDMI_OVERLAY_NUMBER 3
#define MAX_WIDTH 1920
#define MAX_HEIGHT 1080
#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
@@ -1194,7 +1193,7 @@
static bool hdmi_is_connected(void *ctx)
{
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
if (val)
@@ -1207,7 +1206,7 @@
u8 *edid, int len)
{
struct edid *raw_edid;
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1275,7 +1274,7 @@
static int hdmi_check_timing(void *ctx, void *timing)
{
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
struct fb_videomode *check_timing = timing;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1312,13 +1311,6 @@
return 0;
}
-static struct exynos_hdmi_display_ops display_ops = {
- .is_connected = hdmi_is_connected,
- .get_edid = hdmi_get_edid,
- .check_timing = hdmi_check_timing,
- .power_on = hdmi_display_power_on,
-};
-
static void hdmi_set_acr(u32 freq, u8 *acr)
{
u32 n, cts;
@@ -1914,7 +1906,7 @@
struct drm_display_mode *adjusted_mode)
{
struct drm_display_mode *m;
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
int index;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1951,7 +1943,7 @@
static void hdmi_mode_set(void *ctx, void *mode)
{
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
int conf_idx;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1974,7 +1966,7 @@
static void hdmi_commit(void *ctx)
{
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1985,7 +1977,7 @@
static void hdmi_disable(void *ctx)
{
- struct hdmi_context *hdata = (struct hdmi_context *)ctx;
+ struct hdmi_context *hdata = ctx;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
@@ -1996,7 +1988,14 @@
}
}
-static struct exynos_hdmi_manager_ops manager_ops = {
+static struct exynos_hdmi_ops hdmi_ops = {
+ /* display */
+ .is_connected = hdmi_is_connected,
+ .get_edid = hdmi_get_edid,
+ .check_timing = hdmi_check_timing,
+ .power_on = hdmi_display_power_on,
+
+ /* manager */
.mode_fixup = hdmi_mode_fixup,
.mode_set = hdmi_mode_set,
.get_max_resol = hdmi_get_max_resol,
@@ -2020,7 +2019,7 @@
static irqreturn_t hdmi_irq_handler(int irq, void *arg)
{
struct exynos_drm_hdmi_context *ctx = arg;
- struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
+ struct hdmi_context *hdata = ctx->ctx;
u32 intc_flag;
intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
@@ -2173,7 +2172,7 @@
DRM_DEBUG_KMS("%s\n", __func__);
- hdmi_resource_poweroff((struct hdmi_context *)ctx->ctx);
+ hdmi_resource_poweroff(ctx->ctx);
return 0;
}
@@ -2184,7 +2183,7 @@
DRM_DEBUG_KMS("%s\n", __func__);
- hdmi_resource_poweron((struct hdmi_context *)ctx->ctx);
+ hdmi_resource_poweron(ctx->ctx);
return 0;
}
@@ -2322,8 +2321,7 @@
hdata->irq = res->start;
/* register specific callbacks to common hdmi. */
- exynos_drm_display_ops_register(&display_ops);
- exynos_drm_manager_ops_register(&manager_ops);
+ exynos_hdmi_ops_register(&hdmi_ops);
hdmi_resource_poweron(hdata);
@@ -2351,7 +2349,7 @@
static int __devexit hdmi_remove(struct platform_device *pdev)
{
struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
- struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
+ struct hdmi_context *hdata = ctx->ctx;
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 4d5f41e..e15438c 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -37,7 +37,8 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_hdmi.h"
-#define HDMI_OVERLAY_NUMBER 3
+#define MIXER_WIN_NR 3
+#define MIXER_DEFAULT_WIN 0
#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
@@ -75,16 +76,12 @@
};
struct mixer_context {
- struct fb_videomode *default_timing;
- unsigned int default_win;
- unsigned int default_bpp;
unsigned int irq;
int pipe;
bool interlace;
- bool vp_enabled;
struct mixer_resources mixer_res;
- struct hdmi_win_data win_data[HDMI_OVERLAY_NUMBER];
+ struct hdmi_win_data win_data[MIXER_WIN_NR];
};
static const u8 filter_y_horiz_tap8[] = {
@@ -643,9 +640,9 @@
win = overlay->zpos;
if (win == DEFAULT_ZPOS)
- win = mixer_ctx->default_win;
+ win = MIXER_DEFAULT_WIN;
- if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+ if (win < 0 || win > MIXER_WIN_NR) {
DRM_ERROR("overlay plane[%d] is wrong\n", win);
return;
}
@@ -683,9 +680,9 @@
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
if (win == DEFAULT_ZPOS)
- win = mixer_ctx->default_win;
+ win = MIXER_DEFAULT_WIN;
- if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+ if (win < 0 || win > MIXER_WIN_NR) {
DRM_ERROR("overlay plane[%d] is wrong\n", win);
return;
}
@@ -706,9 +703,9 @@
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
if (win == DEFAULT_ZPOS)
- win = mixer_ctx->default_win;
+ win = MIXER_DEFAULT_WIN;
- if (win < 0 || win > HDMI_OVERLAY_NUMBER) {
+ if (win < 0 || win > MIXER_WIN_NR) {
DRM_ERROR("overlay plane[%d] is wrong\n", win);
return;
}
@@ -722,9 +719,12 @@
spin_unlock_irqrestore(&res->reg_slock, flags);
}
-static struct exynos_hdmi_overlay_ops overlay_ops = {
+static struct exynos_mixer_ops mixer_ops = {
+ /* manager */
.enable_vblank = mixer_enable_vblank,
.disable_vblank = mixer_disable_vblank,
+
+ /* overlay */
.win_mode_set = mixer_win_mode_set,
.win_commit = mixer_win_commit,
.win_disable = mixer_win_disable,
@@ -771,8 +771,7 @@
static irqreturn_t mixer_irq_handler(int irq, void *arg)
{
struct exynos_drm_hdmi_context *drm_hdmi_ctx = arg;
- struct mixer_context *ctx =
- (struct mixer_context *)drm_hdmi_ctx->ctx;
+ struct mixer_context *ctx = drm_hdmi_ctx->ctx;
struct mixer_resources *res = &ctx->mixer_res;
u32 val, val_base;
@@ -902,7 +901,7 @@
DRM_DEBUG_KMS("resume - start\n");
- mixer_resource_poweron((struct mixer_context *)ctx->ctx);
+ mixer_resource_poweron(ctx->ctx);
return 0;
}
@@ -913,7 +912,7 @@
DRM_DEBUG_KMS("suspend - start\n");
- mixer_resource_poweroff((struct mixer_context *)ctx->ctx);
+ mixer_resource_poweroff(ctx->ctx);
return 0;
}
@@ -926,8 +925,7 @@
static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
struct platform_device *pdev)
{
- struct mixer_context *mixer_ctx =
- (struct mixer_context *)ctx->ctx;
+ struct mixer_context *mixer_ctx = ctx->ctx;
struct device *dev = &pdev->dev;
struct mixer_resources *mixer_res = &mixer_ctx->mixer_res;
struct resource *res;
@@ -1076,7 +1074,7 @@
goto fail;
/* register specific callback point to common hdmi. */
- exynos_drm_overlay_ops_register(&overlay_ops);
+ exynos_mixer_ops_register(&mixer_ops);
mixer_resource_poweron(ctx);
@@ -1093,7 +1091,7 @@
struct device *dev = &pdev->dev;
struct exynos_drm_hdmi_context *drm_hdmi_ctx =
platform_get_drvdata(pdev);
- struct mixer_context *ctx = (struct mixer_context *)drm_hdmi_ctx->ctx;
+ struct mixer_context *ctx = drm_hdmi_ctx->ctx;
dev_info(dev, "remove successful\n");
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
index 21071ce..36eb074 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.h
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
@@ -29,7 +29,6 @@
#define __MDFLD_DSI_OUTPUT_H__
#include <linux/backlight.h>
-#include <linux/version.h>
#include <drm/drmP.h>
#include <drm/drm.h>
#include <drm/drm_crtc.h>
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index 2c8a60c..f920fb5 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -129,6 +129,7 @@
if (buf_priv->currently_mapped == I810_BUF_MAPPED)
return -EINVAL;
+ /* This is all entirely broken */
down_write(¤t->mm->mmap_sem);
old_fops = file_priv->filp->f_op;
file_priv->filp->f_op = &i810_buffer_fops;
@@ -157,11 +158,8 @@
if (buf_priv->currently_mapped != I810_BUF_MAPPED)
return -EINVAL;
- down_write(¤t->mm->mmap_sem);
- retcode = do_munmap(current->mm,
- (unsigned long)buf_priv->virtual,
+ retcode = vm_munmap((unsigned long)buf_priv->virtual,
(size_t) buf->total);
- up_write(¤t->mm->mmap_sem);
buf_priv->currently_mapped = I810_BUF_UNMAPPED;
buf_priv->virtual = NULL;
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index fdb7cce..e6162a1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1224,6 +1224,9 @@
unsigned long temp, chipset, gfx;
int ret;
+ if (!IS_GEN5(dev))
+ return -ENODEV;
+
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
@@ -1502,14 +1505,6 @@
return 0;
}
-static int
-i915_debugfs_common_open(struct inode *inode,
- struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t
i915_wedged_read(struct file *filp,
char __user *ubuf,
@@ -1560,7 +1555,7 @@
static const struct file_operations i915_wedged_fops = {
.owner = THIS_MODULE,
- .open = i915_debugfs_common_open,
+ .open = simple_open,
.read = i915_wedged_read,
.write = i915_wedged_write,
.llseek = default_llseek,
@@ -1622,7 +1617,7 @@
static const struct file_operations i915_max_freq_fops = {
.owner = THIS_MODULE,
- .open = i915_debugfs_common_open,
+ .open = simple_open,
.read = i915_max_freq_read,
.write = i915_max_freq_write,
.llseek = default_llseek,
@@ -1693,7 +1688,7 @@
static const struct file_operations i915_cache_sharing_fops = {
.owner = THIS_MODULE,
- .open = i915_debugfs_common_open,
+ .open = simple_open,
.read = i915_cache_sharing_read,
.write = i915_cache_sharing_write,
.llseek = default_llseek,
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 9341eb8..ba60f3c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1183,6 +1183,21 @@
return can_switch;
}
+static bool
+intel_enable_ppgtt(struct drm_device *dev)
+{
+ if (i915_enable_ppgtt >= 0)
+ return i915_enable_ppgtt;
+
+#ifdef CONFIG_INTEL_IOMMU
+ /* Disable ppgtt on SNB if VT-d is on. */
+ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
+ return false;
+#endif
+
+ return true;
+}
+
static int i915_load_gem_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1197,7 +1212,7 @@
drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
mutex_lock(&dev->struct_mutex);
- if (i915_enable_ppgtt && HAS_ALIASING_PPGTT(dev)) {
+ if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
/* PPGTT pdes are stolen from global gtt ptes, so shrink the
* aperture accordingly when using aliasing ppgtt. */
gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
@@ -1207,8 +1222,10 @@
i915_gem_do_init(dev, 0, mappable_size, gtt_size);
ret = i915_gem_init_aliasing_ppgtt(dev);
- if (ret)
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
return ret;
+ }
} else {
/* Let GEM Manage all of the aperture.
*
@@ -1684,6 +1701,9 @@
unsigned long diffms;
u32 count;
+ if (dev_priv->info->gen != 5)
+ return;
+
getrawmonotonic(&now);
diff1 = timespec_sub(now, dev_priv->last_time2);
@@ -2104,12 +2124,14 @@
setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
(unsigned long) dev);
- spin_lock(&mchdev_lock);
- i915_mch_dev = dev_priv;
- dev_priv->mchdev_lock = &mchdev_lock;
- spin_unlock(&mchdev_lock);
+ if (IS_GEN5(dev)) {
+ spin_lock(&mchdev_lock);
+ i915_mch_dev = dev_priv;
+ dev_priv->mchdev_lock = &mchdev_lock;
+ spin_unlock(&mchdev_lock);
- ips_ping_for_i915_load();
+ ips_ping_for_i915_load();
+ }
return 0;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 1a7559b..ae8a64f 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -64,9 +64,13 @@
"Use semaphores for inter-ring sync (default: -1 (use per-chip defaults))");
int i915_enable_rc6 __read_mostly = -1;
-module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
+module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0400);
MODULE_PARM_DESC(i915_enable_rc6,
- "Enable power-saving render C-state 6 (default: -1 (use per-chip default)");
+ "Enable power-saving render C-state 6. "
+ "Different stages can be selected via bitmask values "
+ "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). "
+ "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
+ "default: -1 (use per-chip default)");
int i915_enable_fbc __read_mostly = -1;
module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
@@ -103,8 +107,8 @@
"WARNING: Disabling this can cause system wide hangs. "
"(default: true)");
-bool i915_enable_ppgtt __read_mostly = 1;
-module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, bool, 0600);
+int i915_enable_ppgtt __read_mostly = -1;
+module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
MODULE_PARM_DESC(i915_enable_ppgtt,
"Enable PPGTT (default: true)");
@@ -292,6 +296,7 @@
INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */
INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */
INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */
+ INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */
{0, 0, 0}
};
@@ -533,7 +538,9 @@
drm_irq_install(dev);
/* Resume the modeset for every activated CRTC */
+ mutex_lock(&dev->mode_config.mutex);
drm_helper_resume_force_mode(dev);
+ mutex_unlock(&dev->mode_config.mutex);
if (IS_IRONLAKE_M(dev))
ironlake_enable_rc6(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c0f19f57..5fabc6c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1053,6 +1053,27 @@
#include "i915_trace.h"
+/**
+ * RC6 is a special power stage which allows the GPU to enter an very
+ * low-voltage mode when idle, using down to 0V while at this stage. This
+ * stage is entered automatically when the GPU is idle when RC6 support is
+ * enabled, and as soon as new workload arises GPU wakes up automatically as well.
+ *
+ * There are different RC6 modes available in Intel GPU, which differentiate
+ * among each other with the latency required to enter and leave RC6 and
+ * voltage consumed by the GPU in different states.
+ *
+ * The combination of the following flags define which states GPU is allowed
+ * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and
+ * RC6pp is deepest RC6. Their support by hardware varies according to the
+ * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one
+ * which brings the most power savings; deeper states save more power, but
+ * require higher latency to switch to and wake up.
+ */
+#define INTEL_RC6_ENABLE (1<<0)
+#define INTEL_RC6p_ENABLE (1<<1)
+#define INTEL_RC6pp_ENABLE (1<<2)
+
extern struct drm_ioctl_desc i915_ioctls[];
extern int i915_max_ioctl;
extern unsigned int i915_fbpercrtc __always_unused;
@@ -1065,7 +1086,7 @@
extern int i915_enable_rc6 __read_mostly;
extern int i915_enable_fbc __read_mostly;
extern bool i915_enable_hangcheck __read_mostly;
-extern bool i915_enable_ppgtt __read_mostly;
+extern int i915_enable_ppgtt __read_mostly;
extern int i915_suspend(struct drm_device *dev, pm_message_t state);
extern int i915_resume(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1f441f5..0d1e4b7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1087,11 +1087,9 @@
if (obj == NULL)
return -ENOENT;
- down_write(¤t->mm->mmap_sem);
- addr = do_mmap(obj->filp, 0, args->size,
+ addr = vm_mmap(obj->filp, 0, args->size,
PROT_READ | PROT_WRITE, MAP_SHARED,
args->offset);
- up_write(¤t->mm->mmap_sem);
drm_gem_object_unreference_unlocked(obj);
if (IS_ERR((void *)addr))
return addr;
@@ -1472,16 +1470,19 @@
list_move_tail(&obj->ring_list, &ring->active_list);
obj->last_rendering_seqno = seqno;
+
if (obj->fenced_gpu_access) {
- struct drm_i915_fence_reg *reg;
-
- BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE);
-
obj->last_fenced_seqno = seqno;
obj->last_fenced_ring = ring;
- reg = &dev_priv->fence_regs[obj->fence_reg];
- list_move_tail(®->lru_list, &dev_priv->mm.fence_list);
+ /* Bump MRU to take account of the delayed flush */
+ if (obj->fence_reg != I915_FENCE_REG_NONE) {
+ struct drm_i915_fence_reg *reg;
+
+ reg = &dev_priv->fence_regs[obj->fence_reg];
+ list_move_tail(®->lru_list,
+ &dev_priv->mm.fence_list);
+ }
}
}
@@ -1490,6 +1491,7 @@
{
list_del_init(&obj->ring_list);
obj->last_rendering_seqno = 0;
+ obj->last_fenced_seqno = 0;
}
static void
@@ -1518,6 +1520,7 @@
BUG_ON(!list_empty(&obj->gpu_write_list));
BUG_ON(!obj->active);
obj->ring = NULL;
+ obj->last_fenced_ring = NULL;
i915_gem_object_move_off_active(obj);
obj->fenced_gpu_access = false;
@@ -3754,12 +3757,32 @@
drm_i915_private_t *dev_priv = dev->dev_private;
uint32_t pd_offset;
struct intel_ring_buffer *ring;
+ struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
+ uint32_t __iomem *pd_addr;
+ uint32_t pd_entry;
int i;
if (!dev_priv->mm.aliasing_ppgtt)
return;
- pd_offset = dev_priv->mm.aliasing_ppgtt->pd_offset;
+
+ pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t);
+ for (i = 0; i < ppgtt->num_pd_entries; i++) {
+ dma_addr_t pt_addr;
+
+ if (dev_priv->mm.gtt->needs_dmar)
+ pt_addr = ppgtt->pt_dma_addr[i];
+ else
+ pt_addr = page_to_phys(ppgtt->pt_pages[i]);
+
+ pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
+ pd_entry |= GEN6_PDE_VALID;
+
+ writel(pd_entry, pd_addr + i);
+ }
+ readl(pd_addr);
+
+ pd_offset = ppgtt->pd_offset;
pd_offset /= 64; /* in cachelines, */
pd_offset <<= 16;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 81687af..de43194 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -498,8 +498,8 @@
if (ret)
goto err_unpin;
}
+ obj->pending_fenced_gpu_access = true;
}
- obj->pending_fenced_gpu_access = need_fence;
}
entry->offset = obj->gtt_offset;
@@ -1133,6 +1133,11 @@
return -EINVAL;
}
+ if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+ DRM_DEBUG("execbuf with %u cliprects\n",
+ args->num_cliprects);
+ return -EINVAL;
+ }
cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects),
GFP_KERNEL);
if (cliprects == NULL) {
@@ -1404,7 +1409,8 @@
struct drm_i915_gem_exec_object2 *exec2_list = NULL;
int ret;
- if (args->buffer_count < 1) {
+ if (args->buffer_count < 1 ||
+ args->buffer_count > UINT_MAX / sizeof(*exec2_list)) {
DRM_DEBUG("execbuf2 with %d buffers\n", args->buffer_count);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 2eacd78..a135c61 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -65,9 +65,7 @@
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_ppgtt *ppgtt;
- uint32_t pd_entry;
unsigned first_pd_entry_in_global_pt;
- uint32_t __iomem *pd_addr;
int i;
int ret = -ENOMEM;
@@ -100,7 +98,6 @@
goto err_pt_alloc;
}
- pd_addr = dev_priv->mm.gtt->gtt + first_pd_entry_in_global_pt;
for (i = 0; i < ppgtt->num_pd_entries; i++) {
dma_addr_t pt_addr;
if (dev_priv->mm.gtt->needs_dmar) {
@@ -117,13 +114,7 @@
ppgtt->pt_dma_addr[i] = pt_addr;
} else
pt_addr = page_to_phys(ppgtt->pt_pages[i]);
-
- pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
- pd_entry |= GEN6_PDE_VALID;
-
- writel(pd_entry, pd_addr + i);
}
- readl(pd_addr);
ppgtt->scratch_page_dma_addr = dev_priv->mm.gtt->scratch_page_dma;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 3886cf0..9d24d65 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -568,6 +568,7 @@
#define CM0_MASK_SHIFT 16
#define CM0_IZ_OPT_DISABLE (1<<6)
#define CM0_ZR_OPT_DISABLE (1<<5)
+#define CM0_STC_EVICT_DISABLE_LRA_SNB (1<<5)
#define CM0_DEPTH_EVICT_DISABLE (1<<4)
#define CM0_COLOR_EVICT_DISABLE (1<<3)
#define CM0_DEPTH_WRITE_DISABLE (1<<1)
@@ -2385,6 +2386,7 @@
#define PIPECONF_DISABLE 0
#define PIPECONF_DOUBLE_WIDE (1<<30)
#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPECONF_FRAME_START_DELAY_MASK (3<<27)
#define PIPECONF_SINGLE_WIDE 0
#define PIPECONF_PIPE_UNLOCKED 0
#define PIPECONF_PIPE_LOCKED (1<<25)
@@ -3727,6 +3729,9 @@
#define GT_FIFO_FREE_ENTRIES 0x120008
#define GT_FIFO_NUM_RESERVED_ENTRIES 20
+#define GEN6_UCGCTL1 0x9400
+# define GEN6_BLBUNIT_CLOCK_GATE_DISABLE (1 << 5)
+
#define GEN6_UCGCTL2 0x9404
# define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13)
# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12)
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 8168d8f..b48fc2a 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -24,6 +24,7 @@
* Eric Anholt <eric@anholt.net>
*
*/
+#include <linux/dmi.h>
#include <drm/drm_dp_helper.h>
#include "drmP.h"
#include "drm.h"
@@ -621,6 +622,26 @@
dev_priv->edp.bpp = 18;
}
+static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+ "VBIOS ROM for %s\n",
+ id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+ {
+ .callback = intel_no_opregion_vbt_callback,
+ .ident = "ThinkCentre A57",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+ },
+ },
+ { }
+};
+
/**
* intel_parse_bios - find VBT and initialize settings from the BIOS
* @dev: DRM device
@@ -641,7 +662,7 @@
init_vbt_defaults(dev_priv);
/* XXX Should this validation be moved to intel_opregion.c? */
- if (dev_priv->opregion.vbt) {
+ if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt;
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
DRM_DEBUG_KMS("Using VBT from OpRegion: %20s\n",
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 4d3d736..90b9793 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -430,8 +430,8 @@
{
struct drm_device *dev = connector->dev;
struct intel_crt *crt = intel_attached_crt(connector);
- struct drm_crtc *crtc;
enum drm_connector_status status;
+ struct intel_load_detect_pipe tmp;
if (I915_HAS_HOTPLUG(dev)) {
if (intel_crt_detect_hotplug(connector)) {
@@ -450,23 +450,16 @@
return connector->status;
/* for pre-945g platforms use load detect */
- crtc = crt->base.base.crtc;
- if (crtc && crtc->enabled) {
- status = intel_crt_load_detect(crt);
- } else {
- struct intel_load_detect_pipe tmp;
-
- if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
- &tmp)) {
- if (intel_crt_detect_ddc(connector))
- status = connector_status_connected;
- else
- status = intel_crt_load_detect(crt);
- intel_release_load_detect_pipe(&crt->base, connector,
- &tmp);
- } else
- status = connector_status_unknown;
- }
+ if (intel_get_load_detect_pipe(&crt->base, connector, NULL,
+ &tmp)) {
+ if (intel_crt_detect_ddc(connector))
+ status = connector_status_connected;
+ else
+ status = intel_crt_load_detect(crt);
+ intel_release_load_detect_pipe(&crt->base, connector,
+ &tmp);
+ } else
+ status = connector_status_unknown;
return status;
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d514719..1b1cf3b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2245,6 +2245,33 @@
}
static int
+intel_finish_fb(struct drm_framebuffer *old_fb)
+{
+ struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
+ struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+ bool was_interruptible = dev_priv->mm.interruptible;
+ int ret;
+
+ wait_event(dev_priv->pending_flip_queue,
+ atomic_read(&dev_priv->mm.wedged) ||
+ atomic_read(&obj->pending_flip) == 0);
+
+ /* Big Hammer, we also need to ensure that any pending
+ * MI_WAIT_FOR_EVENT inside a user batch buffer on the
+ * current scanout is retired before unpinning the old
+ * framebuffer.
+ *
+ * This should only fail upon a hung GPU, in which case we
+ * can safely continue.
+ */
+ dev_priv->mm.interruptible = false;
+ ret = i915_gem_object_finish_gpu(obj);
+ dev_priv->mm.interruptible = was_interruptible;
+
+ return ret;
+}
+
+static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
@@ -2282,25 +2309,8 @@
return ret;
}
- if (old_fb) {
- struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
-
- wait_event(dev_priv->pending_flip_queue,
- atomic_read(&dev_priv->mm.wedged) ||
- atomic_read(&obj->pending_flip) == 0);
-
- /* Big Hammer, we also need to ensure that any pending
- * MI_WAIT_FOR_EVENT inside a user batch buffer on the
- * current scanout is retired before unpinning the old
- * framebuffer.
- *
- * This should only fail upon a hung GPU, in which case we
- * can safely continue.
- */
- ret = i915_gem_object_finish_gpu(obj);
- (void) ret;
- }
+ if (old_fb)
+ intel_finish_fb(old_fb);
ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
LEAVE_ATOMIC_MODE_SET);
@@ -3371,6 +3381,23 @@
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
struct drm_device *dev = crtc->dev;
+ /* Flush any pending WAITs before we disable the pipe. Note that
+ * we need to drop the struct_mutex in order to acquire it again
+ * during the lowlevel dpms routines around a couple of the
+ * operations. It does not look trivial nor desirable to move
+ * that locking higher. So instead we leave a window for the
+ * submission of further commands on the fb before we can actually
+ * disable it. This race with userspace exists anyway, and we can
+ * only rely on the pipe being disabled by userspace after it
+ * receives the hotplug notification and has flushed any pending
+ * batches.
+ */
+ if (crtc->fb) {
+ mutex_lock(&dev->struct_mutex);
+ intel_finish_fb(crtc->fb);
+ mutex_unlock(&dev->struct_mutex);
+ }
+
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
@@ -3451,8 +3478,11 @@
return false;
}
- /* All interlaced capable intel hw wants timings in frames. */
- drm_mode_set_crtcinfo(adjusted_mode, 0);
+ /* All interlaced capable intel hw wants timings in frames. Note though
+ * that intel_lvds_mode_fixup does some funny tricks with the crtc
+ * timings, so we need to be careful not to clobber these.*/
+ if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET))
+ drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
@@ -5539,7 +5569,8 @@
if (intel_panel_use_ssc(dev_priv) && can_ssc) {
DRM_DEBUG_KMS("Using SSC on panel\n");
temp |= DREF_SSC1_ENABLE;
- }
+ } else
+ temp &= ~DREF_SSC1_ENABLE;
/* Get SSC going before enabling the outputs */
I915_WRITE(PCH_DREF_CONTROL, temp);
@@ -7041,9 +7072,6 @@
struct drm_device *dev = crtc->dev;
drm_i915_private_t *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- int pipe = intel_crtc->pipe;
- int dpll_reg = DPLL(pipe);
- int dpll = I915_READ(dpll_reg);
if (HAS_PCH_SPLIT(dev))
return;
@@ -7056,10 +7084,15 @@
* the manual case.
*/
if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {
+ int pipe = intel_crtc->pipe;
+ int dpll_reg = DPLL(pipe);
+ u32 dpll;
+
DRM_DEBUG_DRIVER("downclocking LVDS\n");
assert_panel_unlocked(dev_priv, pipe);
+ dpll = I915_READ(dpll_reg);
dpll |= DISPLAY_RATE_SELECT_FPA1;
I915_WRITE(dpll_reg, dpll);
intel_wait_for_vblank(dev, pipe);
@@ -7067,7 +7100,6 @@
if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");
}
-
}
/**
@@ -7437,7 +7469,13 @@
OUT_RING(fb->pitches[0] | obj->tiling_mode);
OUT_RING(obj->gtt_offset);
- pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+ /* Contrary to the suggestions in the documentation,
+ * "Enable Panel Fitter" does not seem to be required when page
+ * flipping with a non-native mode, and worse causes a normal
+ * modeset to fail.
+ * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE;
+ */
+ pf = 0;
pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;
OUT_RING(pf | pipesrc);
ADVANCE_LP_RING();
@@ -7580,6 +7618,12 @@
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;
+ /* Clear any frame start delays used for debugging left by the BIOS */
+ for_each_pipe(pipe) {
+ reg = PIPECONF(pipe);
+ I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+ }
+
if (HAS_PCH_SPLIT(dev))
return;
@@ -8215,7 +8259,7 @@
dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);
}
-static bool intel_enable_rc6(struct drm_device *dev)
+static int intel_enable_rc6(struct drm_device *dev)
{
/*
* Respect the kernel parameter if it is set
@@ -8233,11 +8277,11 @@
* Disable rc6 on Sandybridge
*/
if (INTEL_INFO(dev)->gen == 6) {
- DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n");
- return 0;
+ DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n");
+ return INTEL_RC6_ENABLE;
}
- DRM_DEBUG_DRIVER("RC6 enabled\n");
- return 1;
+ DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n");
+ return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
}
void gen6_enable_rps(struct drm_i915_private *dev_priv)
@@ -8247,6 +8291,7 @@
u32 pcu_mbox, rc6_mask = 0;
u32 gtfifodbg;
int cur_freq, min_freq, max_freq;
+ int rc6_mode;
int i;
/* Here begins a magic sequence of register writes to enable
@@ -8284,9 +8329,20 @@
I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);
I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */
- if (intel_enable_rc6(dev_priv->dev))
- rc6_mask = GEN6_RC_CTL_RC6_ENABLE |
- ((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0);
+ rc6_mode = intel_enable_rc6(dev_priv->dev);
+ if (rc6_mode & INTEL_RC6_ENABLE)
+ rc6_mask |= GEN6_RC_CTL_RC6_ENABLE;
+
+ if (rc6_mode & INTEL_RC6p_ENABLE)
+ rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE;
+
+ if (rc6_mode & INTEL_RC6pp_ENABLE)
+ rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE;
+
+ DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n",
+ (rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off",
+ (rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off",
+ (rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off");
I915_WRITE(GEN6_RC_CONTROL,
rc6_mask |
@@ -8510,6 +8566,10 @@
I915_WRITE(WM2_LP_ILK, 0);
I915_WRITE(WM1_LP_ILK, 0);
+ I915_WRITE(GEN6_UCGCTL1,
+ I915_READ(GEN6_UCGCTL1) |
+ GEN6_BLBUNIT_CLOCK_GATE_DISABLE);
+
/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
* gating disable must be set. Failure to set it results in
* flickering pixels due to Z write ordering failures after
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 110552f..4b63791 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -219,14 +219,38 @@
return (max_link_clock * max_lanes * 8) / 10;
}
+static bool
+intel_dp_adjust_dithering(struct intel_dp *intel_dp,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
+ int max_lanes = intel_dp_max_lane_count(intel_dp);
+ int max_rate, mode_rate;
+
+ mode_rate = intel_dp_link_required(mode->clock, 24);
+ max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
+
+ if (mode_rate > max_rate) {
+ mode_rate = intel_dp_link_required(mode->clock, 18);
+ if (mode_rate > max_rate)
+ return false;
+
+ if (adjusted_mode)
+ adjusted_mode->private_flags
+ |= INTEL_MODE_DP_FORCE_6BPC;
+
+ return true;
+ }
+
+ return true;
+}
+
static int
intel_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
- int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp));
- int max_lanes = intel_dp_max_lane_count(intel_dp);
- int max_rate, mode_rate;
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay)
@@ -236,16 +260,8 @@
return MODE_PANEL;
}
- mode_rate = intel_dp_link_required(mode->clock, 24);
- max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
-
- if (mode_rate > max_rate) {
- mode_rate = intel_dp_link_required(mode->clock, 18);
- if (mode_rate > max_rate)
- return MODE_CLOCK_HIGH;
- else
- mode->private_flags |= INTEL_MODE_DP_FORCE_6BPC;
- }
+ if (!intel_dp_adjust_dithering(intel_dp, mode, NULL))
+ return MODE_CLOCK_HIGH;
if (mode->clock < 10000)
return MODE_CLOCK_LOW;
@@ -672,7 +688,7 @@
int lane_count, clock;
int max_lane_count = intel_dp_max_lane_count(intel_dp);
int max_clock = intel_dp_max_link_bw(intel_dp) == DP_LINK_BW_2_7 ? 1 : 0;
- int bpp = mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+ int bpp;
static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
if (is_edp(intel_dp) && intel_dp->panel_fixed_mode) {
@@ -686,6 +702,11 @@
mode->clock = intel_dp->panel_fixed_mode->clock;
}
+ if (!intel_dp_adjust_dithering(intel_dp, mode, adjusted_mode))
+ return false;
+
+ bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
+
for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
for (clock = 0; clock <= max_clock; clock++) {
int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5a14149..715afa1 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -105,6 +105,10 @@
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
#define INTEL_MODE_DP_FORCE_6BPC (0x10)
+/* This flag must be set by the encoder's mode_fixup if it changes the crtc
+ * timings in the mode to prevent the crtc fixup from overwriting them.
+ * Currently only lvds needs that. */
+#define INTEL_MODE_CRTC_TIMINGS_SET (0x20)
static inline void
intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index 19ecd78..6e9ee33 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -279,6 +279,8 @@
struct drm_mode_config *config = &dev->mode_config;
struct drm_plane *plane;
+ mutex_lock(&dev->mode_config.mutex);
+
ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
@@ -286,4 +288,6 @@
/* Be sure to shut off any planes that may be active */
list_for_each_entry(plane, &config->plane_list, head)
plane->funcs->disable_plane(plane);
+
+ mutex_unlock(&dev->mode_config.mutex);
}
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index cae3e5f..2d7f47b 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -136,7 +136,7 @@
val &= ~VIDEO_DIP_SELECT_MASK;
- I915_WRITE(VIDEO_DIP_CTL, val | port | flags);
+ I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags);
for (i = 0; i < len; i += 4) {
I915_WRITE(VIDEO_DIP_DATA, *data);
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
index 601c86e..8fdc957 100644
--- a/drivers/gpu/drm/i915/intel_i2c.c
+++ b/drivers/gpu/drm/i915/intel_i2c.c
@@ -390,7 +390,7 @@
bus->has_gpio = intel_gpio_setup(bus, i);
/* XXX force bit banging until GMBUS is fully debugged */
- if (bus->has_gpio && IS_GEN2(dev))
+ if (bus->has_gpio)
bus->force_bit = true;
}
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index c5c0973..9c71183 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -187,6 +187,8 @@
mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+
+ mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
}
static void
@@ -208,6 +210,8 @@
mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+
+ mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
}
static inline u32 panel_fitter_scaling(u32 source, u32 target)
@@ -283,6 +287,8 @@
for_each_pipe(pipe)
I915_WRITE(BCLRPAT(pipe), 0);
+ drm_mode_set_crtcinfo(adjusted_mode, 0);
+
switch (intel_lvds->fitting_mode) {
case DRM_MODE_SCALE_CENTER:
/*
@@ -744,7 +750,7 @@
.ident = "Hewlett-Packard t5745",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_BOARD_NAME, "hp t5745"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
},
},
{
@@ -752,7 +758,15 @@
.ident = "Hewlett-Packard st5747",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_BOARD_NAME, "hp st5747"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "MSI Wind Box DC500",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
},
},
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 230a141..48177ec 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -47,8 +47,6 @@
adjusted_mode->vtotal = fixed_mode->vtotal;
adjusted_mode->clock = fixed_mode->clock;
-
- drm_mode_set_crtcinfo(adjusted_mode, 0);
}
/* adjusted_mode has been preset to be the panel's fixed mode */
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index fc66af6..62892a8 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -398,6 +398,17 @@
return ret;
}
+
+ if (IS_GEN6(dev)) {
+ /* From the Sandybridge PRM, volume 1 part 3, page 24:
+ * "If this bit is set, STCunit will have LRA as replacement
+ * policy. [...] This bit must be reset. LRA replacement
+ * policy is not supported."
+ */
+ I915_WRITE(CACHE_MODE_0,
+ CM0_STC_EVICT_DISABLE_LRA_SNB << CM0_MASK_SHIFT);
+ }
+
if (INTEL_INFO(dev)->gen >= 6) {
I915_WRITE(INSTPM,
INSTPM_FORCE_ORDERING << 16 | INSTPM_FORCE_ORDERING);
@@ -626,7 +637,7 @@
/* 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))
+ if (IS_GEN6(dev) || IS_GEN7(dev))
intel_ring_get_active_head(ring);
return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
}
@@ -1038,7 +1049,7 @@
* of the buffer.
*/
ring->effective_size = ring->size;
- if (IS_I830(ring->dev))
+ if (IS_I830(ring->dev) || IS_845G(ring->dev))
ring->effective_size -= 128;
return 0;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index e36b171..ae5e748 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -731,6 +731,7 @@
uint16_t width, height;
uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
uint16_t h_sync_offset, v_sync_offset;
+ int mode_clock;
width = mode->crtc_hdisplay;
height = mode->crtc_vdisplay;
@@ -745,7 +746,11 @@
h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
- dtd->part1.clock = mode->clock / 10;
+ mode_clock = mode->clock;
+ mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1;
+ mode_clock /= 10;
+ dtd->part1.clock = mode_clock;
+
dtd->part1.h_active = width & 0xff;
dtd->part1.h_blank = h_blank_len & 0xff;
dtd->part1.h_high = (((width >> 8) & 0xf) << 4) |
@@ -996,7 +1001,7 @@
struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
u32 sdvox;
struct intel_sdvo_in_out_map in_out;
- struct intel_sdvo_dtd input_dtd;
+ struct intel_sdvo_dtd input_dtd, output_dtd;
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
int rate;
@@ -1021,20 +1026,13 @@
intel_sdvo->attached_output))
return;
- /* We have tried to get input timing in mode_fixup, and filled into
- * adjusted_mode.
- */
- if (intel_sdvo->is_tv || intel_sdvo->is_lvds) {
- input_dtd = intel_sdvo->input_dtd;
- } else {
- /* Set the output timing to the screen */
- if (!intel_sdvo_set_target_output(intel_sdvo,
- intel_sdvo->attached_output))
- return;
-
- intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
- (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd);
- }
+ /* lvds has a special fixed output timing. */
+ if (intel_sdvo->is_lvds)
+ intel_sdvo_get_dtd_from_mode(&output_dtd,
+ intel_sdvo->sdvo_lvds_fixed_mode);
+ else
+ intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
+ (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd);
/* Set the input timing to the screen. Assume always input 0. */
if (!intel_sdvo_set_target_input(intel_sdvo))
@@ -1052,6 +1050,10 @@
!intel_sdvo_set_tv_format(intel_sdvo))
return;
+ /* We have tried to get input timing in mode_fixup, and filled into
+ * adjusted_mode.
+ */
+ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
(void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
switch (pixel_multiplier) {
@@ -1218,8 +1220,14 @@
static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo)
{
+ struct drm_device *dev = intel_sdvo->base.base.dev;
u8 response[2];
+ /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise
+ * on the line. */
+ if (IS_I945G(dev) || IS_I945GM(dev))
+ return false;
+
return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT,
&response, 2) && response[0];
}
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7aa0450..e90dfb6 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -95,7 +95,6 @@
/* must disable */
sprctl |= SPRITE_TRICKLE_FEED_DISABLE;
sprctl |= SPRITE_ENABLE;
- sprctl |= SPRITE_DEST_KEY;
/* Sizes are 0 based */
src_w--;
@@ -411,6 +410,9 @@
old_obj = intel_plane->obj;
+ src_w = src_w >> 16;
+ src_h = src_h >> 16;
+
/* Pipe must be running... */
if (!(I915_READ(PIPECONF(pipe)) & PIPECONF_ENABLE))
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig
index ca16399..97a8126 100644
--- a/drivers/gpu/drm/nouveau/Kconfig
+++ b/drivers/gpu/drm/nouveau/Kconfig
@@ -13,6 +13,7 @@
select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT
select ACPI_WMI if ACPI
select MXM_WMI if ACPI
+ select POWER_SUPPLY
help
Choose this option for open-source nVidia support.
diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c
index 7814a76..284bd25 100644
--- a/drivers/gpu/drm/nouveau/nouveau_acpi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c
@@ -270,7 +270,7 @@
struct acpi_buffer buffer = {sizeof(acpi_method_name), acpi_method_name};
struct pci_dev *pdev = NULL;
int has_dsm = 0;
- int has_optimus;
+ int has_optimus = 0;
int vga_count = 0;
bool guid_valid;
int retval;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index 637afe7..0be4a81 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -177,14 +177,15 @@
if (!pci_enable_rom(pdev)) {
void __iomem *rom = pci_map_rom(pdev, &length);
- if (rom) {
+ if (rom && length) {
bios->data = kmalloc(length, GFP_KERNEL);
if (bios->data) {
memcpy_fromio(bios->data, rom, length);
bios->length = length;
}
- pci_unmap_rom(pdev, rom);
}
+ if (rom)
+ pci_unmap_rom(pdev, rom);
pci_disable_rom(pdev);
}
@@ -6155,10 +6156,14 @@
/* heuristic: if we ever get a non-zero connector field, assume
* that all the indices are valid and we don't need fake them.
+ *
+ * and, as usual, a blacklist of boards with bad bios data..
*/
- for (i = 0; i < dcbt->entries; i++) {
- if (dcbt->entry[i].connector)
- return;
+ if (!nv_match_device(bios->dev, 0x0392, 0x107d, 0x20a2)) {
+ for (i = 0; i < dcbt->entries; i++) {
+ if (dcbt->entry[i].connector)
+ return;
+ }
}
/* no useful connector info available, we need to make it up
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 44e6416..846afb0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -436,11 +436,11 @@
}
if (dev_priv->card_type < NV_C0) {
- init->subchan[0].handle = NvSw;
- init->subchan[0].grclass = NV_SW;
- init->nr_subchan = 1;
- } else {
- init->nr_subchan = 0;
+ init->subchan[0].handle = 0x00000000;
+ init->subchan[0].grclass = 0x0000;
+ init->subchan[1].handle = NvSw;
+ init->subchan[1].grclass = NV_SW;
+ init->nr_subchan = 2;
}
/* Named memory object area */
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h
index bcf0fd9..23d4edf 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.h
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.h
@@ -48,8 +48,8 @@
/* Hardcoded object assignments to subchannels (subchannel id). */
enum {
- NvSubSw = 0,
- NvSubM2MF = 1,
+ NvSubM2MF = 0,
+ NvSubSw = 1,
NvSub2D = 2,
NvSubCtxSurf2D = 2,
NvSubGdiRect = 3,
diff --git a/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/drivers/gpu/drm/nouveau/nouveau_hdmi.c
index 59ea1c1..c3de363 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hdmi.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hdmi.c
@@ -32,7 +32,9 @@
hdmi_sor(struct drm_encoder *encoder)
{
struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
- if (dev_priv->chipset < 0xa3)
+ if (dev_priv->chipset < 0xa3 ||
+ dev_priv->chipset == 0xaa ||
+ dev_priv->chipset == 0xac)
return false;
return true;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c
index e2be95a..77e5646 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.c
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c
@@ -29,10 +29,6 @@
#include "nouveau_i2c.h"
#include "nouveau_hw.h"
-#define T_TIMEOUT 2200000
-#define T_RISEFALL 1000
-#define T_HOLD 5000
-
static void
i2c_drive_scl(void *data, int state)
{
@@ -113,175 +109,6 @@
return 0;
}
-static void
-i2c_delay(struct nouveau_i2c_chan *port, u32 nsec)
-{
- udelay((nsec + 500) / 1000);
-}
-
-static bool
-i2c_raise_scl(struct nouveau_i2c_chan *port)
-{
- u32 timeout = T_TIMEOUT / T_RISEFALL;
-
- i2c_drive_scl(port, 1);
- do {
- i2c_delay(port, T_RISEFALL);
- } while (!i2c_sense_scl(port) && --timeout);
-
- return timeout != 0;
-}
-
-static int
-i2c_start(struct nouveau_i2c_chan *port)
-{
- int ret = 0;
-
- port->state = i2c_sense_scl(port);
- port->state |= i2c_sense_sda(port) << 1;
- if (port->state != 3) {
- i2c_drive_scl(port, 0);
- i2c_drive_sda(port, 1);
- if (!i2c_raise_scl(port))
- ret = -EBUSY;
- }
-
- i2c_drive_sda(port, 0);
- i2c_delay(port, T_HOLD);
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return ret;
-}
-
-static void
-i2c_stop(struct nouveau_i2c_chan *port)
-{
- i2c_drive_scl(port, 0);
- i2c_drive_sda(port, 0);
- i2c_delay(port, T_RISEFALL);
-
- i2c_drive_scl(port, 1);
- i2c_delay(port, T_HOLD);
- i2c_drive_sda(port, 1);
- i2c_delay(port, T_HOLD);
-}
-
-static int
-i2c_bitw(struct nouveau_i2c_chan *port, int sda)
-{
- i2c_drive_sda(port, sda);
- i2c_delay(port, T_RISEFALL);
-
- if (!i2c_raise_scl(port))
- return -ETIMEDOUT;
- i2c_delay(port, T_HOLD);
-
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return 0;
-}
-
-static int
-i2c_bitr(struct nouveau_i2c_chan *port)
-{
- int sda;
-
- i2c_drive_sda(port, 1);
- i2c_delay(port, T_RISEFALL);
-
- if (!i2c_raise_scl(port))
- return -ETIMEDOUT;
- i2c_delay(port, T_HOLD);
-
- sda = i2c_sense_sda(port);
-
- i2c_drive_scl(port, 0);
- i2c_delay(port, T_HOLD);
- return sda;
-}
-
-static int
-i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last)
-{
- int i, bit;
-
- *byte = 0;
- for (i = 7; i >= 0; i--) {
- bit = i2c_bitr(port);
- if (bit < 0)
- return bit;
- *byte |= bit << i;
- }
-
- return i2c_bitw(port, last ? 1 : 0);
-}
-
-static int
-i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte)
-{
- int i, ret;
- for (i = 7; i >= 0; i--) {
- ret = i2c_bitw(port, !!(byte & (1 << i)));
- if (ret < 0)
- return ret;
- }
-
- ret = i2c_bitr(port);
- if (ret == 1) /* nack */
- ret = -EIO;
- return ret;
-}
-
-static int
-i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg)
-{
- u32 addr = msg->addr << 1;
- if (msg->flags & I2C_M_RD)
- addr |= 1;
- return i2c_put_byte(port, addr);
-}
-
-static int
-i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-{
- struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap;
- struct i2c_msg *msg = msgs;
- int ret = 0, mcnt = num;
-
- while (!ret && mcnt--) {
- u8 remaining = msg->len;
- u8 *ptr = msg->buf;
-
- ret = i2c_start(port);
- if (ret == 0)
- ret = i2c_addr(port, msg);
-
- if (msg->flags & I2C_M_RD) {
- while (!ret && remaining--)
- ret = i2c_get_byte(port, ptr++, !remaining);
- } else {
- while (!ret && remaining--)
- ret = i2c_put_byte(port, *ptr++);
- }
-
- msg++;
- }
-
- i2c_stop(port);
- return (ret < 0) ? ret : num;
-}
-
-static u32
-i2c_bit_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-const struct i2c_algorithm nouveau_i2c_bit_algo = {
- .master_xfer = i2c_bit_xfer,
- .functionality = i2c_bit_func
-};
-
static const uint32_t nv50_i2c_port[] = {
0x00e138, 0x00e150, 0x00e168, 0x00e180,
0x00e254, 0x00e274, 0x00e764, 0x00e780,
@@ -384,12 +211,10 @@
case 0: /* NV04:NV50 */
port->drive = entry[0];
port->sense = entry[1];
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 4: /* NV4E */
port->drive = 0x600800 + entry[1];
port->sense = port->drive;
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 5: /* NV50- */
port->drive = entry[0] & 0x0f;
@@ -402,7 +227,6 @@
port->drive = 0x00d014 + (port->drive * 0x20);
port->sense = port->drive;
}
- port->adapter.algo = &nouveau_i2c_bit_algo;
break;
case 6: /* NV50- DP AUX */
port->drive = entry[0];
@@ -413,7 +237,7 @@
break;
}
- if (!port->adapter.algo) {
+ if (!port->adapter.algo && !port->drive) {
NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n",
i, port->type, port->drive, port->sense);
kfree(port);
@@ -429,7 +253,26 @@
port->dcb = ROM32(entry[0]);
i2c_set_adapdata(&port->adapter, i2c);
- ret = i2c_add_adapter(&port->adapter);
+ if (port->adapter.algo != &nouveau_dp_i2c_algo) {
+ port->adapter.algo_data = &port->bit;
+ port->bit.udelay = 10;
+ port->bit.timeout = usecs_to_jiffies(2200);
+ port->bit.data = port;
+ port->bit.setsda = i2c_drive_sda;
+ port->bit.setscl = i2c_drive_scl;
+ port->bit.getsda = i2c_sense_sda;
+ port->bit.getscl = i2c_sense_scl;
+
+ i2c_drive_scl(port, 0);
+ i2c_drive_sda(port, 1);
+ i2c_drive_scl(port, 1);
+
+ ret = i2c_bit_add_bus(&port->adapter);
+ } else {
+ port->adapter.algo = &nouveau_dp_i2c_algo;
+ ret = i2c_add_adapter(&port->adapter);
+ }
+
if (ret) {
NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret);
kfree(port);
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h
index 4d2e4e9..1d08389 100644
--- a/drivers/gpu/drm/nouveau/nouveau_i2c.h
+++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h
@@ -34,6 +34,7 @@
struct nouveau_i2c_chan {
struct i2c_adapter adapter;
struct drm_device *dev;
+ struct i2c_algo_bit_data bit;
struct list_head head;
u8 index;
u8 type;
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 34d591b..da3e7c3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -235,6 +235,7 @@
return -EPERM;
strncpy(string, profile, sizeof(string));
+ string[sizeof(string) - 1] = 0;
if ((ptr = strchr(string, '\n')))
*ptr = '\0';
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index a4886b3..c2a8511 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -642,7 +642,7 @@
OUT_RING (chan, chan->vram_handle);
OUT_RING (chan, chan->gart_handle);
} else
- if (dev_priv->card_type <= NV_C0) {
+ if (dev_priv->card_type <= NV_D0) {
ret = nouveau_gpuobj_gr_new(chan, 0x9039, 0x9039);
if (ret)
goto error;
diff --git a/drivers/gpu/drm/nouveau/nv10_gpio.c b/drivers/gpu/drm/nouveau/nv10_gpio.c
index 550ad3f..9d79180 100644
--- a/drivers/gpu/drm/nouveau/nv10_gpio.c
+++ b/drivers/gpu/drm/nouveau/nv10_gpio.c
@@ -65,7 +65,7 @@
if (line < 10) {
line = (line - 2) * 4;
reg = NV_PCRTC_GPIO_EXT;
- mask = 0x00000003 << ((line - 2) * 4);
+ mask = 0x00000003;
data = (dir << 1) | out;
} else
if (line < 14) {
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c
index a7844ab..2746402 100644
--- a/drivers/gpu/drm/nouveau/nv50_sor.c
+++ b/drivers/gpu/drm/nouveau/nv50_sor.c
@@ -42,7 +42,7 @@
struct drm_nouveau_private *dev_priv = dev->dev_private;
static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
static const u8 nv50[] = { 16, 8, 0, 24 };
- if (dev_priv->card_type == 0xaf)
+ if (dev_priv->chipset == 0xaf)
return nvaf[lane];
return nv50[lane];
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c
index 5bf5503..f704e94 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fb.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fb.c
@@ -54,6 +54,11 @@
nvc0_mfb_subp_isr(dev, unit, subp);
units &= ~(1 << unit);
}
+
+ /* we do something horribly wrong and upset PMFB a lot, so mask off
+ * interrupts from it after the first one until it's fixed
+ */
+ nv_mask(dev, 0x000640, 0x02000000, 0x00000000);
}
static void
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index d1bd239..5ce9bf5 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -1306,8 +1306,11 @@
int atom_asic_init(struct atom_context *ctx)
{
+ struct radeon_device *rdev = ctx->card->dev->dev_private;
int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
uint32_t ps[16];
+ int ret;
+
memset(ps, 0, 64);
ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
@@ -1317,7 +1320,17 @@
if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
return 1;
- return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+ ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+ if (ret)
+ return ret;
+
+ memset(ps, 0, 64);
+
+ if (rdev->family < CHIP_R600) {
+ if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
+ atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
+ }
+ return ret;
}
void atom_destroy(struct atom_context *ctx)
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
index 93cfe20..25fea63 100644
--- a/drivers/gpu/drm/radeon/atom.h
+++ b/drivers/gpu/drm/radeon/atom.h
@@ -44,6 +44,7 @@
#define ATOM_CMD_SETSCLK 0x0A
#define ATOM_CMD_SETMCLK 0x0B
#define ATOM_CMD_SETPCLK 0x0C
+#define ATOM_CMD_SPDFANCNTL 0x39
#define ATOM_DATA_FWI_PTR 0xC
#define ATOM_DATA_IIO_PTR 0x32
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index b5ff1f7..af1054f 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -575,6 +575,9 @@
if (rdev->family < CHIP_RV770)
pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
+ /* use frac fb div on APUs */
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
+ pll->flags |= RADEON_PLL_USE_FRAC_FB_DIV;
} else {
pll->flags |= RADEON_PLL_LEGACY;
@@ -955,8 +958,8 @@
break;
}
- if (radeon_encoder->active_device &
- (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) {
+ if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) ||
+ (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE)) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
struct drm_connector *connector =
radeon_get_connector_for_encoder(encoder);
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index e607c4d..2d39f99 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -230,6 +230,10 @@
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return;
+ /* some R4xx chips have the wrong frev */
+ if (rdev->family <= CHIP_RV410)
+ frev = 1;
+
switch (frev) {
case 1:
switch (crev) {
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 81801c1..fe33d35 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -2553,7 +2553,7 @@
* or the chip could hang on a subsequent access
*/
if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) {
- udelay(5000);
+ mdelay(5);
}
/* This function is required to workaround a hardware bug in some (all?)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 391bd26..c8187c4 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1135,7 +1135,7 @@
}
if (rdev->flags & RADEON_IS_AGP) {
size_bf = mc->gtt_start;
- size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+ size_af = 0xFFFFFFFF - mc->gtt_end;
if (size_bf > size_af) {
if (mc->mc_vram_size > size_bf) {
dev_warn(rdev->dev, "limiting VRAM\n");
@@ -1149,7 +1149,7 @@
mc->real_vram_size = size_af;
mc->mc_vram_size = size_af;
}
- mc->vram_start = mc->gtt_end;
+ mc->vram_start = mc->gtt_end + 1;
}
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
@@ -2839,7 +2839,7 @@
/* r7xx asics need to soft reset RLC before halting */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC);
RREG32(SRBM_SOFT_RESET);
- udelay(15000);
+ mdelay(15);
WREG32(SRBM_SOFT_RESET, 0);
RREG32(SRBM_SOFT_RESET);
}
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c
index 84c5462..75ed17c 100644
--- a/drivers/gpu/drm/radeon/r600_cp.c
+++ b/drivers/gpu/drm/radeon/r600_cp.c
@@ -407,7 +407,7 @@
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_UDELAY(15000);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
fw_data = (const __be32 *)dev_priv->me_fw->data;
@@ -500,7 +500,7 @@
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_UDELAY(15000);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
fw_data = (const __be32 *)dev_priv->pfp_fw->data;
@@ -1797,7 +1797,7 @@
RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
RADEON_READ(R600_GRBM_SOFT_RESET);
- DRM_UDELAY(15000);
+ mdelay(15);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c
index 6ae0c75..9c6b29a 100644
--- a/drivers/gpu/drm/radeon/radeon_clocks.c
+++ b/drivers/gpu/drm/radeon/radeon_clocks.c
@@ -633,7 +633,7 @@
tmp &= ~(R300_SCLK_FORCE_VAP);
tmp |= RADEON_SCLK_FORCE_CP;
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
tmp = RREG32_PLL(R300_SCLK_CNTL2);
tmp &= ~(R300_SCLK_FORCE_TCL |
@@ -651,12 +651,12 @@
tmp |= (RADEON_ENGIN_DYNCLK_MODE |
(0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT));
WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL);
tmp |= RADEON_SCLK_DYN_START_CNTL;
WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
/* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200
to lockup randomly, leave them as set by BIOS.
@@ -696,7 +696,7 @@
tmp |= RADEON_SCLK_MORE_FORCEON;
}
WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
}
/* RV200::A11 A12, RV250::A11 A12 */
@@ -709,7 +709,7 @@
tmp |= RADEON_TCL_BYPASS_DISABLE;
WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp);
}
- udelay(15000);
+ mdelay(15);
/*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */
tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -722,14 +722,14 @@
RADEON_PIXCLK_TMDS_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
tmp |= (RADEON_PIXCLK_ALWAYS_ONb |
RADEON_PIXCLK_DAC_ALWAYS_ONb);
WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp);
- udelay(15000);
+ mdelay(15);
}
} else {
/* Turn everything OFF (ForceON to everything) */
@@ -861,7 +861,7 @@
}
WREG32_PLL(RADEON_SCLK_CNTL, tmp);
- udelay(16000);
+ mdelay(16);
if ((rdev->family == CHIP_R300) ||
(rdev->family == CHIP_R350)) {
@@ -870,7 +870,7 @@
R300_SCLK_FORCE_GA |
R300_SCLK_FORCE_CBA);
WREG32_PLL(R300_SCLK_CNTL2, tmp);
- udelay(16000);
+ mdelay(16);
}
if (rdev->flags & RADEON_IS_IGP) {
@@ -878,7 +878,7 @@
tmp &= ~(RADEON_FORCEON_MCLKA |
RADEON_FORCEON_YCLKA);
WREG32_PLL(RADEON_MCLK_CNTL, tmp);
- udelay(16000);
+ mdelay(16);
}
if ((rdev->family == CHIP_RV200) ||
@@ -887,7 +887,7 @@
tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL);
tmp |= RADEON_SCLK_MORE_FORCEON;
WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp);
- udelay(16000);
+ mdelay(16);
}
tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL);
@@ -900,7 +900,7 @@
RADEON_PIXCLK_TMDS_ALWAYS_ONb);
WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
- udelay(16000);
+ mdelay(16);
tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 81fc100..2cad9fd 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2845,7 +2845,7 @@
case 4:
val = RBIOS16(index);
index += 2;
- udelay(val * 1000);
+ mdelay(val);
break;
case 6:
slave_addr = id & 0xff;
@@ -3044,7 +3044,7 @@
udelay(150);
break;
case 2:
- udelay(1000);
+ mdelay(1);
break;
case 3:
while (tmp--) {
@@ -3075,13 +3075,13 @@
/*mclk_cntl |= 0x00001111;*//* ??? */
WREG32_PLL(RADEON_MCLK_CNTL,
mclk_cntl);
- udelay(10000);
+ mdelay(10);
#endif
WREG32_PLL
(RADEON_CLK_PWRMGT_CNTL,
tmp &
~RADEON_CG_NO1_DEBUG_0);
- udelay(10000);
+ mdelay(10);
}
break;
default:
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index bd05156..3c2e7a0 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -970,7 +970,7 @@
encoder = obj_to_encoder(obj);
- if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
continue;
@@ -1000,6 +1000,7 @@
* cases the DVI port is actually a virtual KVM port connected to the service
* processor.
*/
+out:
if ((!rdev->is_atom_bios) &&
(ret == connector_status_disconnected) &&
rdev->mode_info.bios_hardcoded_edid_size) {
@@ -1007,7 +1008,6 @@
ret = connector_status_connected;
}
-out:
/* updated in get modes as well since we need to know if it's analog or digital */
radeon_connector_update_scratch_regs(connector, ret);
return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index ea7df16e2..5992502 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -241,8 +241,8 @@
rdev->wb.use_event = true;
}
}
- /* always use writeback/events on NI */
- if (ASIC_IS_DCE5(rdev)) {
+ /* always use writeback/events on NI, APUs */
+ if (rdev->family >= CHIP_PALM) {
rdev->wb.enabled = true;
rdev->wb.use_event = true;
}
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 8086c96..0a1d4bd 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -533,7 +533,7 @@
radeon_legacy_init_crtc(dev, radeon_crtc);
}
-static const char *encoder_names[36] = {
+static const char *encoder_names[37] = {
"NONE",
"INTERNAL_LVDS",
"INTERNAL_TMDS1",
@@ -570,6 +570,7 @@
"INTERNAL_UNIPHY2",
"NUTMEG",
"TRAVIS",
+ "INTERNAL_VCE"
};
static const char *connector_names[15] = {
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 85bcfc8..3edec1c 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -900,6 +900,10 @@
struct radeon_i2c_chan *i2c;
int ret;
+ /* don't add the mm_i2c bus unless hw_i2c is enabled */
+ if (rec->mm_i2c && (radeon_hw_i2c == 0))
+ return NULL;
+
i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
if (i2c == NULL)
return NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 66d5fe1..65060b7 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -147,6 +147,12 @@
(rdev->pdev->subsystem_device == 0x01fd))
return true;
+ /* RV515 seems to have MSI issues where it loses
+ * MSI rearms occasionally. This leads to lockups and freezes.
+ * disable it by default.
+ */
+ if (rdev->family == CHIP_RV515)
+ return false;
if (rdev->flags & RADEON_IS_IGP) {
/* APUs work fine with MSIs */
if (rdev->family >= CHIP_PALM)
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index 2f46e0c8..42db254 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -88,7 +88,7 @@
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl |= RADEON_LVDS_PLL_EN;
WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl);
- udelay(1000);
+ mdelay(1);
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET;
@@ -101,7 +101,7 @@
(backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
if (is_mac)
lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
- udelay(panel_pwr_delay * 1000);
+ mdelay(panel_pwr_delay);
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
break;
case DRM_MODE_DPMS_STANDBY:
@@ -118,10 +118,10 @@
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON);
}
- udelay(panel_pwr_delay * 1000);
+ mdelay(panel_pwr_delay);
WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
- udelay(panel_pwr_delay * 1000);
+ mdelay(panel_pwr_delay);
break;
}
@@ -656,7 +656,7 @@
WREG32(RADEON_DAC_MACRO_CNTL, tmp);
- udelay(2000);
+ mdelay(2);
if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT)
found = connector_status_connected;
@@ -1499,7 +1499,7 @@
tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN;
WREG32(RADEON_DAC_CNTL2, tmp);
- udelay(10000);
+ mdelay(10);
if (ASIC_IS_R300(rdev)) {
if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B)
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 6f70158..df6a4db 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -241,7 +241,8 @@
domain_start = bo->rdev->mc.vram_start;
else
domain_start = bo->rdev->mc.gtt_start;
- WARN_ON_ONCE((*gpu_addr - domain_start) > max_offset);
+ WARN_ON_ONCE(max_offset <
+ (radeon_bo_gpu_offset(bo) - domain_start));
}
return 0;
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index c62ae4b..cdab1ae 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -969,7 +969,7 @@
}
if (rdev->flags & RADEON_IS_AGP) {
size_bf = mc->gtt_start;
- size_af = 0xFFFFFFFF - mc->gtt_end + 1;
+ size_af = 0xFFFFFFFF - mc->gtt_end;
if (size_bf > size_af) {
if (mc->mc_vram_size > size_bf) {
dev_warn(rdev->dev, "limiting VRAM\n");
@@ -983,7 +983,7 @@
mc->real_vram_size = size_af;
mc->mc_vram_size = size_af;
}
- mc->vram_start = mc->gtt_end;
+ mc->vram_start = mc->gtt_end + 1;
}
mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n",
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index ac7a199..27bda98 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2999,8 +2999,8 @@
}
r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->rlc.save_restore_gpu_addr);
+ radeon_bo_unreserve(rdev->rlc.save_restore_obj);
if (r) {
- radeon_bo_unreserve(rdev->rlc.save_restore_obj);
dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r);
si_rlc_fini(rdev);
return r;
@@ -3023,9 +3023,8 @@
}
r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->rlc.clear_state_gpu_addr);
+ radeon_bo_unreserve(rdev->rlc.clear_state_obj);
if (r) {
-
- radeon_bo_unreserve(rdev->rlc.clear_state_obj);
dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r);
si_rlc_fini(rdev);
return r;
diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c
index 031aaaf..b6d8608 100644
--- a/drivers/gpu/drm/savage/savage_state.c
+++ b/drivers/gpu/drm/savage/savage_state.c
@@ -988,7 +988,7 @@
* for locking on FreeBSD.
*/
if (cmdbuf->size) {
- kcmd_addr = kmalloc(cmdbuf->size * 8, GFP_KERNEL);
+ kcmd_addr = kmalloc_array(cmdbuf->size, 8, GFP_KERNEL);
if (kcmd_addr == NULL)
return -ENOMEM;
@@ -1015,8 +1015,8 @@
cmdbuf->vb_addr = kvb_addr;
}
if (cmdbuf->nbox) {
- kbox_addr = kmalloc(cmdbuf->nbox * sizeof(struct drm_clip_rect),
- GFP_KERNEL);
+ kbox_addr = kmalloc_array(cmdbuf->nbox, sizeof(struct drm_clip_rect),
+ GFP_KERNEL);
if (kbox_addr == NULL) {
ret = -ENOMEM;
goto done;
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 5340c5f..5367390 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -47,7 +47,7 @@
static const struct file_operations udl_driver_fops = {
.owner = THIS_MODULE,
.open = drm_open,
- .mmap = drm_gem_mmap,
+ .mmap = udl_drm_gem_mmap,
.poll = drm_poll,
.read = drm_read,
.unlocked_ioctl = drm_ioctl,
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index 1612954..96820d0 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -121,6 +121,7 @@
int udl_gem_vmap(struct udl_gem_object *obj);
void udl_gem_vunmap(struct udl_gem_object *obj);
+int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c
index 852642d..92f19ef 100644
--- a/drivers/gpu/drm/udl/udl_gem.c
+++ b/drivers/gpu/drm/udl/udl_gem.c
@@ -71,6 +71,20 @@
return drm_gem_handle_delete(file, handle);
}
+int udl_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ int ret;
+
+ ret = drm_gem_mmap(filp, vma);
+ if (ret)
+ return ret;
+
+ vma->vm_flags &= ~VM_PFNMAP;
+ vma->vm_flags |= VM_MIXEDMAP;
+
+ return ret;
+}
+
int udl_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct udl_gem_object *obj = to_udl_bo(vma->vm_private_data);
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index a3d0332..ffddcba 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -34,7 +34,7 @@
config HID_BATTERY_STRENGTH
bool
depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY
- default y
+ default n
config HIDRAW
bool "/dev/hidraw raw HID device support"
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index 12f9777..45c3433 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -1525,12 +1525,6 @@
/*
* The "eeprom" file
*/
-static int picolcd_debug_eeprom_open(struct inode *i, struct file *f)
-{
- f->private_data = i->i_private;
- return 0;
-}
-
static ssize_t picolcd_debug_eeprom_read(struct file *f, char __user *u,
size_t s, loff_t *off)
{
@@ -1618,7 +1612,7 @@
*/
static const struct file_operations picolcd_debug_eeprom_fops = {
.owner = THIS_MODULE,
- .open = picolcd_debug_eeprom_open,
+ .open = simple_open,
.read = picolcd_debug_eeprom_read,
.write = picolcd_debug_eeprom_write,
.llseek = generic_file_llseek,
@@ -1627,12 +1621,6 @@
/*
* The "flash" file
*/
-static int picolcd_debug_flash_open(struct inode *i, struct file *f)
-{
- f->private_data = i->i_private;
- return 0;
-}
-
/* record a flash address to buf (bounds check to be done by caller) */
static int _picolcd_flash_setaddr(struct picolcd_data *data, u8 *buf, long off)
{
@@ -1817,7 +1805,7 @@
*/
static const struct file_operations picolcd_debug_flash_fops = {
.owner = THIS_MODULE,
- .open = picolcd_debug_flash_open,
+ .open = simple_open,
.read = picolcd_debug_flash_read,
.write = picolcd_debug_flash_write,
.llseek = generic_file_llseek,
diff --git a/drivers/hid/hid-tivo.c b/drivers/hid/hid-tivo.c
index de47039..9f85f82 100644
--- a/drivers/hid/hid-tivo.c
+++ b/drivers/hid/hid-tivo.c
@@ -62,7 +62,7 @@
static const struct hid_device_id tivo_devices[] = {
/* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */
- { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
{ }
};
diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c
index 17dabc1..eec3291 100644
--- a/drivers/hid/hid-wiimote-debug.c
+++ b/drivers/hid/hid-wiimote-debug.c
@@ -23,12 +23,6 @@
struct dentry *drm;
};
-static int wiidebug_eeprom_open(struct inode *i, struct file *f)
-{
- f->private_data = i->i_private;
- return 0;
-}
-
static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
loff_t *off)
{
@@ -83,7 +77,7 @@
static const struct file_operations wiidebug_eeprom_fops = {
.owner = THIS_MODULE,
- .open = wiidebug_eeprom_open,
+ .open = simple_open,
.read = wiidebug_eeprom_read,
.llseek = generic_file_llseek,
};
diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig
new file mode 100644
index 0000000..d94e38d
--- /dev/null
+++ b/drivers/hsi/Kconfig
@@ -0,0 +1,19 @@
+#
+# HSI driver configuration
+#
+menuconfig HSI
+ tristate "HSI support"
+ ---help---
+ The "High speed synchronous Serial Interface" is
+ synchronous serial interface used mainly to connect
+ application engines and cellular modems.
+
+if HSI
+
+config HSI_BOARDINFO
+ bool
+ default y
+
+source "drivers/hsi/clients/Kconfig"
+
+endif # HSI
diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile
new file mode 100644
index 0000000..9d5d33f
--- /dev/null
+++ b/drivers/hsi/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for HSI
+#
+obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o
+obj-$(CONFIG_HSI) += hsi.o
+obj-y += clients/
diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig
new file mode 100644
index 0000000..3bacd27
--- /dev/null
+++ b/drivers/hsi/clients/Kconfig
@@ -0,0 +1,13 @@
+#
+# HSI clients configuration
+#
+
+comment "HSI clients"
+
+config HSI_CHAR
+ tristate "HSI/SSI character driver"
+ depends on HSI
+ ---help---
+ If you say Y here, you will enable the HSI/SSI character driver.
+ This driver provides a simple character device interface for
+ serial communication with the cellular modem over HSI/SSI bus.
diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile
new file mode 100644
index 0000000..327c0e2
--- /dev/null
+++ b/drivers/hsi/clients/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for HSI clients
+#
+
+obj-$(CONFIG_HSI_CHAR) += hsi_char.o
diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c
new file mode 100644
index 0000000..3ad91f6
--- /dev/null
+++ b/drivers/hsi/clients/hsi_char.c
@@ -0,0 +1,802 @@
+/*
+ * HSI character device driver, implements the character device
+ * interface.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/atomic.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kmemleak.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <linux/stat.h>
+#include <linux/hsi/hsi.h>
+#include <linux/hsi/hsi_char.h>
+
+#define HSC_DEVS 16 /* Num of channels */
+#define HSC_MSGS 4
+
+#define HSC_RXBREAK 0
+
+#define HSC_ID_BITS 6
+#define HSC_PORT_ID_BITS 4
+#define HSC_ID_MASK 3
+#define HSC_PORT_ID_MASK 3
+#define HSC_CH_MASK 0xf
+
+/*
+ * We support up to 4 controllers that can have up to 4
+ * ports, which should currently be more than enough.
+ */
+#define HSC_BASEMINOR(id, port_id) \
+ ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \
+ (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS))
+
+enum {
+ HSC_CH_OPEN,
+ HSC_CH_READ,
+ HSC_CH_WRITE,
+ HSC_CH_WLINE,
+};
+
+enum {
+ HSC_RX,
+ HSC_TX,
+};
+
+struct hsc_client_data;
+/**
+ * struct hsc_channel - hsi_char internal channel data
+ * @ch: channel number
+ * @flags: Keeps state of the channel (open/close, reading, writing)
+ * @free_msgs_list: List of free HSI messages/requests
+ * @rx_msgs_queue: List of pending RX requests
+ * @tx_msgs_queue: List of pending TX requests
+ * @lock: Serialize access to the lists
+ * @cl: reference to the associated hsi_client
+ * @cl_data: reference to the client data that this channels belongs to
+ * @rx_wait: RX requests wait queue
+ * @tx_wait: TX requests wait queue
+ */
+struct hsc_channel {
+ unsigned int ch;
+ unsigned long flags;
+ struct list_head free_msgs_list;
+ struct list_head rx_msgs_queue;
+ struct list_head tx_msgs_queue;
+ spinlock_t lock;
+ struct hsi_client *cl;
+ struct hsc_client_data *cl_data;
+ wait_queue_head_t rx_wait;
+ wait_queue_head_t tx_wait;
+};
+
+/**
+ * struct hsc_client_data - hsi_char internal client data
+ * @cdev: Characther device associated to the hsi_client
+ * @lock: Lock to serialize open/close access
+ * @flags: Keeps track of port state (rx hwbreak armed)
+ * @usecnt: Use count for claiming the HSI port (mutex protected)
+ * @cl: Referece to the HSI client
+ * @channels: Array of channels accessible by the client
+ */
+struct hsc_client_data {
+ struct cdev cdev;
+ struct mutex lock;
+ unsigned long flags;
+ unsigned int usecnt;
+ struct hsi_client *cl;
+ struct hsc_channel channels[HSC_DEVS];
+};
+
+/* Stores the major number dynamically allocated for hsi_char */
+static unsigned int hsc_major;
+/* Maximum buffer size that hsi_char will accept from userspace */
+static unsigned int max_data_size = 0x1000;
+module_param(max_data_size, uint, 0);
+MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
+
+static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
+ struct list_head *queue)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&channel->lock, flags);
+ list_add_tail(&msg->link, queue);
+ spin_unlock_irqrestore(&channel->lock, flags);
+}
+
+static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel,
+ struct list_head *queue)
+{
+ struct hsi_msg *msg = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&channel->lock, flags);
+
+ if (list_empty(queue))
+ goto out;
+
+ msg = list_first_entry(queue, struct hsi_msg, link);
+ list_del(&msg->link);
+out:
+ spin_unlock_irqrestore(&channel->lock, flags);
+
+ return msg;
+}
+
+static inline void hsc_msg_free(struct hsi_msg *msg)
+{
+ kfree(sg_virt(msg->sgt.sgl));
+ hsi_free_msg(msg);
+}
+
+static void hsc_free_list(struct list_head *list)
+{
+ struct hsi_msg *msg, *tmp;
+
+ list_for_each_entry_safe(msg, tmp, list, link) {
+ list_del(&msg->link);
+ hsc_msg_free(msg);
+ }
+}
+
+static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l)
+{
+ unsigned long flags;
+ LIST_HEAD(list);
+
+ spin_lock_irqsave(&channel->lock, flags);
+ list_splice_init(l, &list);
+ spin_unlock_irqrestore(&channel->lock, flags);
+
+ hsc_free_list(&list);
+}
+
+static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)
+{
+ struct hsi_msg *msg;
+ void *buf;
+
+ msg = hsi_alloc_msg(1, GFP_KERNEL);
+ if (!msg)
+ goto out;
+ buf = kmalloc(alloc_size, GFP_KERNEL);
+ if (!buf) {
+ hsi_free_msg(msg);
+ goto out;
+ }
+ sg_init_one(msg->sgt.sgl, buf, alloc_size);
+ /* Ignore false positive, due to sg pointer handling */
+ kmemleak_ignore(buf);
+
+ return msg;
+out:
+ return NULL;
+}
+
+static inline int hsc_msgs_alloc(struct hsc_channel *channel)
+{
+ struct hsi_msg *msg;
+ int i;
+
+ for (i = 0; i < HSC_MSGS; i++) {
+ msg = hsc_msg_alloc(max_data_size);
+ if (!msg)
+ goto out;
+ msg->channel = channel->ch;
+ list_add_tail(&msg->link, &channel->free_msgs_list);
+ }
+
+ return 0;
+out:
+ hsc_free_list(&channel->free_msgs_list);
+
+ return -ENOMEM;
+}
+
+static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg)
+{
+ return msg->sgt.sgl->length;
+}
+
+static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len)
+{
+ msg->sgt.sgl->length = len;
+}
+
+static void hsc_rx_completed(struct hsi_msg *msg)
+{
+ struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+ struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+ if (test_bit(HSC_CH_READ, &channel->flags)) {
+ hsc_add_tail(channel, msg, &channel->rx_msgs_queue);
+ wake_up(&channel->rx_wait);
+ } else {
+ hsc_add_tail(channel, msg, &channel->free_msgs_list);
+ }
+}
+
+static void hsc_rx_msg_destructor(struct hsi_msg *msg)
+{
+ msg->status = HSI_STATUS_ERROR;
+ hsc_msg_len_set(msg, 0);
+ hsc_rx_completed(msg);
+}
+
+static void hsc_tx_completed(struct hsi_msg *msg)
+{
+ struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+ struct hsc_channel *channel = cl_data->channels + msg->channel;
+
+ if (test_bit(HSC_CH_WRITE, &channel->flags)) {
+ hsc_add_tail(channel, msg, &channel->tx_msgs_queue);
+ wake_up(&channel->tx_wait);
+ } else {
+ hsc_add_tail(channel, msg, &channel->free_msgs_list);
+ }
+}
+
+static void hsc_tx_msg_destructor(struct hsi_msg *msg)
+{
+ msg->status = HSI_STATUS_ERROR;
+ hsc_msg_len_set(msg, 0);
+ hsc_tx_completed(msg);
+}
+
+static void hsc_break_req_destructor(struct hsi_msg *msg)
+{
+ struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+
+ hsi_free_msg(msg);
+ clear_bit(HSC_RXBREAK, &cl_data->flags);
+}
+
+static void hsc_break_received(struct hsi_msg *msg)
+{
+ struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
+ struct hsc_channel *channel = cl_data->channels;
+ int i, ret;
+
+ /* Broadcast HWBREAK on all channels */
+ for (i = 0; i < HSC_DEVS; i++, channel++) {
+ struct hsi_msg *msg2;
+
+ if (!test_bit(HSC_CH_READ, &channel->flags))
+ continue;
+ msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list);
+ if (!msg2)
+ continue;
+ clear_bit(HSC_CH_READ, &channel->flags);
+ hsc_msg_len_set(msg2, 0);
+ msg2->status = HSI_STATUS_COMPLETED;
+ hsc_add_tail(channel, msg2, &channel->rx_msgs_queue);
+ wake_up(&channel->rx_wait);
+ }
+ hsi_flush(msg->cl);
+ ret = hsi_async_read(msg->cl, msg);
+ if (ret < 0)
+ hsc_break_req_destructor(msg);
+}
+
+static int hsc_break_request(struct hsi_client *cl)
+{
+ struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+ struct hsi_msg *msg;
+ int ret;
+
+ if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags))
+ return -EBUSY;
+
+ msg = hsi_alloc_msg(0, GFP_KERNEL);
+ if (!msg) {
+ clear_bit(HSC_RXBREAK, &cl_data->flags);
+ return -ENOMEM;
+ }
+ msg->break_frame = 1;
+ msg->complete = hsc_break_received;
+ msg->destructor = hsc_break_req_destructor;
+ ret = hsi_async_read(cl, msg);
+ if (ret < 0)
+ hsc_break_req_destructor(msg);
+
+ return ret;
+}
+
+static int hsc_break_send(struct hsi_client *cl)
+{
+ struct hsi_msg *msg;
+ int ret;
+
+ msg = hsi_alloc_msg(0, GFP_ATOMIC);
+ if (!msg)
+ return -ENOMEM;
+ msg->break_frame = 1;
+ msg->complete = hsi_free_msg;
+ msg->destructor = hsi_free_msg;
+ ret = hsi_async_write(cl, msg);
+ if (ret < 0)
+ hsi_free_msg(msg);
+
+ return ret;
+}
+
+static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+ struct hsi_config tmp;
+ int ret;
+
+ if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME))
+ return -EINVAL;
+ if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS))
+ return -EINVAL;
+ if (rxc->channels & (rxc->channels - 1))
+ return -EINVAL;
+ if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE))
+ return -EINVAL;
+ tmp = cl->rx_cfg;
+ cl->rx_cfg.mode = rxc->mode;
+ cl->rx_cfg.channels = rxc->channels;
+ cl->rx_cfg.flow = rxc->flow;
+ ret = hsi_setup(cl);
+ if (ret < 0) {
+ cl->rx_cfg = tmp;
+ return ret;
+ }
+ if (rxc->mode == HSI_MODE_FRAME)
+ hsc_break_request(cl);
+
+ return ret;
+}
+
+static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
+{
+ rxc->mode = cl->rx_cfg.mode;
+ rxc->channels = cl->rx_cfg.channels;
+ rxc->flow = cl->rx_cfg.flow;
+}
+
+static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+ struct hsi_config tmp;
+ int ret;
+
+ if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME))
+ return -EINVAL;
+ if ((txc->channels == 0) || (txc->channels > HSC_DEVS))
+ return -EINVAL;
+ if (txc->channels & (txc->channels - 1))
+ return -EINVAL;
+ if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO))
+ return -EINVAL;
+ tmp = cl->tx_cfg;
+ cl->tx_cfg.mode = txc->mode;
+ cl->tx_cfg.channels = txc->channels;
+ cl->tx_cfg.speed = txc->speed;
+ cl->tx_cfg.arb_mode = txc->arb_mode;
+ ret = hsi_setup(cl);
+ if (ret < 0) {
+ cl->tx_cfg = tmp;
+ return ret;
+ }
+
+ return ret;
+}
+
+static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
+{
+ txc->mode = cl->tx_cfg.mode;
+ txc->channels = cl->tx_cfg.channels;
+ txc->speed = cl->tx_cfg.speed;
+ txc->arb_mode = cl->tx_cfg.arb_mode;
+}
+
+static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos __maybe_unused)
+{
+ struct hsc_channel *channel = file->private_data;
+ struct hsi_msg *msg;
+ ssize_t ret;
+
+ if (len == 0)
+ return 0;
+ if (!IS_ALIGNED(len, sizeof(u32)))
+ return -EINVAL;
+ if (len > max_data_size)
+ len = max_data_size;
+ if (channel->ch >= channel->cl->rx_cfg.channels)
+ return -ECHRNG;
+ if (test_and_set_bit(HSC_CH_READ, &channel->flags))
+ return -EBUSY;
+ msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+ if (!msg) {
+ ret = -ENOSPC;
+ goto out;
+ }
+ hsc_msg_len_set(msg, len);
+ msg->complete = hsc_rx_completed;
+ msg->destructor = hsc_rx_msg_destructor;
+ ret = hsi_async_read(channel->cl, msg);
+ if (ret < 0) {
+ hsc_add_tail(channel, msg, &channel->free_msgs_list);
+ goto out;
+ }
+
+ ret = wait_event_interruptible(channel->rx_wait,
+ !list_empty(&channel->rx_msgs_queue));
+ if (ret < 0) {
+ clear_bit(HSC_CH_READ, &channel->flags);
+ hsi_flush(channel->cl);
+ return -EINTR;
+ }
+
+ msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
+ if (msg) {
+ if (msg->status != HSI_STATUS_ERROR) {
+ ret = copy_to_user((void __user *)buf,
+ sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
+ if (ret)
+ ret = -EFAULT;
+ else
+ ret = hsc_msg_len_get(msg);
+ } else {
+ ret = -EIO;
+ }
+ hsc_add_tail(channel, msg, &channel->free_msgs_list);
+ }
+out:
+ clear_bit(HSC_CH_READ, &channel->flags);
+
+ return ret;
+}
+
+static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
+ loff_t *ppos __maybe_unused)
+{
+ struct hsc_channel *channel = file->private_data;
+ struct hsi_msg *msg;
+ ssize_t ret;
+
+ if ((len == 0) || !IS_ALIGNED(len, sizeof(u32)))
+ return -EINVAL;
+ if (len > max_data_size)
+ len = max_data_size;
+ if (channel->ch >= channel->cl->tx_cfg.channels)
+ return -ECHRNG;
+ if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
+ return -EBUSY;
+ msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
+ if (!msg) {
+ clear_bit(HSC_CH_WRITE, &channel->flags);
+ return -ENOSPC;
+ }
+ if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ hsc_msg_len_set(msg, len);
+ msg->complete = hsc_tx_completed;
+ msg->destructor = hsc_tx_msg_destructor;
+ ret = hsi_async_write(channel->cl, msg);
+ if (ret < 0)
+ goto out;
+
+ ret = wait_event_interruptible(channel->tx_wait,
+ !list_empty(&channel->tx_msgs_queue));
+ if (ret < 0) {
+ clear_bit(HSC_CH_WRITE, &channel->flags);
+ hsi_flush(channel->cl);
+ return -EINTR;
+ }
+
+ msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue);
+ if (msg) {
+ if (msg->status == HSI_STATUS_ERROR)
+ ret = -EIO;
+ else
+ ret = hsc_msg_len_get(msg);
+
+ hsc_add_tail(channel, msg, &channel->free_msgs_list);
+ }
+out:
+ clear_bit(HSC_CH_WRITE, &channel->flags);
+
+ return ret;
+}
+
+static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hsc_channel *channel = file->private_data;
+ unsigned int state;
+ struct hsc_rx_config rxc;
+ struct hsc_tx_config txc;
+ long ret = 0;
+
+ switch (cmd) {
+ case HSC_RESET:
+ hsi_flush(channel->cl);
+ break;
+ case HSC_SET_PM:
+ if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
+ return -EFAULT;
+ if (state == HSC_PM_DISABLE) {
+ if (test_and_set_bit(HSC_CH_WLINE, &channel->flags))
+ return -EINVAL;
+ ret = hsi_start_tx(channel->cl);
+ } else if (state == HSC_PM_ENABLE) {
+ if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+ return -EINVAL;
+ ret = hsi_stop_tx(channel->cl);
+ } else {
+ ret = -EINVAL;
+ }
+ break;
+ case HSC_SEND_BREAK:
+ return hsc_break_send(channel->cl);
+ case HSC_SET_RX:
+ if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc)))
+ return -EFAULT;
+ return hsc_rx_set(channel->cl, &rxc);
+ case HSC_GET_RX:
+ hsc_rx_get(channel->cl, &rxc);
+ if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc)))
+ return -EFAULT;
+ break;
+ case HSC_SET_TX:
+ if (copy_from_user(&txc, (void __user *)arg, sizeof(txc)))
+ return -EFAULT;
+ return hsc_tx_set(channel->cl, &txc);
+ case HSC_GET_TX:
+ hsc_tx_get(channel->cl, &txc);
+ if (copy_to_user((void __user *)arg, &txc, sizeof(txc)))
+ return -EFAULT;
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return ret;
+}
+
+static inline void __hsc_port_release(struct hsc_client_data *cl_data)
+{
+ BUG_ON(cl_data->usecnt == 0);
+
+ if (--cl_data->usecnt == 0) {
+ hsi_flush(cl_data->cl);
+ hsi_release_port(cl_data->cl);
+ }
+}
+
+static int hsc_open(struct inode *inode, struct file *file)
+{
+ struct hsc_client_data *cl_data;
+ struct hsc_channel *channel;
+ int ret = 0;
+
+ pr_debug("open, minor = %d\n", iminor(inode));
+
+ cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev);
+ mutex_lock(&cl_data->lock);
+ channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK);
+
+ if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ /*
+ * Check if we have already claimed the port associated to the HSI
+ * client. If not then try to claim it, else increase its refcount
+ */
+ if (cl_data->usecnt == 0) {
+ ret = hsi_claim_port(cl_data->cl, 0);
+ if (ret < 0)
+ goto out;
+ hsi_setup(cl_data->cl);
+ }
+ cl_data->usecnt++;
+
+ ret = hsc_msgs_alloc(channel);
+ if (ret < 0) {
+ __hsc_port_release(cl_data);
+ goto out;
+ }
+
+ file->private_data = channel;
+ mutex_unlock(&cl_data->lock);
+
+ return ret;
+out:
+ mutex_unlock(&cl_data->lock);
+
+ return ret;
+}
+
+static int hsc_release(struct inode *inode __maybe_unused, struct file *file)
+{
+ struct hsc_channel *channel = file->private_data;
+ struct hsc_client_data *cl_data = channel->cl_data;
+
+ mutex_lock(&cl_data->lock);
+ file->private_data = NULL;
+ if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
+ hsi_stop_tx(channel->cl);
+ __hsc_port_release(cl_data);
+ hsc_reset_list(channel, &channel->rx_msgs_queue);
+ hsc_reset_list(channel, &channel->tx_msgs_queue);
+ hsc_reset_list(channel, &channel->free_msgs_list);
+ clear_bit(HSC_CH_READ, &channel->flags);
+ clear_bit(HSC_CH_WRITE, &channel->flags);
+ clear_bit(HSC_CH_OPEN, &channel->flags);
+ wake_up(&channel->rx_wait);
+ wake_up(&channel->tx_wait);
+ mutex_unlock(&cl_data->lock);
+
+ return 0;
+}
+
+static const struct file_operations hsc_fops = {
+ .owner = THIS_MODULE,
+ .read = hsc_read,
+ .write = hsc_write,
+ .unlocked_ioctl = hsc_ioctl,
+ .open = hsc_open,
+ .release = hsc_release,
+};
+
+static void __devinit hsc_channel_init(struct hsc_channel *channel)
+{
+ init_waitqueue_head(&channel->rx_wait);
+ init_waitqueue_head(&channel->tx_wait);
+ spin_lock_init(&channel->lock);
+ INIT_LIST_HEAD(&channel->free_msgs_list);
+ INIT_LIST_HEAD(&channel->rx_msgs_queue);
+ INIT_LIST_HEAD(&channel->tx_msgs_queue);
+}
+
+static int __devinit hsc_probe(struct device *dev)
+{
+ const char devname[] = "hsi_char";
+ struct hsc_client_data *cl_data;
+ struct hsc_channel *channel;
+ struct hsi_client *cl = to_hsi_client(dev);
+ unsigned int hsc_baseminor;
+ dev_t hsc_dev;
+ int ret;
+ int i;
+
+ cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
+ if (!cl_data) {
+ dev_err(dev, "Could not allocate hsc_client_data\n");
+ return -ENOMEM;
+ }
+ hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
+ if (!hsc_major) {
+ ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
+ HSC_DEVS, devname);
+ if (ret > 0)
+ hsc_major = MAJOR(hsc_dev);
+ } else {
+ hsc_dev = MKDEV(hsc_major, hsc_baseminor);
+ ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
+ }
+ if (ret < 0) {
+ dev_err(dev, "Device %s allocation failed %d\n",
+ hsc_major ? "minor" : "major", ret);
+ goto out1;
+ }
+ mutex_init(&cl_data->lock);
+ hsi_client_set_drvdata(cl, cl_data);
+ cdev_init(&cl_data->cdev, &hsc_fops);
+ cl_data->cdev.owner = THIS_MODULE;
+ cl_data->cl = cl;
+ for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
+ hsc_channel_init(channel);
+ channel->ch = i;
+ channel->cl = cl;
+ channel->cl_data = cl_data;
+ }
+
+ /* 1 hsi client -> N char devices (one for each channel) */
+ ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
+ if (ret) {
+ dev_err(dev, "Could not add char device %d\n", ret);
+ goto out2;
+ }
+
+ return 0;
+out2:
+ unregister_chrdev_region(hsc_dev, HSC_DEVS);
+out1:
+ kfree(cl_data);
+
+ return ret;
+}
+
+static int __devexit hsc_remove(struct device *dev)
+{
+ struct hsi_client *cl = to_hsi_client(dev);
+ struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
+ dev_t hsc_dev = cl_data->cdev.dev;
+
+ cdev_del(&cl_data->cdev);
+ unregister_chrdev_region(hsc_dev, HSC_DEVS);
+ hsi_client_set_drvdata(cl, NULL);
+ kfree(cl_data);
+
+ return 0;
+}
+
+static struct hsi_client_driver hsc_driver = {
+ .driver = {
+ .name = "hsi_char",
+ .owner = THIS_MODULE,
+ .probe = hsc_probe,
+ .remove = __devexit_p(hsc_remove),
+ },
+};
+
+static int __init hsc_init(void)
+{
+ int ret;
+
+ if ((max_data_size < 4) || (max_data_size > 0x10000) ||
+ (max_data_size & (max_data_size - 1))) {
+ pr_err("Invalid max read/write data size");
+ return -EINVAL;
+ }
+
+ ret = hsi_register_client_driver(&hsc_driver);
+ if (ret) {
+ pr_err("Error while registering HSI/SSI driver %d", ret);
+ return ret;
+ }
+
+ pr_info("HSI/SSI char device loaded\n");
+
+ return 0;
+}
+module_init(hsc_init);
+
+static void __exit hsc_exit(void)
+{
+ hsi_unregister_client_driver(&hsc_driver);
+ pr_info("HSI char device removed\n");
+}
+module_exit(hsc_exit);
+
+MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
+MODULE_ALIAS("hsi:hsi_char");
+MODULE_DESCRIPTION("HSI character device");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c
new file mode 100644
index 0000000..2d58f93
--- /dev/null
+++ b/drivers/hsi/hsi.c
@@ -0,0 +1,507 @@
+/*
+ * HSI core.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/compiler.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include "hsi_core.h"
+
+static ssize_t modalias_show(struct device *dev,
+ struct device_attribute *a __maybe_unused, char *buf)
+{
+ return sprintf(buf, "hsi:%s\n", dev_name(dev));
+}
+
+static struct device_attribute hsi_bus_dev_attrs[] = {
+ __ATTR_RO(modalias),
+ __ATTR_NULL,
+};
+
+static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev));
+
+ return 0;
+}
+
+static int hsi_bus_match(struct device *dev, struct device_driver *driver)
+{
+ return strcmp(dev_name(dev), driver->name) == 0;
+}
+
+static struct bus_type hsi_bus_type = {
+ .name = "hsi",
+ .dev_attrs = hsi_bus_dev_attrs,
+ .match = hsi_bus_match,
+ .uevent = hsi_bus_uevent,
+};
+
+static void hsi_client_release(struct device *dev)
+{
+ kfree(to_hsi_client(dev));
+}
+
+static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info)
+{
+ struct hsi_client *cl;
+
+ cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+ if (!cl)
+ return;
+ cl->tx_cfg = info->tx_cfg;
+ cl->rx_cfg = info->rx_cfg;
+ cl->device.bus = &hsi_bus_type;
+ cl->device.parent = &port->device;
+ cl->device.release = hsi_client_release;
+ dev_set_name(&cl->device, info->name);
+ cl->device.platform_data = info->platform_data;
+ if (info->archdata)
+ cl->device.archdata = *info->archdata;
+ if (device_register(&cl->device) < 0) {
+ pr_err("hsi: failed to register client: %s\n", info->name);
+ put_device(&cl->device);
+ }
+}
+
+static void hsi_scan_board_info(struct hsi_controller *hsi)
+{
+ struct hsi_cl_info *cl_info;
+ struct hsi_port *p;
+
+ list_for_each_entry(cl_info, &hsi_board_list, list)
+ if (cl_info->info.hsi_id == hsi->id) {
+ p = hsi_find_port_num(hsi, cl_info->info.port);
+ if (!p)
+ continue;
+ hsi_new_client(p, &cl_info->info);
+ }
+}
+
+static int hsi_remove_client(struct device *dev, void *data __maybe_unused)
+{
+ device_unregister(dev);
+
+ return 0;
+}
+
+static int hsi_remove_port(struct device *dev, void *data __maybe_unused)
+{
+ device_for_each_child(dev, NULL, hsi_remove_client);
+ device_unregister(dev);
+
+ return 0;
+}
+
+static void hsi_controller_release(struct device *dev)
+{
+ struct hsi_controller *hsi = to_hsi_controller(dev);
+
+ kfree(hsi->port);
+ kfree(hsi);
+}
+
+static void hsi_port_release(struct device *dev)
+{
+ kfree(to_hsi_port(dev));
+}
+
+/**
+ * hsi_unregister_controller - Unregister an HSI controller
+ * @hsi: The HSI controller to register
+ */
+void hsi_unregister_controller(struct hsi_controller *hsi)
+{
+ device_for_each_child(&hsi->device, NULL, hsi_remove_port);
+ device_unregister(&hsi->device);
+}
+EXPORT_SYMBOL_GPL(hsi_unregister_controller);
+
+/**
+ * hsi_register_controller - Register an HSI controller and its ports
+ * @hsi: The HSI controller to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_controller(struct hsi_controller *hsi)
+{
+ unsigned int i;
+ int err;
+
+ err = device_add(&hsi->device);
+ if (err < 0)
+ return err;
+ for (i = 0; i < hsi->num_ports; i++) {
+ hsi->port[i]->device.parent = &hsi->device;
+ err = device_add(&hsi->port[i]->device);
+ if (err < 0)
+ goto out;
+ }
+ /* Populate HSI bus with HSI clients */
+ hsi_scan_board_info(hsi);
+
+ return 0;
+out:
+ while (i-- > 0)
+ device_del(&hsi->port[i]->device);
+ device_del(&hsi->device);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(hsi_register_controller);
+
+/**
+ * hsi_register_client_driver - Register an HSI client to the HSI bus
+ * @drv: HSI client driver to register
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_register_client_driver(struct hsi_client_driver *drv)
+{
+ drv->driver.bus = &hsi_bus_type;
+
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(hsi_register_client_driver);
+
+static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused)
+{
+ return 0;
+}
+
+static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused)
+{
+ return 0;
+}
+
+/**
+ * hsi_put_controller - Free an HSI controller
+ *
+ * @hsi: Pointer to the HSI controller to freed
+ *
+ * HSI controller drivers should only use this function if they need
+ * to free their allocated hsi_controller structures before a successful
+ * call to hsi_register_controller. Other use is not allowed.
+ */
+void hsi_put_controller(struct hsi_controller *hsi)
+{
+ unsigned int i;
+
+ if (!hsi)
+ return;
+
+ for (i = 0; i < hsi->num_ports; i++)
+ if (hsi->port && hsi->port[i])
+ put_device(&hsi->port[i]->device);
+ put_device(&hsi->device);
+}
+EXPORT_SYMBOL_GPL(hsi_put_controller);
+
+/**
+ * hsi_alloc_controller - Allocate an HSI controller and its ports
+ * @n_ports: Number of ports on the HSI controller
+ * @flags: Kernel allocation flags
+ *
+ * Return NULL on failure or a pointer to an hsi_controller on success.
+ */
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags)
+{
+ struct hsi_controller *hsi;
+ struct hsi_port **port;
+ unsigned int i;
+
+ if (!n_ports)
+ return NULL;
+
+ hsi = kzalloc(sizeof(*hsi), flags);
+ if (!hsi)
+ return NULL;
+ port = kzalloc(sizeof(*port)*n_ports, flags);
+ if (!port) {
+ kfree(hsi);
+ return NULL;
+ }
+ hsi->num_ports = n_ports;
+ hsi->port = port;
+ hsi->device.release = hsi_controller_release;
+ device_initialize(&hsi->device);
+
+ for (i = 0; i < n_ports; i++) {
+ port[i] = kzalloc(sizeof(**port), flags);
+ if (port[i] == NULL)
+ goto out;
+ port[i]->num = i;
+ port[i]->async = hsi_dummy_msg;
+ port[i]->setup = hsi_dummy_cl;
+ port[i]->flush = hsi_dummy_cl;
+ port[i]->start_tx = hsi_dummy_cl;
+ port[i]->stop_tx = hsi_dummy_cl;
+ port[i]->release = hsi_dummy_cl;
+ mutex_init(&port[i]->lock);
+ ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head);
+ dev_set_name(&port[i]->device, "port%d", i);
+ hsi->port[i]->device.release = hsi_port_release;
+ device_initialize(&hsi->port[i]->device);
+ }
+
+ return hsi;
+out:
+ hsi_put_controller(hsi);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_controller);
+
+/**
+ * hsi_free_msg - Free an HSI message
+ * @msg: Pointer to the HSI message
+ *
+ * Client is responsible to free the buffers pointed by the scatterlists.
+ */
+void hsi_free_msg(struct hsi_msg *msg)
+{
+ if (!msg)
+ return;
+ sg_free_table(&msg->sgt);
+ kfree(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_free_msg);
+
+/**
+ * hsi_alloc_msg - Allocate an HSI message
+ * @nents: Number of memory entries
+ * @flags: Kernel allocation flags
+ *
+ * nents can be 0. This mainly makes sense for read transfer.
+ * In that case, HSI drivers will call the complete callback when
+ * there is data to be read without consuming it.
+ *
+ * Return NULL on failure or a pointer to an hsi_msg on success.
+ */
+struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags)
+{
+ struct hsi_msg *msg;
+ int err;
+
+ msg = kzalloc(sizeof(*msg), flags);
+ if (!msg)
+ return NULL;
+
+ if (!nents)
+ return msg;
+
+ err = sg_alloc_table(&msg->sgt, nents, flags);
+ if (unlikely(err)) {
+ kfree(msg);
+ msg = NULL;
+ }
+
+ return msg;
+}
+EXPORT_SYMBOL_GPL(hsi_alloc_msg);
+
+/**
+ * hsi_async - Submit an HSI transfer to the controller
+ * @cl: HSI client sending the transfer
+ * @msg: The HSI transfer passed to controller
+ *
+ * The HSI message must have the channel, ttype, complete and destructor
+ * fields set beforehand. If nents > 0 then the client has to initialize
+ * also the scatterlists to point to the buffers to write to or read from.
+ *
+ * HSI controllers relay on pre-allocated buffers from their clients and they
+ * do not allocate buffers on their own.
+ *
+ * Once the HSI message transfer finishes, the HSI controller calls the
+ * complete callback with the status and actual_len fields of the HSI message
+ * updated. The complete callback can be called before returning from
+ * hsi_async.
+ *
+ * Returns -errno on failure or 0 on success
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+
+ WARN_ON_ONCE(!msg->destructor || !msg->complete);
+ msg->cl = cl;
+
+ return port->async(msg);
+}
+EXPORT_SYMBOL_GPL(hsi_async);
+
+/**
+ * hsi_claim_port - Claim the HSI client's port
+ * @cl: HSI client that wants to claim its port
+ * @share: Flag to indicate if the client wants to share the port or not.
+ *
+ * Returns -errno on failure, 0 on success.
+ */
+int hsi_claim_port(struct hsi_client *cl, unsigned int share)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ int err = 0;
+
+ mutex_lock(&port->lock);
+ if ((port->claimed) && (!port->shared || !share)) {
+ err = -EBUSY;
+ goto out;
+ }
+ if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) {
+ err = -ENODEV;
+ goto out;
+ }
+ port->claimed++;
+ port->shared = !!share;
+ cl->pclaimed = 1;
+out:
+ mutex_unlock(&port->lock);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(hsi_claim_port);
+
+/**
+ * hsi_release_port - Release the HSI client's port
+ * @cl: HSI client which previously claimed its port
+ */
+void hsi_release_port(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+
+ mutex_lock(&port->lock);
+ /* Allow HW driver to do some cleanup */
+ port->release(cl);
+ if (cl->pclaimed)
+ port->claimed--;
+ BUG_ON(port->claimed < 0);
+ cl->pclaimed = 0;
+ if (!port->claimed)
+ port->shared = 0;
+ module_put(to_hsi_controller(port->device.parent)->owner);
+ mutex_unlock(&port->lock);
+}
+EXPORT_SYMBOL_GPL(hsi_release_port);
+
+static int hsi_event_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *data __maybe_unused)
+{
+ struct hsi_client *cl = container_of(nb, struct hsi_client, nb);
+
+ (*cl->ehandler)(cl, event);
+
+ return 0;
+}
+
+/**
+ * hsi_register_port_event - Register a client to receive port events
+ * @cl: HSI client that wants to receive port events
+ * @cb: Event handler callback
+ *
+ * Clients should register a callback to be able to receive
+ * events from the ports. Registration should happen after
+ * claiming the port.
+ * The handler can be called in interrupt context.
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_register_port_event(struct hsi_client *cl,
+ void (*handler)(struct hsi_client *, unsigned long))
+{
+ struct hsi_port *port = hsi_get_port(cl);
+
+ if (!handler || cl->ehandler)
+ return -EINVAL;
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+ cl->ehandler = handler;
+ cl->nb.notifier_call = hsi_event_notifier_call;
+
+ return atomic_notifier_chain_register(&port->n_head, &cl->nb);
+}
+EXPORT_SYMBOL_GPL(hsi_register_port_event);
+
+/**
+ * hsi_unregister_port_event - Stop receiving port events for a client
+ * @cl: HSI client that wants to stop receiving port events
+ *
+ * Clients should call this function before releasing their associated
+ * port.
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_unregister_port_event(struct hsi_client *cl)
+{
+ struct hsi_port *port = hsi_get_port(cl);
+ int err;
+
+ WARN_ON(!hsi_port_claimed(cl));
+
+ err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb);
+ if (!err)
+ cl->ehandler = NULL;
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(hsi_unregister_port_event);
+
+/**
+ * hsi_event -Notifies clients about port events
+ * @port: Port where the event occurred
+ * @event: The event type
+ *
+ * Clients should not be concerned about wake line behavior. However, due
+ * to a race condition in HSI HW protocol, clients need to be notified
+ * about wake line changes, so they can implement a workaround for it.
+ *
+ * Events:
+ * HSI_EVENT_START_RX - Incoming wake line high
+ * HSI_EVENT_STOP_RX - Incoming wake line down
+ *
+ * Returns -errno on error, or 0 on success.
+ */
+int hsi_event(struct hsi_port *port, unsigned long event)
+{
+ return atomic_notifier_call_chain(&port->n_head, event, NULL);
+}
+EXPORT_SYMBOL_GPL(hsi_event);
+
+static int __init hsi_init(void)
+{
+ return bus_register(&hsi_bus_type);
+}
+postcore_initcall(hsi_init);
+
+static void __exit hsi_exit(void)
+{
+ bus_unregister(&hsi_bus_type);
+}
+module_exit(hsi_exit);
+
+MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
+MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hsi/hsi_boardinfo.c b/drivers/hsi/hsi_boardinfo.c
new file mode 100644
index 0000000..e56bc6d
--- /dev/null
+++ b/drivers/hsi/hsi_boardinfo.c
@@ -0,0 +1,62 @@
+/*
+ * HSI clients registration interface
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include <linux/hsi/hsi.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "hsi_core.h"
+
+/*
+ * hsi_board_list is only used internally by the HSI framework.
+ * No one else is allowed to make use of it.
+ */
+LIST_HEAD(hsi_board_list);
+EXPORT_SYMBOL_GPL(hsi_board_list);
+
+/**
+ * hsi_register_board_info - Register HSI clients information
+ * @info: Array of HSI clients on the board
+ * @len: Length of the array
+ *
+ * HSI clients are statically declared and registered on board files.
+ *
+ * HSI clients will be automatically registered to the HSI bus once the
+ * controller and the port where the clients wishes to attach are registered
+ * to it.
+ *
+ * Return -errno on failure, 0 on success.
+ */
+int __init hsi_register_board_info(struct hsi_board_info const *info,
+ unsigned int len)
+{
+ struct hsi_cl_info *cl_info;
+
+ cl_info = kzalloc(sizeof(*cl_info) * len, GFP_KERNEL);
+ if (!cl_info)
+ return -ENOMEM;
+
+ for (; len; len--, info++, cl_info++) {
+ cl_info->info = *info;
+ list_add_tail(&cl_info->list, &hsi_board_list);
+ }
+
+ return 0;
+}
diff --git a/drivers/hsi/hsi_core.h b/drivers/hsi/hsi_core.h
new file mode 100644
index 0000000..ab5c2fb
--- /dev/null
+++ b/drivers/hsi/hsi_core.h
@@ -0,0 +1,35 @@
+/*
+ * HSI framework internal interfaces,
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_CORE_H__
+#define __LINUX_HSI_CORE_H__
+
+#include <linux/hsi/hsi.h>
+
+struct hsi_cl_info {
+ struct list_head list;
+ struct hsi_board_info info;
+};
+
+extern struct list_head hsi_board_list;
+
+#endif /* __LINUX_HSI_CORE_H__ */
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5b32d56..8deedc1 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -253,7 +253,8 @@
If you say yes here you get support for the temperature
sensor(s) inside your CPU. Supported are later revisions of
the AMD Family 10h and all revisions of the AMD Family 11h,
- 12h (Llano), 14h (Brazos) and 15h (Bulldozer) microarchitectures.
+ 12h (Llano), 14h (Brazos) and 15h (Bulldozer/Trinity)
+ microarchitectures.
This driver can also be built as a module. If so, the module
will be called k10temp.
@@ -425,7 +426,7 @@
config SENSORS_GPIO_FAN
tristate "GPIO fan"
- depends on GENERIC_GPIO
+ depends on GPIOLIB
help
If you say yes here you get support for fans connected to GPIO lines.
@@ -883,7 +884,7 @@
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
- depends on GENERIC_GPIO
+ depends on GPIOLIB
help
If you say yes here you get support for the Sensiron SHT10, SHT11,
SHT15, SHT71, SHT75 humidity and temperature sensors.
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 554f046..9140236 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -391,6 +391,7 @@
break;
default:
BUG();
+ val = "";
}
return sprintf(buf, "%s\n", val);
@@ -632,6 +633,7 @@
sensors->dev_attr.show = ro->show;
sensors->index = ro->index;
+ sysfs_attr_init(&sensors->dev_attr.attr);
res = device_create_file(dev, &sensors->dev_attr);
if (res) {
sensors->dev_attr.attr.name = NULL;
@@ -661,6 +663,7 @@
sensors->dev_attr.store = rw->set;
sensors->index = rw->index;
+ sysfs_attr_init(&sensors->dev_attr.attr);
res = device_create_file(dev, &sensors->dev_attr);
if (res) {
sensors->dev_attr.attr.name = NULL;
diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c
index 0e0cfcc..f85ce70 100644
--- a/drivers/hwmon/ad7314.c
+++ b/drivers/hwmon/ad7314.c
@@ -47,7 +47,7 @@
u16 rx ____cacheline_aligned;
};
-static int ad7314_spi_read(struct ad7314_data *chip, s16 *data)
+static int ad7314_spi_read(struct ad7314_data *chip)
{
int ret;
@@ -57,9 +57,7 @@
return ret;
}
- *data = be16_to_cpu(chip->rx);
-
- return ret;
+ return be16_to_cpu(chip->rx);
}
static ssize_t ad7314_show_temperature(struct device *dev,
@@ -70,12 +68,12 @@
s16 data;
int ret;
- ret = ad7314_spi_read(chip, &data);
+ ret = ad7314_spi_read(chip);
if (ret < 0)
return ret;
switch (spi_get_device_id(chip->spi_dev)->driver_data) {
case ad7314:
- data = (data & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
+ data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET;
data = (data << 6) >> 6;
return sprintf(buf, "%d\n", 250 * data);
@@ -86,7 +84,7 @@
* with a sign bit - which is a 14 bit 2's complement
* register. 1lsb - 31.25 milli degrees centigrade
*/
- data &= ADT7301_TEMP_MASK;
+ data = ret & ADT7301_TEMP_MASK;
data = (data << 2) >> 2;
return sprintf(buf, "%d\n",
@@ -128,6 +126,7 @@
ret = PTR_ERR(chip->hwmon_dev);
goto error_remove_group;
}
+ chip->spi_dev = spi_dev;
return 0;
error_remove_group:
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c
index ff37363..44e1fd7 100644
--- a/drivers/hwmon/adm1031.c
+++ b/drivers/hwmon/adm1031.c
@@ -233,18 +233,15 @@
* nearest match if no exact match where found.
*/
static int
-get_fan_auto_nearest(struct adm1031_data *data,
- int chan, u8 val, u8 reg, u8 *new_reg)
+get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg)
{
int i;
int first_match = -1, exact_match = -1;
u8 other_reg_val =
(*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1];
- if (val == 0) {
- *new_reg = 0;
+ if (val == 0)
return 0;
- }
for (i = 0; i < 8; i++) {
if ((val == (*data->chan_select_table)[i][chan]) &&
@@ -264,13 +261,11 @@
}
if (exact_match >= 0)
- *new_reg = exact_match;
+ return exact_match;
else if (first_match >= 0)
- *new_reg = first_match;
- else
- return -EINVAL;
+ return first_match;
- return 0;
+ return -EINVAL;
}
static ssize_t show_fan_auto_channel(struct device *dev,
@@ -301,11 +296,12 @@
mutex_lock(&data->update_lock);
- ret = get_fan_auto_nearest(data, nr, val, data->conf1, ®);
- if (ret) {
+ ret = get_fan_auto_nearest(data, nr, val, data->conf1);
+ if (ret < 0) {
mutex_unlock(&data->update_lock);
return ret;
}
+ reg = ret;
data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1);
if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^
(old_fan_mode & ADM1031_CONF1_AUTO_MODE)) {
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index 7765e4f..1958f03 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -59,14 +59,11 @@
struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
};
-static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
- int *value)
+static int ads1015_read_adc(struct i2c_client *client, unsigned int channel)
{
u16 config;
- s16 conversion;
struct ads1015_data *data = i2c_get_clientdata(client);
unsigned int pga = data->channel_data[channel].pga;
- int fullscale;
unsigned int data_rate = data->channel_data[channel].data_rate;
unsigned int conversion_time_ms;
int res;
@@ -78,7 +75,6 @@
if (res < 0)
goto err_unlock;
config = res;
- fullscale = fullscale_table[pga];
conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
/* setup and start single conversion */
@@ -105,33 +101,36 @@
}
res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION);
- if (res < 0)
- goto err_unlock;
- conversion = res;
-
- mutex_unlock(&data->update_lock);
-
- *value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
-
- return 0;
err_unlock:
mutex_unlock(&data->update_lock);
return res;
}
+static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel,
+ s16 reg)
+{
+ struct ads1015_data *data = i2c_get_clientdata(client);
+ unsigned int pga = data->channel_data[channel].pga;
+ int fullscale = fullscale_table[pga];
+
+ return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0);
+}
+
/* sysfs callback function */
static ssize_t show_in(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
- int in;
int res;
+ int index = attr->index;
- res = ads1015_read_value(client, attr->index, &in);
+ res = ads1015_read_adc(client, index);
+ if (res < 0)
+ return res;
- return (res < 0) ? res : sprintf(buf, "%d\n", in);
+ return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res));
}
static const struct sensor_device_attribute ads1015_in[] = {
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 0d3141f..b9d5123 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -52,7 +52,7 @@
MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
-#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */
+#define NUM_REAL_CORES 32 /* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */
#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1)
@@ -709,6 +709,10 @@
indx = TO_ATTR_NO(cpu);
+ /* The core id is too big, just return */
+ if (indx > MAX_CORE_DATA - 1)
+ return;
+
if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
coretemp_remove_core(pdata, &pdev->dev, indx);
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 729499e..ece4159 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -276,6 +276,7 @@
return false;
default:
BUG();
+ return true;
}
}
@@ -291,6 +292,7 @@
return true;
default:
BUG();
+ return false;
}
}
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index b7494af..e8e18ca 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -122,6 +122,41 @@
return true;
}
+/*
+ * Newer BKDG versions have an updated recommendation on how to properly
+ * initialize the running average range (was: 0xE, now: 0x9). This avoids
+ * counter saturations resulting in bogus power readings.
+ * We correct this value ourselves to cope with older BIOSes.
+ */
+static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+ { 0 }
+};
+
+static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+{
+ u32 val;
+
+ /*
+ * let this quirk apply only to the current version of the
+ * northbridge, since future versions may change the behavior
+ */
+ if (!pci_match_id(affected_device, pdev))
+ return;
+
+ pci_bus_read_config_dword(pdev->bus,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+ REG_TDP_RUNNING_AVERAGE, &val);
+ if ((val & 0xf) != 0xe)
+ return;
+
+ val &= ~0xf;
+ val |= 0x9;
+ pci_bus_write_config_dword(pdev->bus,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+ REG_TDP_RUNNING_AVERAGE, val);
+}
+
static void __devinit fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data)
{
@@ -155,6 +190,13 @@
struct device *dev;
int err;
+ /*
+ * though we ignore every other northbridge, we still have to
+ * do the tweaking on _each_ node in MCM processors as the counters
+ * are working hand-in-hand
+ */
+ tweak_runavg_range(pdev);
+
if (!fam15h_power_is_internal_node0(pdev)) {
err = -ENODEV;
goto exit;
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c
index aba29d6..307bb32 100644
--- a/drivers/hwmon/k10temp.c
+++ b/drivers/hwmon/k10temp.c
@@ -33,6 +33,9 @@
module_param(force, bool, 0444);
MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
+/* PCI-IDs for Northbridge devices not used anywhere else */
+#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3 0x1403
+
/* CPUID function 0x80000001, ebx */
#define CPUID_PKGTYPE_MASK 0xf0000000
#define CPUID_PKGTYPE_F 0x00000000
@@ -210,6 +213,7 @@
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) },
{}
};
MODULE_DEVICE_TABLE(pci, k10temp_id_table);
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index 193067e..de8f7ad 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -596,8 +596,10 @@
return 0;
}
-static int max6639_suspend(struct i2c_client *client, pm_message_t mesg)
+#ifdef CONFIG_PM_SLEEP
+static int max6639_suspend(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
if (data < 0)
return data;
@@ -606,8 +608,9 @@
MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY);
}
-static int max6639_resume(struct i2c_client *client)
+static int max6639_resume(struct device *dev)
{
+ struct i2c_client *client = to_i2c_client(dev);
int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
if (data < 0)
return data;
@@ -615,6 +618,7 @@
return i2c_smbus_write_byte_data(client,
MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY);
}
+#endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id max6639_id[] = {
{"max6639", 0},
@@ -623,15 +627,18 @@
MODULE_DEVICE_TABLE(i2c, max6639_id);
+static const struct dev_pm_ops max6639_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(max6639_suspend, max6639_resume)
+};
+
static struct i2c_driver max6639_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "max6639",
+ .pm = &max6639_pm_ops,
},
.probe = max6639_probe,
.remove = max6639_remove,
- .suspend = max6639_suspend,
- .resume = max6639_resume,
.id_table = max6639_id,
.detect = max6639_detect,
.address_list = normal_i2c,
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index be51037..29b319d 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -710,13 +710,13 @@
* If a negative value is stored in any of the referenced registers, this value
* reflects an error code which will be returned.
*/
-static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
+static int pmbus_get_boolean(struct pmbus_data *data, int index)
{
u8 s1 = (index >> 24) & 0xff;
u8 s2 = (index >> 16) & 0xff;
u8 reg = (index >> 8) & 0xff;
u8 mask = index & 0xff;
- int status;
+ int ret, status;
u8 regval;
status = data->status[reg];
@@ -725,7 +725,7 @@
regval = status & mask;
if (!s1 && !s2)
- *val = !!regval;
+ ret = !!regval;
else {
long v1, v2;
struct pmbus_sensor *sensor1, *sensor2;
@@ -739,9 +739,9 @@
v1 = pmbus_reg2data(data, sensor1);
v2 = pmbus_reg2data(data, sensor2);
- *val = !!(regval && v1 >= v2);
+ ret = !!(regval && v1 >= v2);
}
- return 0;
+ return ret;
}
static ssize_t pmbus_show_boolean(struct device *dev,
@@ -750,11 +750,10 @@
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct pmbus_data *data = pmbus_update_device(dev);
int val;
- int err;
- err = pmbus_get_boolean(data, attr->index, &val);
- if (err)
- return err;
+ val = pmbus_get_boolean(data, attr->index);
+ if (val < 0)
+ return val;
return snprintf(buf, PAGE_SIZE, "%d\n", val);
}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index d3b778d..c5f6be4 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -343,10 +343,11 @@
return err;
}
-static int __init smsc47b397_find(unsigned short *addr)
+static int __init smsc47b397_find(void)
{
u8 id, rev;
char *name;
+ unsigned short addr;
superio_enter();
id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
@@ -370,14 +371,14 @@
rev = superio_inb(SUPERIO_REG_DEVREV);
superio_select(SUPERIO_REG_LD8);
- *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
+ addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
| superio_inb(SUPERIO_REG_BASE_LSB);
pr_info("found SMSC %s (base address 0x%04x, revision %u)\n",
- name, *addr, rev);
+ name, addr, rev);
superio_exit();
- return 0;
+ return addr;
}
static int __init smsc47b397_init(void)
@@ -385,9 +386,10 @@
unsigned short address;
int ret;
- ret = smsc47b397_find(&address);
- if (ret)
+ ret = smsc47b397_find();
+ if (ret < 0)
return ret;
+ address = ret;
ret = platform_driver_register(&smsc47b397_driver);
if (ret)
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index c590c14..b5aa38d 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -491,10 +491,10 @@
.attrs = smsc47m1_attributes,
};
-static int __init smsc47m1_find(unsigned short *addr,
- struct smsc47m1_sio_data *sio_data)
+static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data)
{
u8 val;
+ unsigned short addr;
superio_enter();
val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
@@ -546,9 +546,9 @@
}
superio_select();
- *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+ addr = (superio_inb(SUPERIO_REG_BASE) << 8)
| superio_inb(SUPERIO_REG_BASE + 1);
- if (*addr == 0) {
+ if (addr == 0) {
pr_info("Device address not set, will not use\n");
superio_exit();
return -ENODEV;
@@ -565,7 +565,7 @@
}
superio_exit();
- return 0;
+ return addr;
}
/* Restore device to its initial state */
@@ -938,13 +938,15 @@
unsigned short address;
struct smsc47m1_sio_data sio_data;
- if (smsc47m1_find(&address, &sio_data))
- return -ENODEV;
+ err = smsc47m1_find(&sio_data);
+ if (err < 0)
+ return err;
+ address = err;
/* Sets global pdev as a side effect */
err = smsc47m1_device_add(address, &sio_data);
if (err)
- goto exit;
+ return err;
err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe);
if (err)
@@ -955,7 +957,6 @@
exit_device:
platform_device_unregister(pdev);
smsc47m1_restore(&sio_data);
-exit:
return err;
}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index a25350c..54922ed 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -2619,15 +2619,15 @@
static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
struct w83627ehf_sio_data *sio_data)
{
- static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
- static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
- static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
- static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
- static const char __initdata sio_name_W83627UHG[] = "W83627UHG";
- static const char __initdata sio_name_W83667HG[] = "W83667HG";
- static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
- static const char __initdata sio_name_NCT6775[] = "NCT6775F";
- static const char __initdata sio_name_NCT6776[] = "NCT6776F";
+ static const char sio_name_W83627EHF[] __initconst = "W83627EHF";
+ static const char sio_name_W83627EHG[] __initconst = "W83627EHG";
+ static const char sio_name_W83627DHG[] __initconst = "W83627DHG";
+ static const char sio_name_W83627DHG_P[] __initconst = "W83627DHG-P";
+ static const char sio_name_W83627UHG[] __initconst = "W83627UHG";
+ static const char sio_name_W83667HG[] __initconst = "W83667HG";
+ static const char sio_name_W83667HG_B[] __initconst = "W83667HG-B";
+ static const char sio_name_NCT6775[] __initconst = "NCT6775F";
+ static const char sio_name_NCT6776[] __initconst = "NCT6776F";
u16 val;
const char *sio_name;
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 37f4211..00e8f21 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -182,7 +182,6 @@
pci_restore_state(pdev);
i2c_dw_init(i2c);
- i2c_dw_enable(i2c);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index f086131..c811289b 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -324,7 +324,7 @@
{
long ret;
ret = wait_event_timeout(pch_event,
- (adap->pch_event_flag != 0), msecs_to_jiffies(50));
+ (adap->pch_event_flag != 0), msecs_to_jiffies(1000));
if (ret == 0) {
pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
@@ -1063,6 +1063,6 @@
MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C");
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.lapis-semi.com>");
+MODULE_AUTHOR("Tomoya MORINAGA. <tomoya.rohm@gmail.com>");
module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
module_param(pch_clk, int, (S_IRUSR | S_IWUSR));
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 3d471d5..76b8af4 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -227,6 +227,7 @@
return -EINVAL;
init_completion(&i2c->cmd_complete);
+ i2c->cmd_err = 0;
flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
@@ -252,6 +253,9 @@
if (i2c->cmd_err == -ENXIO)
mxs_i2c_reset(i2c);
+ else
+ writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+ i2c->regs + MXS_I2C_QUEUECTRL_CLR);
dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
@@ -299,8 +303,6 @@
MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ))
/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
i2c->cmd_err = -EIO;
- else
- i2c->cmd_err = 0;
is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
@@ -384,8 +386,6 @@
if (ret)
return -EBUSY;
- writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
- i2c->regs + MXS_I2C_QUEUECTRL_CLR);
writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 04be9f82..eb8ad53 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -546,8 +546,7 @@
{
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
- /* FIXME: shouldn't this be clk_disable? */
- clk_enable(alg_data->clk);
+ clk_disable(alg_data->clk);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index e978635..55e5ea6 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -516,6 +516,14 @@
if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
return 0;
+ /*
+ * NACK interrupt is generated before the I2C controller generates the
+ * STOP condition on the bus. So wait for 2 clock periods before resetting
+ * the controller so that STOP condition has been delivered properly.
+ */
+ if (i2c_dev->msg_err == I2C_ERR_NO_ACK)
+ udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate));
+
tegra_i2c_init(i2c_dev);
if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c
index c976285..fa080eb 100644
--- a/drivers/idle/i7300_idle.c
+++ b/drivers/idle/i7300_idle.c
@@ -516,12 +516,6 @@
MODULE_DEVICE_TABLE(pci, pci_tbl);
-int stats_open_generic(struct inode *inode, struct file *fp)
-{
- fp->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t stats_read_ul(struct file *fp, char __user *ubuf, size_t count,
loff_t *off)
{
@@ -534,7 +528,7 @@
}
static const struct file_operations idle_fops = {
- .open = stats_open_generic,
+ .open = simple_open,
.read = stats_read_ul,
.llseek = default_llseek,
};
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 426bb76..b0d0bc8 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1854,6 +1854,8 @@
response->mad.mad.mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
response->mad.mad.mad_hdr.status =
cpu_to_be16(IB_MGMT_MAD_STATUS_UNSUPPORTED_METHOD_ATTRIB);
+ if (recv->mad.mad.mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+ response->mad.mad.mad_hdr.status |= IB_SMP_DIRECTION;
return true;
} else {
@@ -1869,6 +1871,7 @@
struct ib_mad_list_head *mad_list;
struct ib_mad_agent_private *mad_agent;
int port_num;
+ int ret = IB_MAD_RESULT_SUCCESS;
mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id;
qp_info = mad_list->mad_queue->qp_info;
@@ -1952,8 +1955,6 @@
local:
/* Give driver "right of first refusal" on incoming MAD */
if (port_priv->device->process_mad) {
- int ret;
-
ret = port_priv->device->process_mad(port_priv->device, 0,
port_priv->port_num,
wc, &recv->grh,
@@ -1981,7 +1982,8 @@
* or via recv_handler in ib_mad_complete_recv()
*/
recv = NULL;
- } else if (generate_unmatched_resp(recv, response)) {
+ } else if ((ret & IB_MAD_RESULT_SUCCESS) &&
+ generate_unmatched_resp(recv, response)) {
agent_send_response(&response->mad.mad, &recv->grh, wc,
port_priv->device, port_num, qp_info->qp->qp_num);
}
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 83b720e..246fdc1 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -179,7 +179,7 @@
{
struct ib_port_attr attr;
char *speed = "";
- int rate = -1; /* in deci-Gb/sec */
+ int rate; /* in deci-Gb/sec */
ssize_t ret;
ret = ib_query_port(p->ibdev, p->port_num, &attr);
@@ -187,9 +187,6 @@
return ret;
switch (attr.active_speed) {
- case IB_SPEED_SDR:
- rate = 25;
- break;
case IB_SPEED_DDR:
speed = " DDR";
rate = 50;
@@ -210,6 +207,10 @@
speed = " EDR";
rate = 250;
break;
+ case IB_SPEED_SDR:
+ default: /* default to SDR for invalid rates */
+ rate = 25;
+ break;
}
rate *= ib_width_enum_to_int(attr.active_width);
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index 75d3056..b948b6d 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -247,12 +247,17 @@
err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port,
NULL, NULL, in_mad, out_mad);
if (err)
- return err;
+ goto out;
/* Checking LinkSpeedActive for FDR-10 */
if (out_mad->data[15] & 0x1)
props->active_speed = IB_SPEED_FDR10;
}
+
+ /* Avoid wrong speed value returned by FW if the IB link is down. */
+ if (props->state == IB_PORT_DOWN)
+ props->active_speed = IB_SPEED_SDR;
+
out:
kfree(in_mad);
kfree(out_mad);
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 69e2ad0..daf21b8 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -3232,6 +3232,7 @@
srq_attr.attr.max_wr = sdev->srq_size;
srq_attr.attr.max_sge = 1;
srq_attr.attr.srq_limit = 0;
+ srq_attr.srq_type = IB_SRQT_BASIC;
sdev->srq = ib_create_srq(sdev->pd, &srq_attr);
if (IS_ERR(sdev->srq))
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 2d78779..7faf4a7 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -380,8 +380,7 @@
config INPUT_TWL6040_VIBRA
tristate "Support for TWL6040 Vibrator"
- depends on TWL4030_CORE
- select TWL6040_CORE
+ depends on TWL6040_CORE
select INPUT_FF_MEMLESS
help
This option enables support for TWL6040 Vibrator Driver.
diff --git a/drivers/input/misc/da9052_onkey.c b/drivers/input/misc/da9052_onkey.c
index 34aebb8..3c843cd 100644
--- a/drivers/input/misc/da9052_onkey.c
+++ b/drivers/input/misc/da9052_onkey.c
@@ -95,7 +95,8 @@
input_dev = input_allocate_device();
if (!onkey || !input_dev) {
dev_err(&pdev->dev, "Failed to allocate memory\n");
- return -ENOMEM;
+ error = -ENOMEM;
+ goto err_free_mem;
}
onkey->input = input_dev;
diff --git a/drivers/input/misc/twl6040-vibra.c b/drivers/input/misc/twl6040-vibra.c
index 45874fe..14e94f5 100644
--- a/drivers/input/misc/twl6040-vibra.c
+++ b/drivers/input/misc/twl6040-vibra.c
@@ -28,7 +28,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
-#include <linux/i2c/twl.h>
+#include <linux/input.h>
#include <linux/mfd/twl6040.h>
#include <linux/slab.h>
#include <linux/delay.h>
@@ -257,7 +257,7 @@
static int __devinit twl6040_vibra_probe(struct platform_device *pdev)
{
- struct twl4030_vibra_data *pdata = pdev->dev.platform_data;
+ struct twl6040_vibra_data *pdata = pdev->dev.platform_data;
struct vibra_info *info;
int ret;
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index d2c0db1..4790110 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -486,7 +486,6 @@
unsigned char *packet = psmouse->packet;
input_report_key(dev, BTN_LEFT, packet[0] & 0x01);
- input_report_key(dev, BTN_RIGHT, packet[0] & 0x02);
input_mt_report_pointer_emulation(dev, true);
input_sync(dev);
}
@@ -967,6 +966,7 @@
if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
return -1;
+ __set_bit(INPUT_PROP_POINTER, dev->propbit);
__set_bit(EV_KEY, dev->evbit);
__set_bit(EV_ABS, dev->evbit);
__clear_bit(EV_REL, dev->evbit);
@@ -1017,7 +1017,9 @@
*/
psmouse_warn(psmouse, "couldn't query resolution data.\n");
}
-
+ /* v4 is clickpad, with only one button. */
+ __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
+ __clear_bit(BTN_RIGHT, dev->keybit);
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
/* For X to recognize me as touchpad. */
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
@@ -1245,6 +1247,8 @@
*/
static int elantech_reconnect(struct psmouse *psmouse)
{
+ psmouse_reset(psmouse);
+
if (elantech_detect(psmouse, 0))
return -1;
@@ -1324,6 +1328,8 @@
if (!etd)
return -ENOMEM;
+ psmouse_reset(psmouse);
+
etd->parity[0] = 1;
for (i = 1; i < 256; i++)
etd->parity[i] = etd->parity[i & (i - 1)] ^ 1;
diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c
index a9ad8e1..39fe9b7 100644
--- a/drivers/input/mouse/gpio_mouse.c
+++ b/drivers/input/mouse/gpio_mouse.c
@@ -12,9 +12,9 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/input-polldev.h>
+#include <linux/gpio.h>
#include <linux/gpio_mouse.h>
-#include <asm/gpio.h>
/*
* Timer function which is run every scan_ms ms when the device is opened.
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index a977bfa..661a0ca 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -741,6 +741,14 @@
}
} else {
/* SFAC packet */
+ if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
+ FSP_PB0_LBTN) {
+ /* On-pad click in SFAC mode should be handled
+ * by userspace. On-pad clicks in MFMC mode
+ * are real clickpad clicks, and not ignored.
+ */
+ packet[0] &= ~FSP_PB0_LBTN;
+ }
/* no multi-finger information */
ad->last_mt_fgr = 0;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 8081a0a..a4b14a4 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -274,7 +274,8 @@
static unsigned char param = 0xc8;
struct synaptics_data *priv = psmouse->private;
- if (!SYN_CAP_ADV_GESTURE(priv->ext_cap_0c))
+ if (!(SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+ SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)))
return 0;
if (psmouse_sliced_command(psmouse, SYN_QUE_MODEL))
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index 22b2180..f310249 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -304,7 +304,7 @@
return 0;
if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
- printk(KERN_WARNING "trackpoint.c: failed to get extended button data\n");
+ psmouse_warn(psmouse, "failed to get extended button data\n");
button_info = 0;
}
@@ -326,16 +326,18 @@
error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group);
if (error) {
- printk(KERN_ERR
- "trackpoint.c: failed to create sysfs attributes, error: %d\n",
- error);
+ psmouse_err(psmouse,
+ "failed to create sysfs attributes, error: %d\n",
+ error);
kfree(psmouse->private);
psmouse->private = NULL;
return -1;
}
- printk(KERN_INFO "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
- firmware_id, (button_info & 0xf0) >> 4, button_info & 0x0f);
+ psmouse_info(psmouse,
+ "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n",
+ firmware_id,
+ (button_info & 0xf0) >> 4, button_info & 0x0f);
return 0;
}
diff --git a/drivers/input/touchscreen/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c
index 6c6f6d8..f7eda3d0 100644
--- a/drivers/input/touchscreen/tps6507x-ts.c
+++ b/drivers/input/touchscreen/tps6507x-ts.c
@@ -1,6 +1,4 @@
/*
- * drivers/input/touchscreen/tps6507x_ts.c
- *
* Touchscreen driver for the tps6507x chip.
*
* Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com)
@@ -376,4 +374,4 @@
MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>");
MODULE_DESCRIPTION("TPS6507x - TouchScreen driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:tps6507x-tsc");
+MODULE_ALIAS("platform:tps6507x-ts");
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index ae2ec92..a5bee8e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2707,7 +2707,8 @@
* The exported alloc_coherent function for dma_ops.
*/
static void *alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_addr, gfp_t flag)
+ dma_addr_t *dma_addr, gfp_t flag,
+ struct dma_attrs *attrs)
{
unsigned long flags;
void *virt_addr;
@@ -2765,7 +2766,8 @@
* The exported free_coherent function for dma_ops.
*/
static void free_coherent(struct device *dev, size_t size,
- void *virt_addr, dma_addr_t dma_addr)
+ void *virt_addr, dma_addr_t dma_addr,
+ struct dma_attrs *attrs)
{
unsigned long flags;
struct protection_domain *domain;
@@ -2846,8 +2848,8 @@
}
static struct dma_map_ops amd_iommu_dma_ops = {
- .alloc_coherent = alloc_coherent,
- .free_coherent = free_coherent,
+ .alloc = alloc_coherent,
+ .free = free_coherent,
.map_page = map_page,
.unmap_page = unmap_page,
.map_sg = map_sg,
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 132f93b..f93d5ac 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2949,7 +2949,8 @@
}
static void *intel_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
+ dma_addr_t *dma_handle, gfp_t flags,
+ struct dma_attrs *attrs)
{
void *vaddr;
int order;
@@ -2981,7 +2982,7 @@
}
static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
int order;
@@ -3126,8 +3127,8 @@
}
struct dma_map_ops intel_dma_ops = {
- .alloc_coherent = intel_alloc_coherent,
- .free_coherent = intel_free_coherent,
+ .alloc = intel_alloc_coherent,
+ .free = intel_free_coherent,
.map_sg = intel_map_sg,
.unmap_sg = intel_unmap_sg,
.map_page = intel_map_page,
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 103dbd9..f55fc5d 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -323,15 +323,9 @@
return count;
}
-static int debug_open_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define DEBUG_FOPS(name) \
static const struct file_operations debug_##name##_fops = { \
- .open = debug_open_generic, \
+ .open = simple_open, \
.read = debug_read_##name, \
.write = debug_write_##name, \
.llseek = generic_file_llseek, \
@@ -339,7 +333,7 @@
#define DEBUG_FOPS_RO(name) \
static const struct file_operations debug_##name##_fops = { \
- .open = debug_open_generic, \
+ .open = simple_open, \
.read = debug_read_##name, \
.llseek = generic_file_llseek, \
};
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c
index b3d6ac1..a6d9fd2 100644
--- a/drivers/isdn/gigaset/interface.c
+++ b/drivers/isdn/gigaset/interface.c
@@ -176,7 +176,7 @@
struct cardstate *cs = tty->driver_data;
if (!cs) { /* happens if we didn't find cs in open */
- printk(KERN_DEBUG "%s: no cardstate\n", __func__);
+ gig_dbg(DEBUG_IF, "%s: no cardstate", __func__);
return;
}
diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c
index 05ed4d0c..c0b8c96 100644
--- a/drivers/isdn/hardware/mISDN/avmfritz.c
+++ b/drivers/isdn/hardware/mISDN/avmfritz.c
@@ -891,7 +891,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c
index d055ae7..e2c83a2 100644
--- a/drivers/isdn/hardware/mISDN/hfcpci.c
+++ b/drivers/isdn/hardware/mISDN/hfcpci.c
@@ -1962,7 +1962,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c
index 6023387..8cde2a0 100644
--- a/drivers/isdn/hardware/mISDN/hfcsusb.c
+++ b/drivers/isdn/hardware/mISDN/hfcsusb.c
@@ -486,7 +486,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
index b47e9be..884369f 100644
--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
+++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
@@ -1506,7 +1506,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c
index 10446ab..9a6da6e 100644
--- a/drivers/isdn/hardware/mISDN/mISDNisar.c
+++ b/drivers/isdn/hardware/mISDN/mISDNisar.c
@@ -1670,7 +1670,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
index dd6de9f..c726e09 100644
--- a/drivers/isdn/hardware/mISDN/netjet.c
+++ b/drivers/isdn/hardware/mISDN/netjet.c
@@ -860,7 +860,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/isdn/hardware/mISDN/w6692.c b/drivers/isdn/hardware/mISDN/w6692.c
index 7f1e7ba..2183357 100644
--- a/drivers/isdn/hardware/mISDN/w6692.c
+++ b/drivers/isdn/hardware/mISDN/w6692.c
@@ -1015,7 +1015,7 @@
{
struct bchannel *bch;
- if (rq->adr.channel > 2)
+ if (rq->adr.channel == 0 || rq->adr.channel > 2)
return -EINVAL;
if (rq->protocol == ISDN_P_NONE)
return -EINVAL;
diff --git a/drivers/leds/leds-atmel-pwm.c b/drivers/leds/leds-atmel-pwm.c
index 800243b..64ad702 100644
--- a/drivers/leds/leds-atmel-pwm.c
+++ b/drivers/leds/leds-atmel-pwm.c
@@ -35,7 +35,7 @@
* NOTE: we reuse the platform_data structure of GPIO leds,
* but repurpose its "gpio" number as a PWM channel number.
*/
-static int __init pwmled_probe(struct platform_device *pdev)
+static int __devinit pwmled_probe(struct platform_device *pdev)
{
const struct gpio_led_platform_data *pdata;
struct pwmled *leds;
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 3d0dfa7..17e2b47 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -539,9 +539,6 @@
bitmap->events_cleared = bitmap->mddev->events;
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
- bitmap->flags |= BITMAP_HOSTENDIAN;
- sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN);
-
kunmap_atomic(sb);
return 0;
@@ -1730,8 +1727,7 @@
bitmap->chunkshift = (ffz(~mddev->bitmap_info.chunksize)
- BITMAP_BLOCK_SHIFT);
- /* now that chunksize and chunkshift are set, we can use these macros */
- chunks = (blocks + bitmap->chunkshift - 1) >>
+ chunks = (blocks + (1 << bitmap->chunkshift) - 1) >>
bitmap->chunkshift;
pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
@@ -1788,7 +1784,9 @@
* re-add of a missing device */
start = mddev->recovery_cp;
+ mutex_lock(&mddev->bitmap_info.mutex);
err = bitmap_init_from_disk(bitmap, start);
+ mutex_unlock(&mddev->bitmap_info.mutex);
if (err)
goto out;
diff --git a/drivers/md/bitmap.h b/drivers/md/bitmap.h
index 55ca5ae..b44b0aba 100644
--- a/drivers/md/bitmap.h
+++ b/drivers/md/bitmap.h
@@ -101,9 +101,6 @@
#define BITMAP_BLOCK_SHIFT 9
-/* how many blocks per chunk? (this is variable) */
-#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->mddev->bitmap_info.chunksize >> BITMAP_BLOCK_SHIFT)
-
#endif
/*
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index b0ba524..68965e6 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -859,7 +859,7 @@
int ret;
unsigned redundancy = 0;
struct raid_dev *dev;
- struct md_rdev *rdev, *freshest;
+ struct md_rdev *rdev, *tmp, *freshest;
struct mddev *mddev = &rs->md;
switch (rs->raid_type->level) {
@@ -877,7 +877,7 @@
}
freshest = NULL;
- rdev_for_each(rdev, mddev) {
+ rdev_for_each_safe(rdev, tmp, mddev) {
if (!rdev->meta_bdev)
continue;
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b0fcc7d..fa211d8 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -198,6 +198,7 @@
static int linear_run (struct mddev *mddev)
{
struct linear_conf *conf;
+ int ret;
if (md_check_no_bitmap(mddev))
return -EINVAL;
@@ -211,7 +212,13 @@
blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
mddev->queue->backing_dev_info.congested_fn = linear_congested;
mddev->queue->backing_dev_info.congested_data = mddev;
- return md_integrity_register(mddev);
+
+ ret = md_integrity_register(mddev);
+ if (ret) {
+ kfree(conf);
+ mddev->private = NULL;
+ }
+ return ret;
}
static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b572e1e..477eb2e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7560,14 +7560,14 @@
* any transients in the value of "sync_action".
*/
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
- clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
/* Clear some bits that don't mean anything, but
* might be left set
*/
clear_bit(MD_RECOVERY_INTR, &mddev->recovery);
clear_bit(MD_RECOVERY_DONE, &mddev->recovery);
- if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+ if (!test_and_clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
+ test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
goto unlock;
/* no recovery is running.
* remove any failed drives, then
@@ -8140,7 +8140,8 @@
for_each_mddev(mddev, tmp) {
if (mddev_trylock(mddev)) {
- __md_stop_writes(mddev);
+ if (mddev->pers)
+ __md_stop_writes(mddev);
mddev->safemode = 2;
mddev_unlock(mddev);
}
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 6f31f55..de63a1f 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -407,6 +407,8 @@
return array_sectors;
}
+static int raid0_stop(struct mddev *mddev);
+
static int raid0_run(struct mddev *mddev)
{
struct r0conf *conf;
@@ -454,7 +456,12 @@
blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
dump_zones(mddev);
- return md_integrity_register(mddev);
+
+ ret = md_integrity_register(mddev);
+ if (ret)
+ raid0_stop(mddev);
+
+ return ret;
}
static int raid0_stop(struct mddev *mddev)
@@ -625,6 +632,7 @@
static void *raid0_takeover_raid1(struct mddev *mddev)
{
struct r0conf *priv_conf;
+ int chunksect;
/* Check layout:
* - (N - 1) mirror drives must be already faulty
@@ -635,10 +643,25 @@
return ERR_PTR(-EINVAL);
}
+ /*
+ * a raid1 doesn't have the notion of chunk size, so
+ * figure out the largest suitable size we can use.
+ */
+ chunksect = 64 * 2; /* 64K by default */
+
+ /* The array must be an exact multiple of chunksize */
+ while (chunksect && (mddev->array_sectors & (chunksect - 1)))
+ chunksect >>= 1;
+
+ if ((chunksect << 9) < PAGE_SIZE)
+ /* array size does not allow a suitable chunk size */
+ return ERR_PTR(-EINVAL);
+
/* Set new parameters */
mddev->new_level = 0;
mddev->new_layout = 0;
- mddev->new_chunk_sectors = 128; /* by default set chunk size to 64k */
+ mddev->new_chunk_sectors = chunksect;
+ mddev->chunk_sectors = chunksect;
mddev->delta_disks = 1 - mddev->raid_disks;
mddev->raid_disks = 1;
/* make sure it will be not marked as dirty */
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 4a40a20..15dd59b 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1712,6 +1712,7 @@
struct r1conf *conf = mddev->private;
int primary;
int i;
+ int vcnt;
for (primary = 0; primary < conf->raid_disks * 2; primary++)
if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
@@ -1721,9 +1722,9 @@
break;
}
r1_bio->read_disk = primary;
+ vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9);
for (i = 0; i < conf->raid_disks * 2; i++) {
int j;
- int vcnt = r1_bio->sectors >> (PAGE_SHIFT- 9);
struct bio *pbio = r1_bio->bios[primary];
struct bio *sbio = r1_bio->bios[i];
int size;
@@ -1738,7 +1739,7 @@
s = sbio->bi_io_vec[j].bv_page;
if (memcmp(page_address(p),
page_address(s),
- PAGE_SIZE))
+ sbio->bi_io_vec[j].bv_len))
break;
}
} else
@@ -2386,8 +2387,7 @@
int ok = 1;
for (i = 0 ; i < conf->raid_disks * 2 ; i++)
if (r1_bio->bios[i]->bi_end_io == end_sync_write) {
- struct md_rdev *rdev =
- rcu_dereference(conf->mirrors[i].rdev);
+ struct md_rdev *rdev = conf->mirrors[i].rdev;
ok = rdev_set_badblocks(rdev, sector_nr,
min_bad, 0
) && ok;
@@ -2636,11 +2636,13 @@
return ERR_PTR(err);
}
+static int stop(struct mddev *mddev);
static int run(struct mddev *mddev)
{
struct r1conf *conf;
int i;
struct md_rdev *rdev;
+ int ret;
if (mddev->level != 1) {
printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
@@ -2705,7 +2707,11 @@
mddev->queue->backing_dev_info.congested_data = mddev;
blk_queue_merge_bvec(mddev->queue, raid1_mergeable_bvec);
}
- return md_integrity_register(mddev);
+
+ ret = md_integrity_register(mddev);
+ if (ret)
+ stop(mddev);
+ return ret;
}
static int stop(struct mddev *mddev)
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 3540316..c8dbb84 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1788,6 +1788,7 @@
struct r10conf *conf = mddev->private;
int i, first;
struct bio *tbio, *fbio;
+ int vcnt;
atomic_set(&r10_bio->remaining, 1);
@@ -1802,10 +1803,10 @@
first = i;
fbio = r10_bio->devs[i].bio;
+ vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9);
/* now find blocks with errors */
for (i=0 ; i < conf->copies ; i++) {
int j, d;
- int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
tbio = r10_bio->devs[i].bio;
@@ -1821,7 +1822,7 @@
for (j = 0; j < vcnt; j++)
if (memcmp(page_address(fbio->bi_io_vec[j].bv_page),
page_address(tbio->bi_io_vec[j].bv_page),
- PAGE_SIZE))
+ fbio->bi_io_vec[j].bv_len))
break;
if (j == vcnt)
continue;
@@ -1871,7 +1872,6 @@
*/
for (i = 0; i < conf->copies; i++) {
int j, d;
- int vcnt = r10_bio->sectors >> (PAGE_SHIFT-9);
tbio = r10_bio->devs[i].repl_bio;
if (!tbio || !tbio->bi_end_io)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 23ac880..f351422 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2471,39 +2471,41 @@
int abort = 0;
int i;
- md_done_sync(conf->mddev, STRIPE_SECTORS, 0);
clear_bit(STRIPE_SYNCING, &sh->state);
s->syncing = 0;
s->replacing = 0;
/* There is nothing more to do for sync/check/repair.
+ * Don't even need to abort as that is handled elsewhere
+ * if needed, and not always wanted e.g. if there is a known
+ * bad block here.
* For recover/replace we need to record a bad block on all
* non-sync devices, or abort the recovery
*/
- if (!test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery))
- return;
- /* During recovery devices cannot be removed, so locking and
- * refcounting of rdevs is not needed
- */
- for (i = 0; i < conf->raid_disks; i++) {
- struct md_rdev *rdev = conf->disks[i].rdev;
- if (rdev
- && !test_bit(Faulty, &rdev->flags)
- && !test_bit(In_sync, &rdev->flags)
- && !rdev_set_badblocks(rdev, sh->sector,
- STRIPE_SECTORS, 0))
- abort = 1;
- rdev = conf->disks[i].replacement;
- if (rdev
- && !test_bit(Faulty, &rdev->flags)
- && !test_bit(In_sync, &rdev->flags)
- && !rdev_set_badblocks(rdev, sh->sector,
- STRIPE_SECTORS, 0))
- abort = 1;
+ if (test_bit(MD_RECOVERY_RECOVER, &conf->mddev->recovery)) {
+ /* During recovery devices cannot be removed, so
+ * locking and refcounting of rdevs is not needed
+ */
+ for (i = 0; i < conf->raid_disks; i++) {
+ struct md_rdev *rdev = conf->disks[i].rdev;
+ if (rdev
+ && !test_bit(Faulty, &rdev->flags)
+ && !test_bit(In_sync, &rdev->flags)
+ && !rdev_set_badblocks(rdev, sh->sector,
+ STRIPE_SECTORS, 0))
+ abort = 1;
+ rdev = conf->disks[i].replacement;
+ if (rdev
+ && !test_bit(Faulty, &rdev->flags)
+ && !test_bit(In_sync, &rdev->flags)
+ && !rdev_set_badblocks(rdev, sh->sector,
+ STRIPE_SECTORS, 0))
+ abort = 1;
+ }
+ if (abort)
+ conf->recovery_disabled =
+ conf->mddev->recovery_disabled;
}
- if (abort) {
- conf->recovery_disabled = conf->mddev->recovery_disabled;
- set_bit(MD_RECOVERY_INTR, &conf->mddev->recovery);
- }
+ md_done_sync(conf->mddev, STRIPE_SECTORS, !abort);
}
static int want_replace(struct stripe_head *sh, int disk_idx)
@@ -3203,7 +3205,8 @@
/* Not in-sync */;
else if (is_bad) {
/* also not in-sync */
- if (!test_bit(WriteErrorSeen, &rdev->flags)) {
+ if (!test_bit(WriteErrorSeen, &rdev->flags) &&
+ test_bit(R5_UPTODATE, &dev->flags)) {
/* treat as in-sync, but with a read error
* which we can now try to correct
*/
@@ -3276,12 +3279,14 @@
/* If there is a failed device being replaced,
* we must be recovering.
* else if we are after recovery_cp, we must be syncing
+ * else if MD_RECOVERY_REQUESTED is set, we also are syncing.
* else we can only be replacing
* sync and recovery both need to read all devices, and so
* use the same flag.
*/
if (do_recovery ||
- sh->sector >= conf->mddev->recovery_cp)
+ sh->sector >= conf->mddev->recovery_cp ||
+ test_bit(MD_RECOVERY_REQUESTED, &(conf->mddev->recovery)))
s->syncing = 1;
else
s->replacing = 1;
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index 7f98984..eab2ea4 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -54,6 +54,7 @@
struct list_head hybrid_tuner_instance_list;
u32 if_khz;
+ u32 xtal_khz;
u32 freq_hz;
u32 bandwidth;
u8 video_standard;
@@ -214,9 +215,9 @@
.size = 12401,
};
-static const struct xc5000_fw_cfg xc5000c_41_024_5_31875 = {
- .name = "dvb-fe-xc5000c-41.024.5-31875.fw",
- .size = 16503,
+static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
+ .name = "dvb-fe-xc5000c-41.024.5.fw",
+ .size = 16497,
};
static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
@@ -226,7 +227,7 @@
case XC5000A:
return &xc5000a_1_6_114;
case XC5000C:
- return &xc5000c_41_024_5_31875;
+ return &xc5000c_41_024_5;
}
}
@@ -572,6 +573,31 @@
return found;
}
+static int xc_set_xtal(struct dvb_frontend *fe)
+{
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret = XC_RESULT_SUCCESS;
+
+ switch (priv->chip_id) {
+ default:
+ case XC5000A:
+ /* 32.000 MHz xtal is default */
+ break;
+ case XC5000C:
+ switch (priv->xtal_khz) {
+ default:
+ case 32000:
+ /* 32.000 MHz xtal is default */
+ break;
+ case 31875:
+ /* 31.875 MHz xtal configuration */
+ ret = xc_write_reg(priv, 0x000f, 0x8081);
+ break;
+ }
+ break;
+ }
+ return ret;
+}
static int xc5000_fwupload(struct dvb_frontend *fe)
{
@@ -603,6 +629,8 @@
} else {
printk(KERN_INFO "xc5000: firmware uploading...\n");
ret = xc_load_i2c_sequence(fe, fw->data);
+ if (XC_RESULT_SUCCESS == ret)
+ ret = xc_set_xtal(fe);
printk(KERN_INFO "xc5000: firmware upload complete...\n");
}
@@ -1164,6 +1192,9 @@
priv->if_khz = cfg->if_khz;
}
+ if (priv->xtal_khz == 0)
+ priv->xtal_khz = cfg->xtal_khz;
+
if (priv->radio_input == 0)
priv->radio_input = cfg->radio_input;
diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h
index 3396f8e..39a73bf 100644
--- a/drivers/media/common/tuners/xc5000.h
+++ b/drivers/media/common/tuners/xc5000.h
@@ -34,6 +34,7 @@
u8 i2c_address;
u32 if_khz;
u8 radio_input;
+ u32 xtal_khz;
int chip_id;
};
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 4555baa..0f64d71 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -143,10 +143,12 @@
static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static int dtv_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p_out);
+static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
+ struct dvb_frontend_parameters *p);
static bool has_get_frontend(struct dvb_frontend *fe)
{
- return fe->ops.get_frontend;
+ return fe->ops.get_frontend != NULL;
}
/*
@@ -697,6 +699,7 @@
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
fepriv->delay = HZ / 2;
}
+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
fe->ops.read_status(fe, &s);
if (s != fepriv->status) {
dvb_frontend_add_event(fe, s); /* update event list */
@@ -1443,6 +1446,28 @@
__func__);
return -EINVAL;
}
+ /*
+ * Get a delivery system that is compatible with DVBv3
+ * NOTE: in order for this to work with softwares like Kaffeine that
+ * uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
+ * DVB-S, drivers that support both should put the SYS_DVBS entry
+ * before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
+ * The real fix is that userspace applications should not use DVBv3
+ * and not trust on calling FE_SET_FRONTEND to switch the delivery
+ * system.
+ */
+ ncaps = 0;
+ while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
+ if (fe->ops.delsys[ncaps] == desired_system) {
+ delsys = desired_system;
+ break;
+ }
+ ncaps++;
+ }
+ if (delsys == SYS_UNDEFINED) {
+ dprintk("%s() Couldn't find a delivery system that matches %d\n",
+ __func__, desired_system);
+ }
} else {
/*
* This is a DVBv5 call. So, it likely knows the supported
@@ -1491,9 +1516,10 @@
__func__);
return -EINVAL;
}
- c->delivery_system = delsys;
}
+ c->delivery_system = delsys;
+
/*
* The DVBv3 or DVBv5 call is requesting a different system. So,
* emulation is needed.
@@ -1833,6 +1859,13 @@
return -EINVAL;
/*
+ * Initialize output parameters to match the values given by
+ * the user. FE_SET_FRONTEND triggers an initial frontend event
+ * with status = 0, which copies output parameters to userspace.
+ */
+ dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
+
+ /*
* Be sure that the bandwidth will be filled for all
* non-satellite systems, as tuners need to know what
* low pass/Nyquist half filter should be applied, in
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
index 3b7b102..482d249 100644
--- a/drivers/media/dvb/dvb-usb/it913x.c
+++ b/drivers/media/dvb/dvb-usb/it913x.c
@@ -238,12 +238,27 @@
static u32 it913x_query(struct usb_device *udev, u8 pro)
{
- int ret;
+ int ret, i;
u8 data[4];
- ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
- 0x1222, 0, &data[0], 3);
+ u8 ver;
- it913x_config.chip_ver = data[0];
+ for (i = 0; i < 5; i++) {
+ ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
+ 0x1222, 0, &data[0], 3);
+ ver = data[0];
+ if (ver > 0 && ver < 3)
+ break;
+ msleep(100);
+ }
+
+ if (ver < 1 || ver > 2) {
+ info("Failed to identify chip version applying 1");
+ it913x_config.chip_ver = 0x1;
+ it913x_config.chip_type = 0x9135;
+ return 0;
+ }
+
+ it913x_config.chip_ver = ver;
it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
@@ -660,30 +675,41 @@
if ((packet_size > min_pkt) || (i == fw->size)) {
fw_data = (u8 *)(fw->data + pos);
pos += packet_size;
- if (packet_size > 0)
- ret |= it913x_io(udev, WRITE_DATA,
+ if (packet_size > 0) {
+ ret = it913x_io(udev, WRITE_DATA,
DEV_0, CMD_SCATTER_WRITE, 0,
0, fw_data, packet_size);
+ if (ret < 0)
+ break;
+ }
udelay(1000);
}
}
i++;
}
- ret |= it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
-
- msleep(100);
-
if (ret < 0)
- info("FRM Firmware Download Failed (%04x)" , ret);
+ info("FRM Firmware Download Failed (%d)" , ret);
else
info("FRM Firmware Download Completed - Resetting Device");
- ret |= it913x_return_status(udev);
+ msleep(30);
+
+ ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
+ if (ret < 0)
+ info("FRM Device not responding to reboot");
+
+ ret = it913x_return_status(udev);
+ if (ret == 0) {
+ info("FRM Failed to reboot device");
+ return -ENODEV;
+ }
msleep(30);
- ret |= it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400);
+ ret = it913x_wr_reg(udev, DEV_0, I2C_CLK, I2C_CLK_400);
+
+ msleep(30);
/* Tuner function */
if (it913x_config.dual_mode)
@@ -901,5 +927,5 @@
MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.27");
+MODULE_VERSION("1.28");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/drxk_hard.c b/drivers/media/dvb/frontends/drxk_hard.c
index 36d1175..a414b1f 100644
--- a/drivers/media/dvb/frontends/drxk_hard.c
+++ b/drivers/media/dvb/frontends/drxk_hard.c
@@ -1520,8 +1520,10 @@
dprintk(1, "\n");
if ((cmd == 0) || ((parameterLen > 0) && (parameter == NULL)) ||
- ((resultLen > 0) && (result == NULL)))
- goto error;
+ ((resultLen > 0) && (result == NULL))) {
+ printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
+ return status;
+ }
mutex_lock(&state->mutex);
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index b09c5fa..af52658 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1046,6 +1046,7 @@
goto exit_unregister_led;
}
+ data->dev->driver_type = RC_DRIVER_IR_RAW;
data->dev->driver_name = WBCIR_NAME;
data->dev->input_name = WBCIR_NAME;
data->dev->input_phys = "wbcir/cir0";
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index f2479c5..ce1e7ba 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -492,7 +492,7 @@
config VIDEO_MT9M032
tristate "MT9M032 camera sensor support"
- depends on I2C && VIDEO_V4L2
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
select VIDEO_APTINA_PLL
---help---
This driver supports MT9M032 camera sensors from Aptina, monochrome
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index 5452bee..989e556 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -1763,13 +1763,13 @@
IVTV_DEBUG_IOCTL("AUDIO_CHANNEL_SELECT\n");
if (iarg > AUDIO_STEREO_SWAPPED)
return -EINVAL;
- return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg);
+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_playback, iarg + 1);
case AUDIO_BILINGUAL_CHANNEL_SELECT:
IVTV_DEBUG_IOCTL("AUDIO_BILINGUAL_CHANNEL_SELECT\n");
if (iarg > AUDIO_STEREO_SWAPPED)
return -EINVAL;
- return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg);
+ return v4l2_ctrl_s_ctrl(itv->ctrl_audio_multilingual_playback, iarg + 1);
default:
return -EINVAL;
diff --git a/drivers/media/video/mt9m032.c b/drivers/media/video/mt9m032.c
index 7636672..645973c 100644
--- a/drivers/media/video/mt9m032.c
+++ b/drivers/media/video/mt9m032.c
@@ -392,10 +392,11 @@
}
/* Scaling is not supported, the format is thus fixed. */
- ret = mt9m032_get_pad_format(subdev, fh, fmt);
+ fmt->format = *__mt9m032_get_pad_format(sensor, fh, fmt->which);
+ ret = 0;
done:
- mutex_lock(&sensor->lock);
+ mutex_unlock(&sensor->lock);
return ret;
}
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 4a44f9a..b76b0ac 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -468,22 +468,30 @@
spin_unlock_irqrestore(&stream->clock.lock, flags);
}
+static void uvc_video_clock_reset(struct uvc_streaming *stream)
+{
+ struct uvc_clock *clock = &stream->clock;
+
+ clock->head = 0;
+ clock->count = 0;
+ clock->last_sof = -1;
+ clock->sof_offset = -1;
+}
+
static int uvc_video_clock_init(struct uvc_streaming *stream)
{
struct uvc_clock *clock = &stream->clock;
spin_lock_init(&clock->lock);
- clock->head = 0;
- clock->count = 0;
clock->size = 32;
- clock->last_sof = -1;
- clock->sof_offset = -1;
clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
GFP_KERNEL);
if (clock->samples == NULL)
return -ENOMEM;
+ uvc_video_clock_reset(stream);
+
return 0;
}
@@ -1424,8 +1432,6 @@
if (free_buffers)
uvc_free_urb_buffers(stream);
-
- uvc_video_clock_cleanup(stream);
}
/*
@@ -1555,10 +1561,6 @@
uvc_video_stats_start(stream);
- ret = uvc_video_clock_init(stream);
- if (ret < 0)
- return ret;
-
if (intf->num_altsetting > 1) {
struct usb_host_endpoint *best_ep = NULL;
unsigned int best_psize = 3 * 1024;
@@ -1683,6 +1685,8 @@
stream->frozen = 0;
+ uvc_video_clock_reset(stream);
+
ret = uvc_commit_video(stream, &stream->ctrl);
if (ret < 0) {
uvc_queue_enable(&stream->queue, 0);
@@ -1819,25 +1823,35 @@
uvc_uninit_video(stream, 1);
usb_set_interface(stream->dev->udev, stream->intfnum, 0);
uvc_queue_enable(&stream->queue, 0);
+ uvc_video_clock_cleanup(stream);
return 0;
}
- ret = uvc_queue_enable(&stream->queue, 1);
+ ret = uvc_video_clock_init(stream);
if (ret < 0)
return ret;
+ ret = uvc_queue_enable(&stream->queue, 1);
+ if (ret < 0)
+ goto error_queue;
+
/* Commit the streaming parameters. */
ret = uvc_commit_video(stream, &stream->ctrl);
- if (ret < 0) {
- uvc_queue_enable(&stream->queue, 0);
- return ret;
- }
+ if (ret < 0)
+ goto error_commit;
ret = uvc_init_video(stream, GFP_KERNEL);
- if (ret < 0) {
- usb_set_interface(stream->dev->udev, stream->intfnum, 0);
- uvc_queue_enable(&stream->queue, 0);
- }
+ if (ret < 0)
+ goto error_video;
+
+ return 0;
+
+error_video:
+ usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+error_commit:
+ uvc_queue_enable(&stream->queue, 0);
+error_queue:
+ uvc_video_clock_cleanup(stream);
return ret;
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 29f463c..11e44386 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -268,10 +268,17 @@
This is used to control charging LED brightness.
config TWL6040_CORE
- bool
- depends on TWL4030_CORE && GENERIC_HARDIRQS
+ bool "Support for TWL6040 audio codec"
+ depends on I2C=y && GENERIC_HARDIRQS
select MFD_CORE
+ select REGMAP_I2C
default n
+ help
+ Say yes here if you want support for Texas Instruments TWL6040 audio
+ codec.
+ This driver provides common support for accessing the device,
+ additional drivers must be enabled in order to use the
+ functionality of the device (audio, vibra).
config MFD_STMPE
bool "Support STMicroelectronics STMPE"
diff --git a/drivers/mfd/aat2870-core.c b/drivers/mfd/aat2870-core.c
index 3aa36eb..44a3fdb 100644
--- a/drivers/mfd/aat2870-core.c
+++ b/drivers/mfd/aat2870-core.c
@@ -262,13 +262,6 @@
return count;
}
-static int aat2870_reg_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -330,7 +323,7 @@
}
static const struct file_operations aat2870_reg_fops = {
- .open = aat2870_reg_open_file,
+ .open = simple_open,
.read = aat2870_reg_read_file,
.write = aat2870_reg_write_file,
};
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index 60107ee..1efad20 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -483,12 +483,6 @@
bool mode;
};
-static int ab3100_get_set_reg_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t ab3100_get_set_reg(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
@@ -583,7 +577,7 @@
}
static const struct file_operations ab3100_get_set_reg_fops = {
- .open = ab3100_get_set_reg_open_file,
+ .open = simple_open,
.write = ab3100_get_set_reg,
.llseek = noop_llseek,
};
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index 1895cf9..1582c3d 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -527,7 +527,9 @@
static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
- return (offset < ASIC3_NUM_GPIOS) ? IRQ_BOARD_START + offset : -ENXIO;
+ struct asic3 *asic = container_of(chip, struct asic3, gpio);
+
+ return (offset < ASIC3_NUM_GPIOS) ? asic->irq_base + offset : -ENXIO;
}
static __init int asic3_gpio_probe(struct platform_device *pdev,
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index ebc1e86..5be3248 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2788,6 +2788,7 @@
.constraints = {
.name = "db8500-vape",
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ .always_on = true,
},
.consumer_supplies = db8500_vape_consumers,
.num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 95a2e54..7e96bb2 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -25,7 +25,7 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
-#include <linux/gpio.h>
+#include <plat/cpu.h>
#include <plat/usb.h>
#include <linux/pm_runtime.h>
@@ -502,19 +502,6 @@
pm_runtime_get_sync(dev);
spin_lock_irqsave(&omap->lock, flags);
- if (pdata->ehci_data->phy_reset) {
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
- gpio_request_one(pdata->ehci_data->reset_gpio_port[0],
- GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
-
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_request_one(pdata->ehci_data->reset_gpio_port[1],
- GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
-
- /* Hold the PHY in RESET for enough time till DIR is high */
- udelay(10);
- }
-
omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
@@ -593,39 +580,10 @@
usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
}
- if (pdata->ehci_data->phy_reset) {
- /* Hold the PHY in RESET for enough time till
- * PHY is settled and ready
- */
- udelay(10);
-
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
- gpio_set_value
- (pdata->ehci_data->reset_gpio_port[0], 1);
-
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_set_value
- (pdata->ehci_data->reset_gpio_port[1], 1);
- }
-
spin_unlock_irqrestore(&omap->lock, flags);
pm_runtime_put_sync(dev);
}
-static void omap_usbhs_deinit(struct device *dev)
-{
- struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
- struct usbhs_omap_platform_data *pdata = &omap->platdata;
-
- if (pdata->ehci_data->phy_reset) {
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
-
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
- }
-}
-
/**
* usbhs_omap_probe - initialize TI-based HCDs
@@ -860,7 +818,6 @@
{
struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
- omap_usbhs_deinit(&pdev->dev);
iounmap(omap->tll_base);
iounmap(omap->uhh_base);
clk_put(omap->init_60m_fclk);
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index 99ef944..44afae0 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -80,44 +80,6 @@
{.name = "rc5t583-key", }
};
-int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_write(rc5t583->regmap, reg, val);
-}
-
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- unsigned int ival;
- int ret;
- ret = regmap_read(rc5t583->regmap, reg, &ival);
- if (!ret)
- *val = (uint8_t)ival;
- return ret;
-}
-
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
-}
-
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
-}
-
-int rc5t583_update(struct device *dev, unsigned int reg,
- unsigned int val, unsigned int mask)
-{
- struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
- return regmap_update_bits(rc5t583->regmap, reg, mask, val);
-}
-
static int __rc5t583_set_ext_pwrreq1_control(struct device *dev,
int id, int ext_pwr, int slots)
{
@@ -197,6 +159,7 @@
ds_id, ext_pwr_req);
return 0;
}
+EXPORT_SYMBOL(rc5t583_ext_power_req_config);
static int rc5t583_clear_ext_power_req(struct rc5t583 *rc5t583,
struct rc5t583_platform_data *pdata)
diff --git a/drivers/mfd/twl6040-core.c b/drivers/mfd/twl6040-core.c
index b2d8e51..2d6beda 100644
--- a/drivers/mfd/twl6040-core.c
+++ b/drivers/mfd/twl6040-core.c
@@ -30,7 +30,9 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/delay.h>
-#include <linux/i2c/twl.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
#include <linux/mfd/core.h>
#include <linux/mfd/twl6040.h>
@@ -39,7 +41,7 @@
int twl6040_reg_read(struct twl6040 *twl6040, unsigned int reg)
{
int ret;
- u8 val = 0;
+ unsigned int val;
mutex_lock(&twl6040->io_mutex);
/* Vibra control registers from cache */
@@ -47,7 +49,7 @@
reg == TWL6040_REG_VIBCTLR)) {
val = twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)];
} else {
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
+ ret = regmap_read(twl6040->regmap, reg, &val);
if (ret < 0) {
mutex_unlock(&twl6040->io_mutex);
return ret;
@@ -64,7 +66,7 @@
int ret;
mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
+ ret = regmap_write(twl6040->regmap, reg, val);
/* Cache the vibra control registers */
if (reg == TWL6040_REG_VIBCTLL || reg == TWL6040_REG_VIBCTLR)
twl6040->vibra_ctrl_cache[VIBRACTRL_MEMBER(reg)] = val;
@@ -77,16 +79,9 @@
int twl6040_set_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
{
int ret;
- u8 val;
mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val |= mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+ ret = regmap_update_bits(twl6040->regmap, reg, mask, mask);
mutex_unlock(&twl6040->io_mutex);
return ret;
}
@@ -95,16 +90,9 @@
int twl6040_clear_bits(struct twl6040 *twl6040, unsigned int reg, u8 mask)
{
int ret;
- u8 val;
mutex_lock(&twl6040->io_mutex);
- ret = twl_i2c_read_u8(TWL_MODULE_AUDIO_VOICE, &val, reg);
- if (ret)
- goto out;
-
- val &= ~mask;
- ret = twl_i2c_write_u8(TWL_MODULE_AUDIO_VOICE, val, reg);
-out:
+ ret = regmap_update_bits(twl6040->regmap, reg, mask, 0);
mutex_unlock(&twl6040->io_mutex);
return ret;
}
@@ -494,32 +482,58 @@
},
};
-static int __devinit twl6040_probe(struct platform_device *pdev)
+static bool twl6040_readable_reg(struct device *dev, unsigned int reg)
{
- struct twl4030_audio_data *pdata = pdev->dev.platform_data;
+ /* Register 0 is not readable */
+ if (!reg)
+ return false;
+ return true;
+}
+
+static struct regmap_config twl6040_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TWL6040_REG_STATUS, /* 0x2e */
+
+ .readable_reg = twl6040_readable_reg,
+};
+
+static int __devinit twl6040_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct twl6040_platform_data *pdata = client->dev.platform_data;
struct twl6040 *twl6040;
struct mfd_cell *cell = NULL;
int ret, children = 0;
if (!pdata) {
- dev_err(&pdev->dev, "Platform data is missing\n");
+ dev_err(&client->dev, "Platform data is missing\n");
return -EINVAL;
}
/* In order to operate correctly we need valid interrupt config */
- if (!pdata->naudint_irq || !pdata->irq_base) {
- dev_err(&pdev->dev, "Invalid IRQ configuration\n");
+ if (!client->irq || !pdata->irq_base) {
+ dev_err(&client->dev, "Invalid IRQ configuration\n");
return -EINVAL;
}
- twl6040 = kzalloc(sizeof(struct twl6040), GFP_KERNEL);
- if (!twl6040)
- return -ENOMEM;
+ twl6040 = devm_kzalloc(&client->dev, sizeof(struct twl6040),
+ GFP_KERNEL);
+ if (!twl6040) {
+ ret = -ENOMEM;
+ goto err;
+ }
- platform_set_drvdata(pdev, twl6040);
+ twl6040->regmap = regmap_init_i2c(client, &twl6040_regmap_config);
+ if (IS_ERR(twl6040->regmap)) {
+ ret = PTR_ERR(twl6040->regmap);
+ goto err;
+ }
- twl6040->dev = &pdev->dev;
- twl6040->irq = pdata->naudint_irq;
+ i2c_set_clientdata(client, twl6040);
+
+ twl6040->dev = &client->dev;
+ twl6040->irq = client->irq;
twl6040->irq_base = pdata->irq_base;
mutex_init(&twl6040->mutex);
@@ -588,12 +602,12 @@
}
if (children) {
- ret = mfd_add_devices(&pdev->dev, pdev->id, twl6040->cells,
+ ret = mfd_add_devices(&client->dev, -1, twl6040->cells,
children, NULL, 0);
if (ret)
goto mfd_err;
} else {
- dev_err(&pdev->dev, "No platform data found for children\n");
+ dev_err(&client->dev, "No platform data found for children\n");
ret = -ENODEV;
goto mfd_err;
}
@@ -608,14 +622,15 @@
if (gpio_is_valid(twl6040->audpwron))
gpio_free(twl6040->audpwron);
gpio1_err:
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
+ i2c_set_clientdata(client, NULL);
+ regmap_exit(twl6040->regmap);
+err:
return ret;
}
-static int __devexit twl6040_remove(struct platform_device *pdev)
+static int __devexit twl6040_remove(struct i2c_client *client)
{
- struct twl6040 *twl6040 = platform_get_drvdata(pdev);
+ struct twl6040 *twl6040 = i2c_get_clientdata(client);
if (twl6040->power_count)
twl6040_power(twl6040, 0);
@@ -626,23 +641,30 @@
free_irq(twl6040->irq_base + TWL6040_IRQ_READY, twl6040);
twl6040_irq_exit(twl6040);
- mfd_remove_devices(&pdev->dev);
- platform_set_drvdata(pdev, NULL);
- kfree(twl6040);
+ mfd_remove_devices(&client->dev);
+ i2c_set_clientdata(client, NULL);
+ regmap_exit(twl6040->regmap);
return 0;
}
-static struct platform_driver twl6040_driver = {
+static const struct i2c_device_id twl6040_i2c_id[] = {
+ { "twl6040", 0, },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, twl6040_i2c_id);
+
+static struct i2c_driver twl6040_driver = {
+ .driver = {
+ .name = "twl6040",
+ .owner = THIS_MODULE,
+ },
.probe = twl6040_probe,
.remove = __devexit_p(twl6040_remove),
- .driver = {
- .owner = THIS_MODULE,
- .name = "twl6040",
- },
+ .id_table = twl6040_i2c_id,
};
-module_platform_driver(twl6040_driver);
+module_i2c_driver(twl6040_driver);
MODULE_DESCRIPTION("TWL6040 MFD");
MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 1c034b8..6673e57 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -500,12 +500,6 @@
return 1;
}
-static int remote_settings_file_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static int remote_settings_file_close(struct inode *inode, struct file *file)
{
return 0;
@@ -600,7 +594,7 @@
};
static const struct file_operations remote_settings_fops = {
- .open = remote_settings_file_open,
+ .open = simple_open,
.release = remote_settings_file_close,
.read = remote_settings_file_read,
.write = remote_settings_file_write,
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
index 3f7ad83..3aa9a96 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -134,12 +134,17 @@
static int hwbreaks_ok;
static int hw_break_val;
static int hw_break_val2;
+static int cont_instead_of_sstep;
+static unsigned long cont_thread_id;
+static unsigned long sstep_thread_id;
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
static int arch_needs_sstep_emulation = 1;
#else
static int arch_needs_sstep_emulation;
#endif
+static unsigned long cont_addr;
static unsigned long sstep_addr;
+static int restart_from_top_after_write;
static int sstep_state;
/* Storage for the registers, in GDB format. */
@@ -187,7 +192,8 @@
*/
while (!final_ack)
msleep_interruptible(1500);
-
+ /* Pause for any other threads to exit after final ack. */
+ msleep_interruptible(1000);
if (configured)
kgdb_unregister_io_module(&kgdbts_io_ops);
configured = 0;
@@ -211,7 +217,7 @@
if (!strcmp(arg, "kgdbts_break_test"))
addr = (unsigned long)kgdbts_break_test;
else if (!strcmp(arg, "sys_open"))
- addr = (unsigned long)sys_open;
+ addr = (unsigned long)do_sys_open;
else if (!strcmp(arg, "do_fork"))
addr = (unsigned long)do_fork;
else if (!strcmp(arg, "hw_break_val"))
@@ -283,6 +289,16 @@
hw_break_val++;
}
+static int get_thread_id_continue(char *put_str, char *arg)
+{
+ char *ptr = &put_str[11];
+
+ if (put_str[1] != 'T' || put_str[2] != '0')
+ return 1;
+ kgdb_hex2long(&ptr, &cont_thread_id);
+ return 0;
+}
+
static int check_and_rewind_pc(char *put_str, char *arg)
{
unsigned long addr = lookup_addr(arg);
@@ -299,13 +315,21 @@
if (addr + BREAK_INSTR_SIZE == ip)
offset = -BREAK_INSTR_SIZE;
#endif
- if (strcmp(arg, "silent") && ip + offset != addr) {
+
+ if (arch_needs_sstep_emulation && sstep_addr &&
+ ip + offset == sstep_addr &&
+ ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
+ /* This is special case for emulated single step */
+ v2printk("Emul: rewind hit single step bp\n");
+ restart_from_top_after_write = 1;
+ } else if (strcmp(arg, "silent") && ip + offset != addr) {
eprintk("kgdbts: BP mismatch %lx expected %lx\n",
ip + offset, addr);
return 1;
}
/* Readjust the instruction pointer if needed */
ip += offset;
+ cont_addr = ip;
#ifdef GDB_ADJUSTS_BREAK_OFFSET
instruction_pointer_set(&kgdbts_regs, ip);
#endif
@@ -315,6 +339,8 @@
static int check_single_step(char *put_str, char *arg)
{
unsigned long addr = lookup_addr(arg);
+ static int matched_id;
+
/*
* From an arch indepent point of view the instruction pointer
* should be on a different instruction
@@ -324,6 +350,29 @@
gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
v2printk("Singlestep stopped at IP: %lx\n",
instruction_pointer(&kgdbts_regs));
+
+ if (sstep_thread_id != cont_thread_id) {
+ /*
+ * Ensure we stopped in the same thread id as before, else the
+ * debugger should continue until the original thread that was
+ * single stepped is scheduled again, emulating gdb's behavior.
+ */
+ v2printk("ThrID does not match: %lx\n", cont_thread_id);
+ if (arch_needs_sstep_emulation) {
+ if (matched_id &&
+ instruction_pointer(&kgdbts_regs) != addr)
+ goto continue_test;
+ matched_id++;
+ ts.idx -= 2;
+ sstep_state = 0;
+ return 0;
+ }
+ cont_instead_of_sstep = 1;
+ ts.idx -= 4;
+ return 0;
+ }
+continue_test:
+ matched_id = 0;
if (instruction_pointer(&kgdbts_regs) == addr) {
eprintk("kgdbts: SingleStep failed at %lx\n",
instruction_pointer(&kgdbts_regs));
@@ -365,10 +414,40 @@
return 1;
}
+static void get_cont_catch(char *arg)
+{
+ /* Always send detach because the test is completed at this point */
+ fill_get_buf("D");
+}
+
+static int put_cont_catch(char *put_str, char *arg)
+{
+ /* This is at the end of the test and we catch any and all input */
+ v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
+ ts.idx--;
+ return 0;
+}
+
+static int emul_reset(char *put_str, char *arg)
+{
+ if (strncmp(put_str, "$OK", 3))
+ return 1;
+ if (restart_from_top_after_write) {
+ restart_from_top_after_write = 0;
+ ts.idx = -1;
+ }
+ return 0;
+}
+
static void emul_sstep_get(char *arg)
{
if (!arch_needs_sstep_emulation) {
- fill_get_buf(arg);
+ if (cont_instead_of_sstep) {
+ cont_instead_of_sstep = 0;
+ fill_get_buf("c");
+ } else {
+ fill_get_buf(arg);
+ }
return;
}
switch (sstep_state) {
@@ -398,9 +477,11 @@
static int emul_sstep_put(char *put_str, char *arg)
{
if (!arch_needs_sstep_emulation) {
- if (!strncmp(put_str+1, arg, 2))
- return 0;
- return 1;
+ char *ptr = &put_str[11];
+ if (put_str[1] != 'T' || put_str[2] != '0')
+ return 1;
+ kgdb_hex2long(&ptr, &sstep_thread_id);
+ return 0;
}
switch (sstep_state) {
case 1:
@@ -411,8 +492,7 @@
v2printk("Stopped at IP: %lx\n",
instruction_pointer(&kgdbts_regs));
/* Want to stop at IP + break instruction size by default */
- sstep_addr = instruction_pointer(&kgdbts_regs) +
- BREAK_INSTR_SIZE;
+ sstep_addr = cont_addr + BREAK_INSTR_SIZE;
break;
case 2:
if (strncmp(put_str, "$OK", 3)) {
@@ -424,6 +504,9 @@
if (strncmp(put_str, "$T0", 3)) {
eprintk("kgdbts: failed continue sstep\n");
return 1;
+ } else {
+ char *ptr = &put_str[11];
+ kgdb_hex2long(&ptr, &sstep_thread_id);
}
break;
case 4:
@@ -502,10 +585,10 @@
static struct test_struct singlestep_break_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
+ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, /* Write registers */
- { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "kgdbts_break_test", NULL, check_single_step },
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
@@ -523,16 +606,16 @@
static struct test_struct do_fork_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
- { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
- { "write", "OK", write_regs }, /* Write registers */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
+ { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
+ { "write", "OK", write_regs, emul_reset }, /* Write registers */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "do_fork", NULL, check_single_step },
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
- { "", "" },
+ { "", "", get_cont_catch, put_cont_catch },
};
/* Test for hitting a breakpoint at sys_open for what ever the number
@@ -541,16 +624,16 @@
static struct test_struct sys_open_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
- { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
- { "write", "OK", write_regs }, /* Write registers */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
+ { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
+ { "write", "OK", write_regs, emul_reset }, /* Write registers */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "sys_open", NULL, check_single_step },
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
- { "", "" },
+ { "", "", get_cont_catch, put_cont_catch },
};
/*
@@ -693,8 +776,8 @@
/* This callback is a put char which is when kgdb sends data to
* this I/O module.
*/
- if (ts.tst[ts.idx].get[0] == '\0' &&
- ts.tst[ts.idx].put[0] == '\0') {
+ if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' &&
+ !ts.tst[ts.idx].get_handler) {
eprintk("kgdbts: ERROR: beyond end of test on"
" '%s' line %i\n", ts.name, ts.idx);
return 0;
@@ -907,6 +990,17 @@
if (ptr)
sstep_test = simple_strtol(ptr+1, NULL, 10);
+ /* All HW break point tests */
+ if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+ hwbreaks_ok = 1;
+ v1printk("kgdbts:RUN hw breakpoint test\n");
+ run_breakpoint_test(1);
+ v1printk("kgdbts:RUN hw write breakpoint test\n");
+ run_hw_break_test(1);
+ v1printk("kgdbts:RUN access write breakpoint test\n");
+ run_hw_break_test(0);
+ }
+
/* required internal KGDB tests */
v1printk("kgdbts:RUN plant and detach test\n");
run_plant_and_detach_test(0);
@@ -924,35 +1018,11 @@
/* ===Optional tests=== */
- /* All HW break point tests */
- if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
- hwbreaks_ok = 1;
- v1printk("kgdbts:RUN hw breakpoint test\n");
- run_breakpoint_test(1);
- v1printk("kgdbts:RUN hw write breakpoint test\n");
- run_hw_break_test(1);
- v1printk("kgdbts:RUN access write breakpoint test\n");
- run_hw_break_test(0);
- }
-
if (nmi_sleep) {
v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
run_nmi_sleep_test(nmi_sleep);
}
-#ifdef CONFIG_DEBUG_RODATA
- /* Until there is an api to write to read-only text segments, use
- * HW breakpoints for the remainder of any tests, else print a
- * failure message if hw breakpoints do not work.
- */
- if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
- eprintk("kgdbts: HW breakpoints do not work,"
- "skipping remaining tests\n");
- return;
- }
- force_hwbrks = 1;
-#endif /* CONFIG_DEBUG_RODATA */
-
/* If the do_fork test is run it will be the last test that is
* executed because a kernel thread will be spawned at the very
* end to unregister the debug hooks.
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index eed213a..dabec55 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -873,7 +873,7 @@
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
- unsigned int from, nr, arg;
+ unsigned int from, nr, arg, trim_arg, erase_arg;
int err = 0, type = MMC_BLK_SECDISCARD;
if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
@@ -881,20 +881,26 @@
goto out;
}
- /* The sanitize operation is supported at v4.5 only */
- if (mmc_can_sanitize(card)) {
- err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
- EXT_CSD_SANITIZE_START, 1, 0);
- goto out;
- }
-
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
- if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
- arg = MMC_SECURE_TRIM1_ARG;
- else
- arg = MMC_SECURE_ERASE_ARG;
+ /* The sanitize operation is supported at v4.5 only */
+ if (mmc_can_sanitize(card)) {
+ erase_arg = MMC_ERASE_ARG;
+ trim_arg = MMC_TRIM_ARG;
+ } else {
+ erase_arg = MMC_SECURE_ERASE_ARG;
+ trim_arg = MMC_SECURE_TRIM1_ARG;
+ }
+
+ if (mmc_erase_group_aligned(card, from, nr))
+ arg = erase_arg;
+ else if (mmc_can_trim(card))
+ arg = trim_arg;
+ else {
+ err = -EINVAL;
+ goto out;
+ }
retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -904,25 +910,41 @@
INAND_CMD38_ARG_SECERASE,
0);
if (err)
- goto out;
+ goto out_retry;
}
+
err = mmc_erase(card, from, nr, arg);
- if (!err && arg == MMC_SECURE_TRIM1_ARG) {
+ if (err == -EIO)
+ goto out_retry;
+ if (err)
+ goto out;
+
+ if (arg == MMC_SECURE_TRIM1_ARG) {
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
INAND_CMD38_ARG_EXT_CSD,
INAND_CMD38_ARG_SECTRIM2,
0);
if (err)
- goto out;
+ goto out_retry;
}
+
err = mmc_erase(card, from, nr, MMC_SECURE_TRIM2_ARG);
+ if (err == -EIO)
+ goto out_retry;
+ if (err)
+ goto out;
}
-out:
- if (err == -EIO && !mmc_blk_reset(md, card->host, type))
+
+ if (mmc_can_sanitize(card))
+ err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+ EXT_CSD_SANITIZE_START, 1, 0);
+out_retry:
+ if (err && !mmc_blk_reset(md, card->host, type))
goto retry;
if (!err)
mmc_blk_reset_success(md, type);
+out:
spin_lock_irq(&md->lock);
__blk_end_request(req, err, blk_rq_bytes(req));
spin_unlock_irq(&md->lock);
@@ -1623,24 +1645,6 @@
return ret;
}
-static int
-mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
-{
- int err;
-
- mmc_claim_host(card->host);
- err = mmc_set_blocklen(card, 512);
- mmc_release_host(card->host);
-
- if (err) {
- pr_err("%s: unable to set block size to 512: %d\n",
- md->disk->disk_name, err);
- return -EINVAL;
- }
-
- return 0;
-}
-
static void mmc_blk_remove_req(struct mmc_blk_data *md)
{
struct mmc_card *card;
@@ -1768,7 +1772,6 @@
static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md, *part_md;
- int err;
char cap_str[10];
/*
@@ -1781,10 +1784,6 @@
if (IS_ERR(md))
return PTR_ERR(md);
- err = mmc_blk_set_blksize(md, card);
- if (err)
- goto out;
-
string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s %s\n",
@@ -1809,7 +1808,7 @@
out:
mmc_blk_remove_parts(card, md);
mmc_blk_remove_req(md);
- return err;
+ return 0;
}
static void mmc_blk_remove(struct mmc_card *card)
@@ -1825,7 +1824,7 @@
}
#ifdef CONFIG_PM
-static int mmc_blk_suspend(struct mmc_card *card, pm_message_t state)
+static int mmc_blk_suspend(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);
@@ -1845,8 +1844,6 @@
struct mmc_blk_data *md = mmc_get_drvdata(card);
if (md) {
- mmc_blk_set_blksize(md, card);
-
/*
* Resume involves the card going into idle state,
* so current partition is always the main one.
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 2517547..996f8e3 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -139,7 +139,7 @@
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
q->limits.max_discard_sectors = max_discard;
- if (card->erased_byte == 0)
+ if (card->erased_byte == 0 && !mmc_can_discard(card))
q->limits.discard_zeroes_data = 1;
q->limits.discard_granularity = card->pref_erase << 9;
/* granularity must not be greater than max. discard */
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 5d011a3..c60cee9 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -122,14 +122,14 @@
return 0;
}
-static int mmc_bus_suspend(struct device *dev, pm_message_t state)
+static int mmc_bus_suspend(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
int ret = 0;
if (dev->driver && drv->suspend)
- ret = drv->suspend(card, state);
+ ret = drv->suspend(card);
return ret;
}
@@ -165,20 +165,14 @@
return pm_runtime_suspend(dev);
}
-static const struct dev_pm_ops mmc_bus_pm_ops = {
- .runtime_suspend = mmc_runtime_suspend,
- .runtime_resume = mmc_runtime_resume,
- .runtime_idle = mmc_runtime_idle,
-};
-
-#define MMC_PM_OPS_PTR (&mmc_bus_pm_ops)
-
-#else /* !CONFIG_PM_RUNTIME */
-
-#define MMC_PM_OPS_PTR NULL
-
#endif /* !CONFIG_PM_RUNTIME */
+static const struct dev_pm_ops mmc_bus_pm_ops = {
+ SET_RUNTIME_PM_OPS(mmc_runtime_suspend, mmc_runtime_resume,
+ mmc_runtime_idle)
+ SET_SYSTEM_SLEEP_PM_OPS(mmc_bus_suspend, mmc_bus_resume)
+};
+
static struct bus_type mmc_bus_type = {
.name = "mmc",
.dev_attrs = mmc_dev_attrs,
@@ -186,9 +180,7 @@
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
- .suspend = mmc_bus_suspend,
- .resume = mmc_bus_resume,
- .pm = MMC_PM_OPS_PTR,
+ .pm = &mmc_bus_pm_ops,
};
int mmc_register_bus(void)
@@ -267,6 +259,15 @@
{
int ret;
const char *type;
+ const char *uhs_bus_speed_mode = "";
+ static const char *const uhs_speeds[] = {
+ [UHS_SDR12_BUS_SPEED] = "SDR12 ",
+ [UHS_SDR25_BUS_SPEED] = "SDR25 ",
+ [UHS_SDR50_BUS_SPEED] = "SDR50 ",
+ [UHS_SDR104_BUS_SPEED] = "SDR104 ",
+ [UHS_DDR50_BUS_SPEED] = "DDR50 ",
+ };
+
dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
@@ -296,6 +297,10 @@
break;
}
+ if (mmc_sd_card_uhs(card) &&
+ (card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
+ uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];
+
if (mmc_host_is_spi(card->host)) {
pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
@@ -303,13 +308,13 @@
mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
- pr_info("%s: new %s%s%s%s card at address %04x\n",
+ pr_info("%s: new %s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
(mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "",
- type, card->rca);
+ uhs_bus_speed_mode, type, card->rca);
}
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
index 29de31e..2c14be7 100644
--- a/drivers/mmc/core/cd-gpio.c
+++ b/drivers/mmc/core/cd-gpio.c
@@ -12,6 +12,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/jiffies.h>
+#include <linux/mmc/cd-gpio.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 14f262e..ba821fe 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -527,10 +527,14 @@
if (data->flags & MMC_DATA_WRITE)
/*
- * The limit is really 250 ms, but that is
- * insufficient for some crappy cards.
+ * The MMC spec "It is strongly recommended
+ * for hosts to implement more than 500ms
+ * timeout value even if the card indicates
+ * the 250ms maximum busy length." Even the
+ * previous value of 300ms is known to be
+ * insufficient for some cards.
*/
- limit_us = 300000;
+ limit_us = 3000000;
else
limit_us = 100000;
@@ -1405,7 +1409,10 @@
{
unsigned int erase_timeout;
- if (card->ext_csd.erase_group_def & 1) {
+ if (arg == MMC_DISCARD_ARG ||
+ (arg == MMC_TRIM_ARG && card->ext_csd.rev >= 6)) {
+ erase_timeout = card->ext_csd.trim_timeout;
+ } else if (card->ext_csd.erase_group_def & 1) {
/* High Capacity Erase Group Size uses HC timeouts */
if (arg == MMC_TRIM_ARG)
erase_timeout = card->ext_csd.trim_timeout;
@@ -1677,8 +1684,6 @@
{
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
return 1;
- if (mmc_can_discard(card))
- return 1;
return 0;
}
EXPORT_SYMBOL(mmc_can_trim);
@@ -1697,6 +1702,8 @@
int mmc_can_sanitize(struct mmc_card *card)
{
+ if (!mmc_can_trim(card) && !mmc_can_erase(card))
+ return 0;
if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_SANITIZE)
return 1;
return 0;
@@ -2231,6 +2238,7 @@
mmc_card_is_removable(host))
return err;
+ mmc_claim_host(host);
if (card && mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
@@ -2248,6 +2256,7 @@
card->ext_csd.cache_ctrl = enable;
}
}
+ mmc_release_host(host);
return err;
}
@@ -2265,49 +2274,32 @@
cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();
- if (mmc_try_claim_host(host)) {
- err = mmc_cache_ctrl(host, 0);
- mmc_release_host(host);
- } else {
- err = -EBUSY;
- }
+ err = mmc_cache_ctrl(host, 0);
if (err)
goto out;
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
- /*
- * A long response time is not acceptable for device drivers
- * when doing suspend. Prevent mmc_claim_host in the suspend
- * sequence, to potentially wait "forever" by trying to
- * pre-claim the host.
- */
- if (mmc_try_claim_host(host)) {
- if (host->bus_ops->suspend) {
- err = host->bus_ops->suspend(host);
- }
- mmc_release_host(host);
+ if (host->bus_ops->suspend)
+ err = host->bus_ops->suspend(host);
- if (err == -ENOSYS || !host->bus_ops->resume) {
- /*
- * We simply "remove" the card in this case.
- * It will be redetected on resume. (Calling
- * bus_ops->remove() with a claimed host can
- * deadlock.)
- */
- if (host->bus_ops->remove)
- host->bus_ops->remove(host);
- mmc_claim_host(host);
- mmc_detach_bus(host);
- mmc_power_off(host);
- mmc_release_host(host);
- host->pm_flags = 0;
- err = 0;
- }
- } else {
- err = -EBUSY;
+ if (err == -ENOSYS || !host->bus_ops->resume) {
+ /*
+ * We simply "remove" the card in this case.
+ * It will be redetected on resume. (Calling
+ * bus_ops->remove() with a claimed host can
+ * deadlock.)
+ */
+ if (host->bus_ops->remove)
+ host->bus_ops->remove(host);
+ mmc_claim_host(host);
+ mmc_detach_bus(host);
+ mmc_power_off(host);
+ mmc_release_host(host);
+ host->pm_flags = 0;
+ err = 0;
}
}
mmc_bus_put(host);
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 02914d6..54df5ad 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -695,6 +695,11 @@
else if (host->ios.clock <= 200000000)
index = EXT_CSD_PWR_CL_200_195;
break;
+ case MMC_VDD_27_28:
+ case MMC_VDD_28_29:
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ case MMC_VDD_31_32:
case MMC_VDD_32_33:
case MMC_VDD_33_34:
case MMC_VDD_34_35:
@@ -1111,11 +1116,10 @@
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
- if (err) {
- pr_err("%s: power class selection to bus width %d failed\n",
- mmc_hostname(card->host), 1 << bus_width);
- goto err;
- }
+ if (err)
+ pr_warning("%s: power class selection to bus width %d"
+ " failed\n", mmc_hostname(card->host),
+ 1 << bus_width);
}
/*
@@ -1147,10 +1151,10 @@
err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
ext_csd);
if (err)
- pr_err("%s: power class selection to "
- "bus width %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width);
+ pr_warning("%s: power class selection to "
+ "bus width %d failed\n",
+ mmc_hostname(card->host),
+ 1 << bus_width);
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
@@ -1178,10 +1182,10 @@
err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
ext_csd);
if (err)
- pr_err("%s: power class selection to "
- "bus width %d ddr %d failed\n",
- mmc_hostname(card->host),
- 1 << bus_width, ddr);
+ pr_warning("%s: power class selection to "
+ "bus width %d ddr %d failed\n",
+ mmc_hostname(card->host),
+ 1 << bus_width, ddr);
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 40989e6..236842e 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -192,9 +192,15 @@
return ret;
}
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
+
+static int pm_no_operation(struct device *dev)
+{
+ return 0;
+}
static const struct dev_pm_ops sdio_bus_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
@@ -204,11 +210,11 @@
#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)
-#else /* !CONFIG_PM_RUNTIME */
+#else /* !CONFIG_PM */
#define SDIO_PM_OPS_PTR NULL
-#endif /* !CONFIG_PM_RUNTIME */
+#endif /* !CONFIG_PM */
static struct bus_type sdio_bus_type = {
.name = "sdio",
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index 000b3ad..787aba1 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -31,6 +31,7 @@
# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
+# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
#define ATMCI_DTOR 0x0008 /* Data Timeout */
# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 9819dc0..e94476b 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -77,6 +77,7 @@
bool has_cstor_reg;
bool has_highspeed;
bool has_rwproof;
+ bool has_odd_clk_div;
};
struct atmel_mci_dma {
@@ -482,7 +483,14 @@
static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
unsigned int ns)
{
- return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+ /*
+ * It is easier here to use us instead of ns for the timeout,
+ * it prevents from overflows during calculation.
+ */
+ unsigned int us = DIV_ROUND_UP(ns, 1000);
+
+ /* Maximum clock frequency is host->bus_hz/2 */
+ return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
}
static void atmci_set_timeout(struct atmel_mci *host,
@@ -1127,16 +1135,27 @@
}
/* Calculate clock divider */
- clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
- if (clkdiv > 255) {
- dev_warn(&mmc->class_dev,
- "clock %u too slow; using %lu\n",
- clock_min, host->bus_hz / (2 * 256));
- clkdiv = 255;
+ if (host->caps.has_odd_clk_div) {
+ clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
+ if (clkdiv > 511) {
+ dev_warn(&mmc->class_dev,
+ "clock %u too slow; using %lu\n",
+ clock_min, host->bus_hz / (511 + 2));
+ clkdiv = 511;
+ }
+ host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
+ | ATMCI_MR_CLKODD(clkdiv & 1);
+ } else {
+ clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
+ if (clkdiv > 255) {
+ dev_warn(&mmc->class_dev,
+ "clock %u too slow; using %lu\n",
+ clock_min, host->bus_hz / (2 * 256));
+ clkdiv = 255;
+ }
+ host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
}
- host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
-
/*
* WRPROOF and RDPROOF prevent overruns/underruns by
* stopping the clock when the FIFO is full/empty.
@@ -2007,35 +2026,35 @@
"version: 0x%x\n", version);
host->caps.has_dma = 0;
- host->caps.has_pdc = 0;
+ host->caps.has_pdc = 1;
host->caps.has_cfg_reg = 0;
host->caps.has_cstor_reg = 0;
host->caps.has_highspeed = 0;
host->caps.has_rwproof = 0;
+ host->caps.has_odd_clk_div = 0;
/* keep only major version number */
switch (version & 0xf00) {
- case 0x100:
- case 0x200:
- host->caps.has_pdc = 1;
- host->caps.has_rwproof = 1;
- break;
- case 0x300:
- case 0x400:
case 0x500:
+ host->caps.has_odd_clk_div = 1;
+ case 0x400:
+ case 0x300:
#ifdef CONFIG_AT_HDMAC
host->caps.has_dma = 1;
#else
- host->caps.has_dma = 0;
dev_info(&host->pdev->dev,
"has dma capability but dma engine is not selected, then use pio\n");
#endif
+ host->caps.has_pdc = 0;
host->caps.has_cfg_reg = 1;
host->caps.has_cstor_reg = 1;
host->caps.has_highspeed = 1;
+ case 0x200:
host->caps.has_rwproof = 1;
+ case 0x100:
break;
default:
+ host->caps.has_pdc = 0;
dev_warn(&host->pdev->dev,
"Unmanaged mci version, set minimum capabilities\n");
break;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index bf3c9b4..ab3fc46 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -526,8 +526,10 @@
return -ENODEV;
sg_len = dw_mci_pre_dma_transfer(host, data, 0);
- if (sg_len < 0)
+ if (sg_len < 0) {
+ host->dma_ops->stop(host);
return sg_len;
+ }
host->using_dma = 1;
@@ -1879,7 +1881,8 @@
if (!host->dma_ops)
goto no_dma;
- if (host->dma_ops->init) {
+ if (host->dma_ops->init && host->dma_ops->start &&
+ host->dma_ops->stop && host->dma_ops->cleanup) {
if (host->dma_ops->init(host)) {
dev_err(&host->dev, "%s: Unable to initialize "
"DMA Controller.\n", __func__);
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index b0f2ef9..e3f5af9 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -363,6 +363,7 @@
goto out;
dmaengine_submit(desc);
+ dma_async_issue_pending(host->dmach);
return;
out:
@@ -403,6 +404,7 @@
goto out;
dmaengine_submit(desc);
+ dma_async_issue_pending(host->dmach);
return;
out:
@@ -531,6 +533,7 @@
goto out;
dmaengine_submit(desc);
+ dma_async_issue_pending(host->dmach);
return;
out:
dev_warn(mmc_dev(host->mmc),
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 47adb16..56d4499 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -249,7 +249,7 @@
* the pbias cell programming support is still missing when
* booting with Device tree
*/
- if (of_have_populated_dt() && !vdd)
+ if (dev->of_node && !vdd)
return 0;
if (mmc_slot(host).before_set_reg)
@@ -1549,7 +1549,7 @@
* can't be allowed when booting with device
* tree.
*/
- (!of_have_populated_dt())) {
+ !host->dev->of_node) {
/*
* The mmc_select_voltage fn of the core does
* not seem to set the power_mode to
@@ -1741,7 +1741,7 @@
.data = &omap4_reg_offset,
},
{},
-}
+};
MODULE_DEVICE_TABLE(of, omap_mmc_of_match);
static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
@@ -1785,7 +1785,7 @@
}
#endif
-static int __init omap_hsmmc_probe(struct platform_device *pdev)
+static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
{
struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
struct mmc_host *mmc;
@@ -1818,8 +1818,6 @@
if (res == NULL || irq < 0)
return -ENXIO;
- res->start += pdata->reg_offset;
- res->end += pdata->reg_offset;
res = request_mem_region(res->start, resource_size(res), pdev->name);
if (res == NULL)
return -EBUSY;
@@ -1843,7 +1841,7 @@
host->dma_ch = -1;
host->irq = irq;
host->slot_id = 0;
- host->mapbase = res->start;
+ host->mapbase = res->start + pdata->reg_offset;
host->base = ioremap(host->mapbase, SZ_4K);
host->power_mode = MMC_POWER_OFF;
host->next_data.cookie = 1;
@@ -1875,8 +1873,6 @@
goto err1;
}
- omap_hsmmc_context_save(host);
-
if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
@@ -1887,6 +1883,8 @@
pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(host->dev);
+ omap_hsmmc_context_save(host);
+
if (cpu_is_omap2430()) {
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
/*
@@ -2018,8 +2016,7 @@
err_irq_cd_init:
free_irq(host->irq, host);
err_irq:
- pm_runtime_mark_last_busy(host->dev);
- pm_runtime_put_autosuspend(host->dev);
+ pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev);
clk_put(host->fclk);
if (host->got_dbclk) {
@@ -2037,35 +2034,33 @@
return ret;
}
-static int omap_hsmmc_remove(struct platform_device *pdev)
+static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
{
struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
struct resource *res;
- if (host) {
- pm_runtime_get_sync(host->dev);
- mmc_remove_host(host->mmc);
- if (host->use_reg)
- omap_hsmmc_reg_put(host);
- if (host->pdata->cleanup)
- host->pdata->cleanup(&pdev->dev);
- free_irq(host->irq, host);
- if (mmc_slot(host).card_detect_irq)
- free_irq(mmc_slot(host).card_detect_irq, host);
+ pm_runtime_get_sync(host->dev);
+ mmc_remove_host(host->mmc);
+ if (host->use_reg)
+ omap_hsmmc_reg_put(host);
+ if (host->pdata->cleanup)
+ host->pdata->cleanup(&pdev->dev);
+ free_irq(host->irq, host);
+ if (mmc_slot(host).card_detect_irq)
+ free_irq(mmc_slot(host).card_detect_irq, host);
- pm_runtime_put_sync(host->dev);
- pm_runtime_disable(host->dev);
- clk_put(host->fclk);
- if (host->got_dbclk) {
- clk_disable(host->dbclk);
- clk_put(host->dbclk);
- }
-
- mmc_free_host(host->mmc);
- iounmap(host->base);
- omap_hsmmc_gpio_free(pdev->dev.platform_data);
+ pm_runtime_put_sync(host->dev);
+ pm_runtime_disable(host->dev);
+ clk_put(host->fclk);
+ if (host->got_dbclk) {
+ clk_disable(host->dbclk);
+ clk_put(host->dbclk);
}
+ mmc_free_host(host->mmc);
+ iounmap(host->base);
+ omap_hsmmc_gpio_free(pdev->dev.platform_data);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
@@ -2078,49 +2073,45 @@
static int omap_hsmmc_suspend(struct device *dev)
{
int ret = 0;
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+ if (!host)
+ return 0;
if (host && host->suspended)
return 0;
- if (host) {
- pm_runtime_get_sync(host->dev);
- host->suspended = 1;
- if (host->pdata->suspend) {
- ret = host->pdata->suspend(&pdev->dev,
- host->slot_id);
- if (ret) {
- dev_dbg(mmc_dev(host->mmc),
- "Unable to handle MMC board"
- " level suspend\n");
- host->suspended = 0;
- return ret;
- }
- }
- ret = mmc_suspend_host(host->mmc);
-
+ pm_runtime_get_sync(host->dev);
+ host->suspended = 1;
+ if (host->pdata->suspend) {
+ ret = host->pdata->suspend(dev, host->slot_id);
if (ret) {
+ dev_dbg(dev, "Unable to handle MMC board"
+ " level suspend\n");
host->suspended = 0;
- if (host->pdata->resume) {
- ret = host->pdata->resume(&pdev->dev,
- host->slot_id);
- if (ret)
- dev_dbg(mmc_dev(host->mmc),
- "Unmask interrupt failed\n");
- }
- goto err;
+ return ret;
}
-
- if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
- omap_hsmmc_disable_irq(host);
- OMAP_HSMMC_WRITE(host->base, HCTL,
- OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
- }
- if (host->got_dbclk)
- clk_disable(host->dbclk);
-
}
+ ret = mmc_suspend_host(host->mmc);
+
+ if (ret) {
+ host->suspended = 0;
+ if (host->pdata->resume) {
+ ret = host->pdata->resume(dev, host->slot_id);
+ if (ret)
+ dev_dbg(dev, "Unmask interrupt failed\n");
+ }
+ goto err;
+ }
+
+ if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) {
+ omap_hsmmc_disable_irq(host);
+ OMAP_HSMMC_WRITE(host->base, HCTL,
+ OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
+ }
+
+ if (host->got_dbclk)
+ clk_disable(host->dbclk);
err:
pm_runtime_put_sync(host->dev);
return ret;
@@ -2130,39 +2121,38 @@
static int omap_hsmmc_resume(struct device *dev)
{
int ret = 0;
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
+ struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+
+ if (!host)
+ return 0;
if (host && !host->suspended)
return 0;
- if (host) {
- pm_runtime_get_sync(host->dev);
+ pm_runtime_get_sync(host->dev);
- if (host->got_dbclk)
- clk_enable(host->dbclk);
+ if (host->got_dbclk)
+ clk_enable(host->dbclk);
- if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
- omap_hsmmc_conf_bus_power(host);
+ if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
+ omap_hsmmc_conf_bus_power(host);
- if (host->pdata->resume) {
- ret = host->pdata->resume(&pdev->dev, host->slot_id);
- if (ret)
- dev_dbg(mmc_dev(host->mmc),
- "Unmask interrupt failed\n");
- }
-
- omap_hsmmc_protect_card(host);
-
- /* Notify the core to resume the host */
- ret = mmc_resume_host(host->mmc);
- if (ret == 0)
- host->suspended = 0;
-
- pm_runtime_mark_last_busy(host->dev);
- pm_runtime_put_autosuspend(host->dev);
+ if (host->pdata->resume) {
+ ret = host->pdata->resume(dev, host->slot_id);
+ if (ret)
+ dev_dbg(dev, "Unmask interrupt failed\n");
}
+ omap_hsmmc_protect_card(host);
+
+ /* Notify the core to resume the host */
+ ret = mmc_resume_host(host->mmc);
+ if (ret == 0)
+ host->suspended = 0;
+
+ pm_runtime_mark_last_busy(host->dev);
+ pm_runtime_put_autosuspend(host->dev);
+
return ret;
}
@@ -2178,7 +2168,7 @@
host = platform_get_drvdata(to_platform_device(dev));
omap_hsmmc_context_save(host);
- dev_dbg(mmc_dev(host->mmc), "disabled\n");
+ dev_dbg(dev, "disabled\n");
return 0;
}
@@ -2189,7 +2179,7 @@
host = platform_get_drvdata(to_platform_device(dev));
omap_hsmmc_context_restore(host);
- dev_dbg(mmc_dev(host->mmc), "enabled\n");
+ dev_dbg(dev, "enabled\n");
return 0;
}
@@ -2202,7 +2192,8 @@
};
static struct platform_driver omap_hsmmc_driver = {
- .remove = omap_hsmmc_remove,
+ .probe = omap_hsmmc_probe,
+ .remove = __devexit_p(omap_hsmmc_remove),
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
@@ -2211,21 +2202,7 @@
},
};
-static int __init omap_hsmmc_init(void)
-{
- /* Register the MMC driver */
- return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe);
-}
-
-static void __exit omap_hsmmc_cleanup(void)
-{
- /* Unregister MMC driver */
- platform_driver_unregister(&omap_hsmmc_driver);
-}
-
-module_init(omap_hsmmc_init);
-module_exit(omap_hsmmc_cleanup);
-
+module_platform_driver(omap_hsmmc_driver);
MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c
index 46fd1fd..177f697 100644
--- a/drivers/mmc/host/sdhci-dove.c
+++ b/drivers/mmc/host/sdhci-dove.c
@@ -20,6 +20,7 @@
*/
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/mmc/host.h>
#include "sdhci-pltfm.h"
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 6193a0d..8abdaf6 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -467,8 +467,7 @@
clk_prepare_enable(clk);
pltfm_host->clk = clk;
- if (!is_imx25_esdhc(imx_data))
- host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data))
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index fbbebe2..69ef0be 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -1418,8 +1418,6 @@
slots = chip->num_slots; /* Quirk may have changed this */
- pci_enable_msi(pdev);
-
for (i = 0; i < slots; i++) {
slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
if (IS_ERR(slot)) {
@@ -1438,8 +1436,6 @@
return 0;
free:
- pci_disable_msi(pdev);
-
pci_set_drvdata(pdev, NULL);
kfree(chip);
@@ -1462,8 +1458,6 @@
for (i = 0; i < chip->num_slots; i++)
sdhci_pci_remove_slot(chip->slots[i]);
- pci_disable_msi(pdev);
-
pci_set_drvdata(pdev, NULL);
kfree(chip);
}
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c
index b19e7d4..55a164f 100644
--- a/drivers/mmc/host/sdhci-s3c.c
+++ b/drivers/mmc/host/sdhci-s3c.c
@@ -20,6 +20,10 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
#include <linux/mmc/host.h>
@@ -53,6 +57,18 @@
struct clk *clk_bus[MAX_BUS_CLK];
};
+/**
+ * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data
+ * @sdhci_quirks: sdhci host specific quirks.
+ *
+ * Specifies platform specific configuration of sdhci controller.
+ * Note: A structure for driver specific platform data is used for future
+ * expansion of its usage.
+ */
+struct sdhci_s3c_drv_data {
+ unsigned int sdhci_quirks;
+};
+
static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
{
return sdhci_priv(host);
@@ -132,10 +148,10 @@
return UINT_MAX;
/*
- * Clock divider's step is different as 1 from that of host controller
- * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL.
+ * If controller uses a non-standard clock division, find the best clock
+ * speed possible with selected clock source and skip the division.
*/
- if (ourhost->pdata->clk_type) {
+ if (ourhost->host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
rate = clk_round_rate(clksrc, wanted);
return wanted - rate;
}
@@ -272,6 +288,8 @@
static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_s3c *ourhost = to_s3c(host);
+ unsigned long timeout;
+ u16 clk = 0;
/* don't bother if the clock is going off */
if (clock == 0)
@@ -282,6 +300,25 @@
clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock);
host->clock = clock;
+
+ clk = SDHCI_CLOCK_INT_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+ /* Wait max 20 ms */
+ timeout = 20;
+ while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+ & SDHCI_CLOCK_INT_STABLE)) {
+ if (timeout == 0) {
+ printk(KERN_ERR "%s: Internal clock never "
+ "stabilised.\n", mmc_hostname(host->mmc));
+ return;
+ }
+ timeout--;
+ mdelay(1);
+ }
+
+ clk |= SDHCI_CLOCK_CARD_EN;
+ sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
}
/**
@@ -382,16 +419,24 @@
}
}
+static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data(
+ struct platform_device *pdev)
+{
+ return (struct sdhci_s3c_drv_data *)
+ platform_get_device_id(pdev)->driver_data;
+}
+
static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
{
- struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
+ struct s3c_sdhci_platdata *pdata;
+ struct sdhci_s3c_drv_data *drv_data;
struct device *dev = &pdev->dev;
struct sdhci_host *host;
struct sdhci_s3c *sc;
struct resource *res;
int ret, irq, ptr, clks;
- if (!pdata) {
+ if (!pdev->dev.platform_data) {
dev_err(dev, "no device data specified\n");
return -ENOENT;
}
@@ -402,18 +447,20 @@
return irq;
}
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "no memory specified\n");
- return -ENOENT;
- }
-
host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
if (IS_ERR(host)) {
dev_err(dev, "sdhci_alloc_host() failed\n");
return PTR_ERR(host);
}
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ ret = -ENOMEM;
+ goto err_io_clk;
+ }
+ memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata));
+
+ drv_data = sdhci_s3c_get_driver_data(pdev);
sc = sdhci_priv(host);
sc->host = host;
@@ -464,15 +511,8 @@
goto err_no_busclks;
}
- sc->ioarea = request_mem_region(res->start, resource_size(res),
- mmc_hostname(host->mmc));
- if (!sc->ioarea) {
- dev_err(dev, "failed to reserve register area\n");
- ret = -ENXIO;
- goto err_req_regs;
- }
-
- host->ioaddr = ioremap_nocache(res->start, resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ host->ioaddr = devm_request_and_ioremap(&pdev->dev, res);
if (!host->ioaddr) {
dev_err(dev, "failed to map registers\n");
ret = -ENXIO;
@@ -491,6 +531,8 @@
/* Setup quirks for the controller */
host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;
host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT;
+ if (drv_data)
+ host->quirks |= drv_data->sdhci_quirks;
#ifndef CONFIG_MMC_SDHCI_S3C_DMA
@@ -518,6 +560,14 @@
if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
host->mmc->caps = MMC_CAP_NONREMOVABLE;
+ switch (pdata->max_width) {
+ case 8:
+ host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+ case 4:
+ host->mmc->caps |= MMC_CAP_4_BIT_DATA;
+ break;
+ }
+
if (pdata->pm_caps)
host->mmc->pm_caps |= pdata->pm_caps;
@@ -531,7 +581,7 @@
* If controller does not have internal clock divider,
* we can use overriding functions instead of default.
*/
- if (pdata->clk_type) {
+ if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) {
sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock;
sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock;
sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -544,10 +594,17 @@
if (pdata->host_caps2)
host->mmc->caps2 |= pdata->host_caps2;
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_suspend_ignore_children(&pdev->dev, 1);
+
ret = sdhci_add_host(host);
if (ret) {
dev_err(dev, "sdhci_add_host() failed\n");
- goto err_add_host;
+ pm_runtime_forbid(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+ goto err_req_regs;
}
/* The following two methods of card detection might call
@@ -561,10 +618,6 @@
return 0;
- err_add_host:
- release_resource(sc->ioarea);
- kfree(sc->ioarea);
-
err_req_regs:
for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
if (sc->clk_bus[ptr]) {
@@ -601,6 +654,8 @@
sdhci_remove_host(host, 1);
+ pm_runtime_disable(&pdev->dev);
+
for (ptr = 0; ptr < 3; ptr++) {
if (sc->clk_bus[ptr]) {
clk_disable(sc->clk_bus[ptr]);
@@ -610,18 +665,13 @@
clk_disable(sc->clk_io);
clk_put(sc->clk_io);
- iounmap(host->ioaddr);
- release_resource(sc->ioarea);
- kfree(sc->ioarea);
-
sdhci_free_host(host);
platform_set_drvdata(pdev, NULL);
return 0;
}
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
static int sdhci_s3c_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
@@ -635,10 +685,29 @@
return sdhci_resume_host(host);
}
+#endif
+#ifdef CONFIG_PM_RUNTIME
+static int sdhci_s3c_runtime_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+
+ return sdhci_runtime_suspend_host(host);
+}
+
+static int sdhci_s3c_runtime_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+
+ return sdhci_runtime_resume_host(host);
+}
+#endif
+
+#ifdef CONFIG_PM
static const struct dev_pm_ops sdhci_s3c_pmops = {
- .suspend = sdhci_s3c_suspend,
- .resume = sdhci_s3c_resume,
+ SET_SYSTEM_SLEEP_PM_OPS(sdhci_s3c_suspend, sdhci_s3c_resume)
+ SET_RUNTIME_PM_OPS(sdhci_s3c_runtime_suspend, sdhci_s3c_runtime_resume,
+ NULL)
};
#define SDHCI_S3C_PMOPS (&sdhci_s3c_pmops)
@@ -647,9 +716,31 @@
#define SDHCI_S3C_PMOPS NULL
#endif
+#if defined(CONFIG_CPU_EXYNOS4210) || defined(CONFIG_SOC_EXYNOS4212)
+static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = {
+ .sdhci_quirks = SDHCI_QUIRK_NONSTANDARD_CLOCK,
+};
+#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)
+#else
+#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)NULL)
+#endif
+
+static struct platform_device_id sdhci_s3c_driver_ids[] = {
+ {
+ .name = "s3c-sdhci",
+ .driver_data = (kernel_ulong_t)NULL,
+ }, {
+ .name = "exynos4-sdhci",
+ .driver_data = EXYNOS4_SDHCI_DRV_DATA,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids);
+
static struct platform_driver sdhci_s3c_driver = {
.probe = sdhci_s3c_probe,
.remove = __devexit_p(sdhci_s3c_remove),
+ .id_table = sdhci_s3c_driver_ids,
.driver = {
.owner = THIS_MODULE,
.name = "s3c-sdhci",
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 8262cad..ccefdeb 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -147,7 +147,7 @@
u32 present, irqs;
if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) ||
- !mmc_card_is_removable(host->mmc))
+ (host->mmc->caps & MMC_CAP_NONREMOVABLE))
return;
present = sdhci_readl(host, SDHCI_PRESENT_STATE) &
@@ -2782,8 +2782,9 @@
mmc_card_is_removable(mmc))
mmc->caps |= MMC_CAP_NEEDS_POLL;
- /* UHS-I mode(s) supported by the host controller. */
- if (host->version >= SDHCI_SPEC_300)
+ /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
+ if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 |
+ SDHCI_SUPPORT_DDR50))
mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25;
/* SDR104 supports also implies SDR50 support */
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index aafaf0b..724b35e 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -454,7 +454,8 @@
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
else
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
- ((fls(host->clk / clk) - 1) << 16));
+ ((fls(DIV_ROUND_UP(host->clk,
+ clk) - 1) - 1) << 16));
sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
}
@@ -1297,14 +1298,8 @@
spin_lock_init(&host->lock);
mmc->ops = &sh_mmcif_ops;
- mmc->f_max = host->clk;
- /* close to 400KHz */
- if (mmc->f_max < 51200000)
- mmc->f_min = mmc->f_max / 128;
- else if (mmc->f_max < 102400000)
- mmc->f_min = mmc->f_max / 256;
- else
- mmc->f_min = mmc->f_max / 512;
+ mmc->f_max = host->clk / 2;
+ mmc->f_min = host->clk / 512;
if (pd->ocr)
mmc->ocr_avail = pd->ocr;
mmc->caps = MMC_CAP_MMC_HIGHSPEED;
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 94eb05b..58fc65f 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -106,16 +106,14 @@
}
if (mtd->type == MTD_ABSENT) {
- put_mtd_device(mtd);
ret = -ENODEV;
- goto out;
+ goto out1;
}
mtd_ino = iget_locked(mnt->mnt_sb, devnum);
if (!mtd_ino) {
- put_mtd_device(mtd);
ret = -ENOMEM;
- goto out;
+ goto out1;
}
if (mtd_ino->i_state & I_NEW) {
mtd_ino->i_private = mtd;
@@ -127,23 +125,25 @@
/* You can't open it RW if it's not a writeable device */
if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) {
- iput(mtd_ino);
- put_mtd_device(mtd);
ret = -EACCES;
- goto out;
+ goto out2;
}
mfi = kzalloc(sizeof(*mfi), GFP_KERNEL);
if (!mfi) {
- iput(mtd_ino);
- put_mtd_device(mtd);
ret = -ENOMEM;
- goto out;
+ goto out2;
}
mfi->ino = mtd_ino;
mfi->mtd = mtd;
file->private_data = mfi;
+ mutex_unlock(&mtd_mutex);
+ return 0;
+out2:
+ iput(mtd_ino);
+out1:
+ put_mtd_device(mtd);
out:
mutex_unlock(&mtd_mutex);
simple_release_fs(&mnt, &count);
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index 75b1dde..9ec51ce 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -266,6 +266,7 @@
desc->callback = dma_irq_callback;
desc->callback_param = this;
dmaengine_submit(desc);
+ dma_async_issue_pending(get_dma_chan(this));
/* Wait for the interrupt from the DMA block. */
err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000));
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index e2cdebf..61af9bb 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -386,19 +386,11 @@
return count;
}
-static int default_open(struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
/* File operations for all UBI debugfs files */
static const struct file_operations dfs_fops = {
.read = dfs_file_read,
.write = dfs_file_write,
- .open = default_open,
+ .open = simple_open,
.llseek = no_llseek,
.owner = THIS_MODULE,
};
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 25197b6..b8b4c7b 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -89,16 +89,16 @@
BUGLVL(D_NORMAL) printk(VERSION);
BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n");
- BUGMSG(D_NORMAL, "Given: node %02Xh, shmem %lXh, irq %d\n",
+ BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n",
dev->dev_addr[0], dev->mem_start, dev->irq);
if (dev->mem_start <= 0 || dev->irq <= 0) {
- BUGMSG(D_NORMAL, "No autoprobe for RIM I; you "
+ BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you "
"must specify the shmem and irq!\n");
return -ENODEV;
}
if (dev->dev_addr[0] == 0) {
- BUGMSG(D_NORMAL, "You need to specify your card's station "
+ BUGLVL(D_NORMAL) printk("You need to specify your card's station "
"ID!\n");
return -ENODEV;
}
@@ -109,7 +109,7 @@
* will be taken.
*/
if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) {
- BUGMSG(D_NORMAL, "Card memory already allocated\n");
+ BUGLVL(D_NORMAL) printk("Card memory already allocated\n");
return -ENODEV;
}
return arcrimi_found(dev);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 0c76186..62d2409 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -891,9 +891,15 @@
switch (bond->params.fail_over_mac) {
case BOND_FOM_ACTIVE:
- if (new_active)
+ if (new_active) {
memcpy(bond->dev->dev_addr, new_active->dev->dev_addr,
new_active->dev->addr_len);
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+ }
break;
case BOND_FOM_FOLLOW:
/*
@@ -2028,6 +2034,9 @@
write_unlock_bh(&bond->lock);
unblock_netpoll_tx();
+ if (bond->slave_cnt == 0)
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+
bond_compute_features(bond);
if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
(old_features & NETIF_F_VLAN_CHALLENGED))
@@ -3001,7 +3010,11 @@
trans_start + delta_in_ticks)) ||
bond->curr_active_slave != slave) {
slave->link = BOND_LINK_UP;
- bond->current_arp_slave = NULL;
+ if (bond->current_arp_slave) {
+ bond_set_slave_inactive_flags(
+ bond->current_arp_slave);
+ bond->current_arp_slave = NULL;
+ }
pr_info("%s: link status definitely up for interface %s.\n",
bond->dev->name, slave->dev->name);
@@ -3695,17 +3708,52 @@
read_unlock(&bond->lock);
}
-static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
+static int bond_neigh_init(struct neighbour *n)
{
- struct bonding *bond = netdev_priv(dev);
+ struct bonding *bond = netdev_priv(n->dev);
struct slave *slave = bond->first_slave;
+ const struct net_device_ops *slave_ops;
+ struct neigh_parms parms;
+ int ret;
- if (slave) {
- const struct net_device_ops *slave_ops
- = slave->dev->netdev_ops;
- if (slave_ops->ndo_neigh_setup)
- return slave_ops->ndo_neigh_setup(slave->dev, parms);
- }
+ if (!slave)
+ return 0;
+
+ slave_ops = slave->dev->netdev_ops;
+
+ if (!slave_ops->ndo_neigh_setup)
+ return 0;
+
+ parms.neigh_setup = NULL;
+ parms.neigh_cleanup = NULL;
+ ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
+ if (ret)
+ return ret;
+
+ /*
+ * Assign slave's neigh_cleanup to neighbour in case cleanup is called
+ * after the last slave has been detached. Assumes that all slaves
+ * utilize the same neigh_cleanup (true at this writing as only user
+ * is ipoib).
+ */
+ n->parms->neigh_cleanup = parms.neigh_cleanup;
+
+ if (!parms.neigh_setup)
+ return 0;
+
+ return parms.neigh_setup(n);
+}
+
+/*
+ * The bonding ndo_neigh_setup is called at init time beofre any
+ * slave exists. So we must declare proxy setup function which will
+ * be used at run time to resolve the actual slave neigh param setup.
+ */
+static int bond_neigh_setup(struct net_device *dev,
+ struct neigh_parms *parms)
+{
+ parms->neigh_setup = bond_neigh_init;
+
return 0;
}
diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c
index 9a66e2a..9c1c8cd 100644
--- a/drivers/net/caif/caif_hsi.c
+++ b/drivers/net/caif/caif_hsi.c
@@ -744,14 +744,14 @@
size_t fifo_occupancy = 0;
/* Wakeup timeout */
- dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n",
+ dev_dbg(&cfhsi->ndev->dev, "%s: Timeout.\n",
__func__);
/* Check FIFO to check if modem has sent something. */
WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev,
&fifo_occupancy));
- dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
+ dev_dbg(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n",
__func__, (unsigned) fifo_occupancy);
/* Check if we misssed the interrupt. */
@@ -1210,7 +1210,7 @@
static void cfhsi_shutdown(struct cfhsi *cfhsi)
{
- u8 *tx_buf, *rx_buf;
+ u8 *tx_buf, *rx_buf, *flip_buf;
/* Stop TXing */
netif_tx_stop_all_queues(cfhsi->ndev);
@@ -1234,7 +1234,7 @@
/* Store bufferes: will be freed later. */
tx_buf = cfhsi->tx_buf;
rx_buf = cfhsi->rx_buf;
-
+ flip_buf = cfhsi->rx_flip_buf;
/* Flush transmit queues. */
cfhsi_abort_tx(cfhsi);
@@ -1247,6 +1247,7 @@
/* Free buffers. */
kfree(tx_buf);
kfree(rx_buf);
+ kfree(flip_buf);
}
int cfhsi_remove(struct platform_device *pdev)
diff --git a/drivers/net/caif/caif_spi.c b/drivers/net/caif/caif_spi.c
index 96391c3..b71ce9b 100644
--- a/drivers/net/caif/caif_spi.c
+++ b/drivers/net/caif/caif_spi.c
@@ -127,12 +127,6 @@
debugfs_remove(cfspi->dbgfs_dir);
}
-static int dbgfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t dbgfs_state(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -243,13 +237,13 @@
}
static const struct file_operations dbgfs_state_fops = {
- .open = dbgfs_open,
+ .open = simple_open,
.read = dbgfs_state,
.owner = THIS_MODULE
};
static const struct file_operations dbgfs_frame_fops = {
- .open = dbgfs_open,
+ .open = simple_open,
.read = dbgfs_frame,
.owner = THIS_MODULE
};
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index 5234586..629c4ba 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -875,6 +875,7 @@
PCAN_USBPRO_INFO_FW,
&fi, sizeof(fi));
if (err) {
+ kfree(usb_if);
dev_err(dev->netdev->dev.parent,
"unable to read %s firmware info (err %d)\n",
pcan_usb_pro.name, err);
@@ -885,6 +886,7 @@
PCAN_USBPRO_INFO_BL,
&bi, sizeof(bi));
if (err) {
+ kfree(usb_if);
dev_err(dev->netdev->dev.parent,
"unable to read %s bootloader info (err %d)\n",
pcan_usb_pro.name, err);
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index d5c6d92..442d91a 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -107,14 +107,14 @@
return 0;
}
-static void dummy_dev_free(struct net_device *dev)
+static void dummy_dev_uninit(struct net_device *dev)
{
free_percpu(dev->dstats);
- free_netdev(dev);
}
static const struct net_device_ops dummy_netdev_ops = {
.ndo_init = dummy_dev_init,
+ .ndo_uninit = dummy_dev_uninit,
.ndo_start_xmit = dummy_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_rx_mode = set_multicast_list,
@@ -128,7 +128,7 @@
/* Initialize the device structure. */
dev->netdev_ops = &dummy_netdev_ops;
- dev->destructor = dummy_dev_free;
+ dev->destructor = free_netdev;
/* Fill in device structure with ethernet-generic values. */
dev->tx_queue_len = 0;
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index a59cf96..f219d38 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -125,6 +125,7 @@
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_eql.h>
+#include <linux/pkt_sched.h>
#include <asm/uaccess.h>
@@ -143,7 +144,7 @@
equalizer_t *eql = (equalizer_t *) param;
struct list_head *this, *tmp, *head;
- spin_lock_bh(&eql->queue.lock);
+ spin_lock(&eql->queue.lock);
head = &eql->queue.all_slaves;
list_for_each_safe(this, tmp, head) {
slave_t *slave = list_entry(this, slave_t, list);
@@ -157,7 +158,7 @@
}
}
- spin_unlock_bh(&eql->queue.lock);
+ spin_unlock(&eql->queue.lock);
eql->timer.expires = jiffies + EQL_DEFAULT_RESCHED_IVAL;
add_timer(&eql->timer);
@@ -341,7 +342,7 @@
struct net_device *slave_dev = slave->dev;
skb->dev = slave_dev;
- skb->priority = 1;
+ skb->priority = TC_PRIO_FILLER;
slave->bytes_queued += skb->len;
dev_queue_xmit(skb);
dev->stats.tx_packets++;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 40ac414..c926857 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -2476,7 +2476,7 @@
"pcie phy link down %x\n", status);
if (netif_running(adapter->netdev)) { /* reset MAC */
iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
+ schedule_work(&adapter->reset_dev_task);
return IRQ_HANDLED;
}
}
@@ -2488,7 +2488,7 @@
"pcie DMA r/w error (status = 0x%x)\n",
status);
iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
+ schedule_work(&adapter->reset_dev_task);
return IRQ_HANDLED;
}
@@ -2633,10 +2633,10 @@
atl1_clean_rx_ring(adapter);
}
-static void atl1_tx_timeout_task(struct work_struct *work)
+static void atl1_reset_dev_task(struct work_struct *work)
{
struct atl1_adapter *adapter =
- container_of(work, struct atl1_adapter, tx_timeout_task);
+ container_of(work, struct atl1_adapter, reset_dev_task);
struct net_device *netdev = adapter->netdev;
netif_device_detach(netdev);
@@ -3038,12 +3038,10 @@
(unsigned long)adapter);
adapter->phy_timer_pending = false;
- INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+ INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task);
INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
- INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
-
err = register_netdev(netdev);
if (err)
goto err_common;
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h
index 109d6da..e04bf4d 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.h
+++ b/drivers/net/ethernet/atheros/atlx/atl1.h
@@ -758,9 +758,8 @@
u16 link_speed;
u16 link_duplex;
spinlock_t lock;
- struct work_struct tx_timeout_task;
+ struct work_struct reset_dev_task;
struct work_struct link_chg_task;
- struct work_struct pcie_dma_to_rst_task;
struct timer_list phy_config_timer;
bool phy_timer_pending;
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 3cd8837..c9e9dc5 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -194,7 +194,7 @@
{
struct atlx_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
- schedule_work(&adapter->tx_timeout_task);
+ schedule_work(&adapter->reset_dev_task);
}
/*
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index e37161f..2c9ee55 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1173,6 +1173,13 @@
};
+struct bnx2x_prev_path_list {
+ u8 bus;
+ u8 slot;
+ u8 path;
+ struct list_head list;
+};
+
struct bnx2x {
/* Fields used in the tx and intr/napi performance paths
* are grouped together in the beginning of the structure
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index f1f3ca6..4b05481 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -1721,6 +1721,29 @@
} while (0)
#endif
+bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
+{
+ /* build FW version dword */
+ u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
+ (BCM_5710_FW_MINOR_VERSION << 8) +
+ (BCM_5710_FW_REVISION_VERSION << 16) +
+ (BCM_5710_FW_ENGINEERING_VERSION << 24);
+
+ /* read loaded FW from chip */
+ u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
+
+ DP(NETIF_MSG_IFUP, "loaded fw %x, my fw %x\n", loaded_fw, my_fw);
+
+ if (loaded_fw != my_fw) {
+ if (is_err)
+ BNX2X_ERR("bnx2x with FW %x was already loaded, which mismatches my %x FW. aborting\n",
+ loaded_fw, my_fw);
+ return false;
+ }
+
+ return true;
+}
+
/* must be called with rtnl_lock */
int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
{
@@ -1815,23 +1838,8 @@
}
if (load_code != FW_MSG_CODE_DRV_LOAD_COMMON_CHIP &&
load_code != FW_MSG_CODE_DRV_LOAD_COMMON) {
- /* build FW version dword */
- u32 my_fw = (BCM_5710_FW_MAJOR_VERSION) +
- (BCM_5710_FW_MINOR_VERSION << 8) +
- (BCM_5710_FW_REVISION_VERSION << 16) +
- (BCM_5710_FW_ENGINEERING_VERSION << 24);
-
- /* read loaded FW from chip */
- u32 loaded_fw = REG_RD(bp, XSEM_REG_PRAM);
-
- DP(BNX2X_MSG_SP, "loaded fw %x, my fw %x",
- loaded_fw, my_fw);
-
/* abort nic load if version mismatch */
- if (my_fw != loaded_fw) {
- BNX2X_ERR("bnx2x with FW %x already loaded, "
- "which mismatches my %x FW. aborting",
- loaded_fw, my_fw);
+ if (!bnx2x_test_firmware_version(bp, true)) {
rc = -EBUSY;
LOAD_ERROR_EXIT(bp, load_error2);
}
@@ -1866,7 +1874,6 @@
* bnx2x_periodic_task().
*/
smp_mb();
- queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
} else
bp->port.pmf = 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
index 8b16338..5c27454 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
@@ -431,6 +431,9 @@
void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
+/* validate currect fw is loaded */
+bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err);
+
/* dev_close main block */
int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
index cd6dfa9..b9b2633 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
@@ -25,31 +25,31 @@
(IRO[149].base + ((funcId) * IRO[149].m1))
#define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
#define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[315].base + ((pfId) * IRO[315].m1))
-#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
(IRO[316].base + ((pfId) * IRO[316].m1))
+#define CSTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
+ (IRO[317].base + ((pfId) * IRO[317].m1))
#define CSTORM_ISCSI_EQ_CONS_OFFSET(pfId, iscsiEqId) \
- (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
-#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
- (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
(IRO[309].base + ((pfId) * IRO[309].m1) + ((iscsiEqId) * IRO[309].m2))
-#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
+#define CSTORM_ISCSI_EQ_NEXT_EQE_ADDR_OFFSET(pfId, iscsiEqId) \
(IRO[311].base + ((pfId) * IRO[311].m1) + ((iscsiEqId) * IRO[311].m2))
-#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
- (IRO[307].base + ((pfId) * IRO[307].m1) + ((iscsiEqId) * IRO[307].m2))
-#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
- (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
-#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_OFFSET(pfId, iscsiEqId) \
+ (IRO[310].base + ((pfId) * IRO[310].m1) + ((iscsiEqId) * IRO[310].m2))
+#define CSTORM_ISCSI_EQ_NEXT_PAGE_ADDR_VALID_OFFSET(pfId, iscsiEqId) \
(IRO[312].base + ((pfId) * IRO[312].m1) + ((iscsiEqId) * IRO[312].m2))
+#define CSTORM_ISCSI_EQ_PROD_OFFSET(pfId, iscsiEqId) \
+ (IRO[308].base + ((pfId) * IRO[308].m1) + ((iscsiEqId) * IRO[308].m2))
+#define CSTORM_ISCSI_EQ_SB_INDEX_OFFSET(pfId, iscsiEqId) \
+ (IRO[314].base + ((pfId) * IRO[314].m1) + ((iscsiEqId) * IRO[314].m2))
+#define CSTORM_ISCSI_EQ_SB_NUM_OFFSET(pfId, iscsiEqId) \
+ (IRO[313].base + ((pfId) * IRO[313].m1) + ((iscsiEqId) * IRO[313].m2))
#define CSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[314].base + ((pfId) * IRO[314].m1))
+ (IRO[315].base + ((pfId) * IRO[315].m1))
#define CSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[306].base + ((pfId) * IRO[306].m1))
+ (IRO[307].base + ((pfId) * IRO[307].m1))
#define CSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[305].base + ((pfId) * IRO[305].m1))
+ (IRO[306].base + ((pfId) * IRO[306].m1))
#define CSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[304].base + ((pfId) * IRO[304].m1))
+ (IRO[305].base + ((pfId) * IRO[305].m1))
#define CSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
(IRO[151].base + ((funcId) * IRO[151].m1))
#define CSTORM_SP_STATUS_BLOCK_DATA_OFFSET(pfId) \
@@ -96,37 +96,37 @@
#define TSTORM_FUNC_EN_OFFSET(funcId) \
(IRO[103].base + ((funcId) * IRO[103].m1))
#define TSTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
- (IRO[271].base + ((pfId) * IRO[271].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
(IRO[272].base + ((pfId) * IRO[272].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CID_TABLE_OFFSET(pfId) \
(IRO[273].base + ((pfId) * IRO[273].m1))
-#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+#define TSTORM_ISCSI_L2_ISCSI_OOO_CLIENT_ID_TABLE_OFFSET(pfId) \
(IRO[274].base + ((pfId) * IRO[274].m1))
+#define TSTORM_ISCSI_L2_ISCSI_OOO_PROD_OFFSET(pfId) \
+ (IRO[275].base + ((pfId) * IRO[275].m1))
#define TSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[270].base + ((pfId) * IRO[270].m1))
+ (IRO[271].base + ((pfId) * IRO[271].m1))
#define TSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[269].base + ((pfId) * IRO[269].m1))
+ (IRO[270].base + ((pfId) * IRO[270].m1))
#define TSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[268].base + ((pfId) * IRO[268].m1))
+ (IRO[269].base + ((pfId) * IRO[269].m1))
#define TSTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
- (IRO[267].base + ((pfId) * IRO[267].m1))
+ (IRO[268].base + ((pfId) * IRO[268].m1))
#define TSTORM_ISCSI_TCP_LOCAL_ADV_WND_OFFSET(pfId) \
- (IRO[276].base + ((pfId) * IRO[276].m1))
+ (IRO[277].base + ((pfId) * IRO[277].m1))
#define TSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[263].base + ((pfId) * IRO[263].m1))
-#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
(IRO[264].base + ((pfId) * IRO[264].m1))
-#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
+#define TSTORM_ISCSI_TCP_VARS_LSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
(IRO[265].base + ((pfId) * IRO[265].m1))
-#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+#define TSTORM_ISCSI_TCP_VARS_MID_LOCAL_MAC_ADDR_OFFSET(pfId) \
(IRO[266].base + ((pfId) * IRO[266].m1))
+#define TSTORM_ISCSI_TCP_VARS_MSB_LOCAL_MAC_ADDR_OFFSET(pfId) \
+ (IRO[267].base + ((pfId) * IRO[267].m1))
#define TSTORM_MAC_FILTER_CONFIG_OFFSET(pfId) \
(IRO[202].base + ((pfId) * IRO[202].m1))
#define TSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
(IRO[105].base + ((funcId) * IRO[105].m1))
#define TSTORM_TCP_MAX_CWND_OFFSET(pfId) \
- (IRO[216].base + ((pfId) * IRO[216].m1))
+ (IRO[217].base + ((pfId) * IRO[217].m1))
#define TSTORM_VF_TO_PF_OFFSET(funcId) \
(IRO[104].base + ((funcId) * IRO[104].m1))
#define USTORM_AGG_DATA_OFFSET (IRO[206].base)
@@ -140,29 +140,29 @@
#define USTORM_ETH_PAUSE_ENABLED_OFFSET(portId) \
(IRO[183].base + ((portId) * IRO[183].m1))
#define USTORM_FCOE_EQ_PROD_OFFSET(pfId) \
- (IRO[317].base + ((pfId) * IRO[317].m1))
+ (IRO[318].base + ((pfId) * IRO[318].m1))
#define USTORM_FUNC_EN_OFFSET(funcId) \
(IRO[178].base + ((funcId) * IRO[178].m1))
#define USTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
- (IRO[281].base + ((pfId) * IRO[281].m1))
-#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
(IRO[282].base + ((pfId) * IRO[282].m1))
-#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
- (IRO[286].base + ((pfId) * IRO[286].m1))
-#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
+#define USTORM_ISCSI_CQ_SQN_SIZE_OFFSET(pfId) \
(IRO[283].base + ((pfId) * IRO[283].m1))
-#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[279].base + ((pfId) * IRO[279].m1))
-#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[278].base + ((pfId) * IRO[278].m1))
-#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[277].base + ((pfId) * IRO[277].m1))
-#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
- (IRO[280].base + ((pfId) * IRO[280].m1))
-#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
+#define USTORM_ISCSI_ERROR_BITMAP_OFFSET(pfId) \
+ (IRO[287].base + ((pfId) * IRO[287].m1))
+#define USTORM_ISCSI_GLOBAL_BUF_PHYS_ADDR_OFFSET(pfId) \
(IRO[284].base + ((pfId) * IRO[284].m1))
-#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+#define USTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[280].base + ((pfId) * IRO[280].m1))
+#define USTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[279].base + ((pfId) * IRO[279].m1))
+#define USTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[278].base + ((pfId) * IRO[278].m1))
+#define USTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[281].base + ((pfId) * IRO[281].m1))
+#define USTORM_ISCSI_RQ_BUFFER_SIZE_OFFSET(pfId) \
(IRO[285].base + ((pfId) * IRO[285].m1))
+#define USTORM_ISCSI_RQ_SIZE_OFFSET(pfId) \
+ (IRO[286].base + ((pfId) * IRO[286].m1))
#define USTORM_MEM_WORKAROUND_ADDRESS_OFFSET(pfId) \
(IRO[182].base + ((pfId) * IRO[182].m1))
#define USTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
@@ -188,39 +188,39 @@
#define XSTORM_FUNC_EN_OFFSET(funcId) \
(IRO[47].base + ((funcId) * IRO[47].m1))
#define XSTORM_ISCSI_HQ_SIZE_OFFSET(pfId) \
- (IRO[294].base + ((pfId) * IRO[294].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
- (IRO[297].base + ((pfId) * IRO[297].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
- (IRO[298].base + ((pfId) * IRO[298].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
- (IRO[299].base + ((pfId) * IRO[299].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
- (IRO[300].base + ((pfId) * IRO[300].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
- (IRO[301].base + ((pfId) * IRO[301].m1))
-#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
- (IRO[302].base + ((pfId) * IRO[302].m1))
-#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
- (IRO[303].base + ((pfId) * IRO[303].m1))
-#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
- (IRO[293].base + ((pfId) * IRO[293].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
- (IRO[292].base + ((pfId) * IRO[292].m1))
-#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
- (IRO[291].base + ((pfId) * IRO[291].m1))
-#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
- (IRO[296].base + ((pfId) * IRO[296].m1))
-#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
(IRO[295].base + ((pfId) * IRO[295].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR0_OFFSET(pfId) \
+ (IRO[298].base + ((pfId) * IRO[298].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR1_OFFSET(pfId) \
+ (IRO[299].base + ((pfId) * IRO[299].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR2_OFFSET(pfId) \
+ (IRO[300].base + ((pfId) * IRO[300].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR3_OFFSET(pfId) \
+ (IRO[301].base + ((pfId) * IRO[301].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR4_OFFSET(pfId) \
+ (IRO[302].base + ((pfId) * IRO[302].m1))
+#define XSTORM_ISCSI_LOCAL_MAC_ADDR5_OFFSET(pfId) \
+ (IRO[303].base + ((pfId) * IRO[303].m1))
+#define XSTORM_ISCSI_LOCAL_VLAN_OFFSET(pfId) \
+ (IRO[304].base + ((pfId) * IRO[304].m1))
+#define XSTORM_ISCSI_NUM_OF_TASKS_OFFSET(pfId) \
+ (IRO[294].base + ((pfId) * IRO[294].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_LOG_OFFSET(pfId) \
+ (IRO[293].base + ((pfId) * IRO[293].m1))
+#define XSTORM_ISCSI_PAGE_SIZE_OFFSET(pfId) \
+ (IRO[292].base + ((pfId) * IRO[292].m1))
+#define XSTORM_ISCSI_R2TQ_SIZE_OFFSET(pfId) \
+ (IRO[297].base + ((pfId) * IRO[297].m1))
+#define XSTORM_ISCSI_SQ_SIZE_OFFSET(pfId) \
+ (IRO[296].base + ((pfId) * IRO[296].m1))
#define XSTORM_ISCSI_TCP_VARS_ADV_WND_SCL_OFFSET(pfId) \
- (IRO[290].base + ((pfId) * IRO[290].m1))
+ (IRO[291].base + ((pfId) * IRO[291].m1))
#define XSTORM_ISCSI_TCP_VARS_FLAGS_OFFSET(pfId) \
- (IRO[289].base + ((pfId) * IRO[289].m1))
+ (IRO[290].base + ((pfId) * IRO[290].m1))
#define XSTORM_ISCSI_TCP_VARS_TOS_OFFSET(pfId) \
- (IRO[288].base + ((pfId) * IRO[288].m1))
+ (IRO[289].base + ((pfId) * IRO[289].m1))
#define XSTORM_ISCSI_TCP_VARS_TTL_OFFSET(pfId) \
- (IRO[287].base + ((pfId) * IRO[287].m1))
+ (IRO[288].base + ((pfId) * IRO[288].m1))
#define XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET(pfId) \
(IRO[44].base + ((pfId) * IRO[44].m1))
#define XSTORM_RECORD_SLOW_PATH_OFFSET(funcId) \
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
index 5d71b7d..dbff591 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
@@ -1251,6 +1251,9 @@
#define DRV_MSG_CODE_LINK_STATUS_CHANGED 0x01000000
+ #define DRV_MSG_CODE_INITIATE_FLR 0x02000000
+ #define REQ_BC_VER_4_INITIATE_FLR 0x00070213
+
#define BIOS_MSG_CODE_LIC_CHALLENGE 0xff010000
#define BIOS_MSG_CODE_LIC_RESPONSE 0xff020000
#define BIOS_MSG_CODE_VIRT_MAC_PRIM 0xff030000
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index beb4cdb..64392ec 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -35,7 +35,6 @@
#define ETH_MAX_PACKET_SIZE 1500
#define ETH_MAX_JUMBO_PACKET_SIZE 9600
#define MDIO_ACCESS_TIMEOUT 1000
-#define BMAC_CONTROL_RX_ENABLE 2
#define WC_LANE_MAX 4
#define I2C_SWITCH_WIDTH 2
#define I2C_BSC0 0
@@ -943,6 +942,12 @@
const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 :
DCBX_E3B0_MAX_NUM_COS_PORT0;
+ if (pri >= max_num_of_cos) {
+ DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
+ "parameter Illegal strict priority\n");
+ return -EINVAL;
+ }
+
if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) {
DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
"parameter There can't be two COS's with "
@@ -950,12 +955,6 @@
return -EINVAL;
}
- if (pri > max_num_of_cos) {
- DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid "
- "parameter Illegal strict priority\n");
- return -EINVAL;
- }
-
sp_pri_to_cos[pri] = cos_entry;
return 0;
@@ -1372,7 +1371,14 @@
pfc1_val |= XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN |
XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN |
XMAC_PFC_CTRL_HI_REG_RX_PFC_EN |
- XMAC_PFC_CTRL_HI_REG_TX_PFC_EN;
+ XMAC_PFC_CTRL_HI_REG_TX_PFC_EN |
+ XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
+ /* Write pause and PFC registers */
+ REG_WR(bp, xmac_base + XMAC_REG_PAUSE_CTRL, pause_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL, pfc0_val);
+ REG_WR(bp, xmac_base + XMAC_REG_PFC_CTRL_HI, pfc1_val);
+ pfc1_val &= ~XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON;
+
}
/* Write pause and PFC registers */
@@ -3649,6 +3655,33 @@
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) {
bnx2x_cl22_read(bp, phy, 0x4, &ld_pause);
bnx2x_cl22_read(bp, phy, 0x5, &lp_pause);
+ } else if (CHIP_IS_E3(bp) &&
+ SINGLE_MEDIA_DIRECT(params)) {
+ u8 lane = bnx2x_get_warpcore_lane(phy, params);
+ u16 gp_status, gp_mask;
+ bnx2x_cl45_read(bp, phy,
+ MDIO_AN_DEVAD, MDIO_WC_REG_GP2_STATUS_GP_2_4,
+ &gp_status);
+ gp_mask = (MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL |
+ MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP) <<
+ lane;
+ if ((gp_status & gp_mask) == gp_mask) {
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+ } else {
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LD, &ld_pause);
+ bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LP, &lp_pause);
+ ld_pause = ((ld_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+ << 3);
+ lp_pause = ((lp_pause &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH)
+ << 3);
+ }
} else {
bnx2x_cl45_read(bp, phy,
MDIO_AN_DEVAD,
@@ -3699,7 +3732,23 @@
u16 val16 = 0, lane, bam37 = 0;
struct bnx2x *bp = params->bp;
DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
-
+ /* Set to default registers that may be overriden by 10G force */
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_WC_REG_PAR_DET_10G_CTRL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555);
+ bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
+ MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_RX66_CONTROL, 0x7415);
+ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+ MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190);
/* Disable Autoneg: re-enable it after adv is done. */
bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
MDIO_WC_REG_IEEE0BLK_MIICNTL, 0);
@@ -3945,13 +3994,13 @@
} else {
misc1_val |= 0x9;
- tap_val = ((0x12 << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
- (0x2d << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
- (0x00 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
+ tap_val = ((0x0f << MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET) |
+ (0x2b << MDIO_WC_REG_TX_FIR_TAP_MAIN_TAP_OFFSET) |
+ (0x02 << MDIO_WC_REG_TX_FIR_TAP_PRE_TAP_OFFSET));
tx_driver_val =
- ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+ ((0x03 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
(0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
- (0x02 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
+ (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET));
}
bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
MDIO_WC_REG_SERDESDIGITAL_MISC1, misc1_val);
@@ -4369,7 +4418,7 @@
switch (serdes_net_if) {
case PORT_HW_CFG_NET_SERDES_IF_KR:
/* Enable KR Auto Neg */
- if (params->loopback_mode == LOOPBACK_NONE)
+ if (params->loopback_mode != LOOPBACK_EXT)
bnx2x_warpcore_enable_AN_KR(phy, params, vars);
else {
DP(NETIF_MSG_LINK, "Setting KR 10G-Force\n");
@@ -6167,12 +6216,14 @@
tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
if (params->phy[EXT_PHY1].type ==
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
- EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp & 0xfff1);
- else {
- EMAC_WR(bp, EMAC_REG_EMAC_LED,
- (tmp | EMAC_LED_OVERRIDE));
- }
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE)
+ tmp &= ~(EMAC_LED_1000MB_OVERRIDE |
+ EMAC_LED_100MB_OVERRIDE |
+ EMAC_LED_10MB_OVERRIDE);
+ else
+ tmp |= EMAC_LED_OVERRIDE;
+
+ EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp);
break;
case LED_MODE_OPER:
@@ -6227,10 +6278,15 @@
hw_led_mode);
} else if ((params->phy[EXT_PHY1].type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
- (mode != LED_MODE_OPER)) {
+ (mode == LED_MODE_ON)) {
REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp | 0x3);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED, tmp |
+ EMAC_LED_OVERRIDE | EMAC_LED_1000MB_OVERRIDE);
+ /* Break here; otherwise, it'll disable the
+ * intended override.
+ */
+ break;
} else
REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
hw_led_mode);
@@ -6245,13 +6301,9 @@
LED_BLINK_RATE_VAL_E1X_E2);
REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
port*4, 1);
- if ((params->phy[EXT_PHY1].type !=
- PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE) &&
- (mode != LED_MODE_OPER)) {
- tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
- EMAC_WR(bp, EMAC_REG_EMAC_LED,
- (tmp & (~EMAC_LED_OVERRIDE)));
- }
+ tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
+ EMAC_WR(bp, EMAC_REG_EMAC_LED,
+ (tmp & (~EMAC_LED_OVERRIDE)));
if (CHIP_IS_E1(bp) &&
((speed == SPEED_2500) ||
@@ -6844,6 +6896,12 @@
SINGLE_MEDIA_DIRECT(params)) &&
(phy_vars[active_external_phy].fault_detected == 0));
+ /* Update the PFC configuration in case it was changed */
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+ vars->link_status |= LINK_STATUS_PFC_ENABLED;
+ else
+ vars->link_status &= ~LINK_STATUS_PFC_ENABLED;
+
if (vars->link_up)
rc = bnx2x_update_link_up(params, vars, link_10g_plus);
else
@@ -8031,7 +8089,9 @@
netdev_err(bp->dev, "Warning: Unqualified SFP+ module detected,"
" Port %d from %s part number %s\n",
params->port, vendor_name, vendor_pn);
- phy->flags |= FLAGS_SFP_NOT_APPROVED;
+ if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
+ PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG)
+ phy->flags |= FLAGS_SFP_NOT_APPROVED;
return -EINVAL;
}
@@ -9091,6 +9151,12 @@
tmp2 &= 0xFFEF;
bnx2x_cl45_write(bp, phy,
MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
+ bnx2x_cl45_read(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+ &tmp2);
+ bnx2x_cl45_write(bp, phy,
+ MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER,
+ (tmp2 & 0x7fff));
}
return 0;
@@ -9271,12 +9337,11 @@
MDIO_PMA_DEVAD, MDIO_PMA_LASI_RXCTRL,
((1<<5) | (1<<2)));
}
- DP(NETIF_MSG_LINK, "Enabling 8727 TX laser if SFP is approved\n");
- bnx2x_8727_specific_func(phy, params, ENABLE_TX);
- /* If transmitter is disabled, ignore false link up indication */
- bnx2x_cl45_read(bp, phy,
- MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &val1);
- if (val1 & (1<<15)) {
+
+ if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) {
+ DP(NETIF_MSG_LINK, "Enabling 8727 TX laser\n");
+ bnx2x_sfp_set_transmitter(params, phy, 1);
+ } else {
DP(NETIF_MSG_LINK, "Tx is disabled\n");
return 0;
}
@@ -9370,8 +9435,7 @@
if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
- bnx2x_save_spirom_version(bp, port,
- ((fw_ver1 & 0xf000)>>5) | (fw_ver1 & 0x7f),
+ bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
phy->ver_addr);
} else {
/* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
@@ -9794,6 +9858,15 @@
other_shmem_base_addr));
u32 shmem_base_path[2];
+
+ /* Work around for 84833 LED failure inside RESET status */
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_LEGACY_MII_CTRL,
+ MDIO_AN_REG_8481_MII_CTRL_FORCE_1G);
+ bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+ MDIO_AN_REG_8481_1G_100T_EXT_CTRL,
+ MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF);
+
shmem_base_path[0] = params->shmem_base;
shmem_base_path[1] = other_shmem_base_addr;
@@ -10104,7 +10177,7 @@
u8 port;
u16 val16;
- if (!(CHIP_IS_E1(bp)))
+ if (!(CHIP_IS_E1x(bp)))
port = BP_PATH(bp);
else
port = params->port;
@@ -10131,7 +10204,7 @@
u16 val;
u8 port;
- if (!(CHIP_IS_E1(bp)))
+ if (!(CHIP_IS_E1x(bp)))
port = BP_PATH(bp);
else
port = params->port;
@@ -12050,6 +12123,9 @@
bnx2x_emac_init(params, vars);
+ if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
+ vars->link_status |= LINK_STATUS_PFC_ENABLED;
+
if (params->num_phys == 0) {
DP(NETIF_MSG_LINK, "No phy found for initialization !!\n");
return -EINVAL;
@@ -12129,10 +12205,10 @@
* Hold it as vars low
*/
/* clear link led */
+ bnx2x_set_mdio_clk(bp, params->chip_id, port);
bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
if (reset_ext_phy) {
- bnx2x_set_mdio_clk(bp, params->chip_id, port);
for (phy_index = EXT_PHY1; phy_index < params->num_phys;
phy_index++) {
if (params->phy[phy_index].link_reset) {
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
index 7ba557a..763535e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
@@ -89,6 +89,8 @@
#define PFC_BRB_FULL_LB_XON_THRESHOLD 250
#define MAXVAL(a, b) (((a) > (b)) ? (a) : (b))
+
+#define BMAC_CONTROL_RX_ENABLE 2
/***********************************************************/
/* Structs */
/***********************************************************/
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index f7f9aa8..e077d25 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -52,6 +52,7 @@
#include <linux/prefetch.h>
#include <linux/zlib.h>
#include <linux/io.h>
+#include <linux/semaphore.h>
#include <linux/stringify.h>
#include <linux/vmalloc.h>
@@ -211,6 +212,10 @@
MODULE_DEVICE_TABLE(pci, bnx2x_pci_tbl);
+/* Global resources for unloading a previously loaded device */
+#define BNX2X_PREV_WAIT_NEEDED 1
+static DEFINE_SEMAPHORE(bnx2x_prev_sem);
+static LIST_HEAD(bnx2x_prev_list);
/****************************************************************************
* General service functions
****************************************************************************/
@@ -8812,109 +8817,371 @@
bnx2x_undi_int_disable_e1h(bp);
}
-static void __devinit bnx2x_undi_unload(struct bnx2x *bp)
+static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
{
- u32 val;
+ u32 val, base_addr, offset, mask, reset_reg;
+ bool mac_stopped = false;
+ u8 port = BP_PORT(bp);
- /* possibly another driver is trying to reset the chip */
- bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+ reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
- /* check if doorbell queue is reset */
- if (REG_RD(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET)
- & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
+ if (!CHIP_IS_E3(bp)) {
+ val = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port * 4);
+ mask = MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port;
+ if ((mask & reset_reg) && val) {
+ u32 wb_data[2];
+ BNX2X_DEV_INFO("Disable bmac Rx\n");
+ base_addr = BP_PORT(bp) ? NIG_REG_INGRESS_BMAC1_MEM
+ : NIG_REG_INGRESS_BMAC0_MEM;
+ offset = CHIP_IS_E2(bp) ? BIGMAC2_REGISTER_BMAC_CONTROL
+ : BIGMAC_REGISTER_BMAC_CONTROL;
- /*
- * Check if it is the UNDI driver
- * UNDI driver initializes CID offset for normal bell to 0x7
- */
- val = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
- if (val == 0x7) {
- u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
- /* save our pf_num */
- int orig_pf_num = bp->pf_num;
- int port;
- u32 swap_en, swap_val, value;
+ /*
+ * use rd/wr since we cannot use dmae. This is safe
+ * since MCP won't access the bus due to the request
+ * to unload, and no function on the path can be
+ * loaded at this time.
+ */
+ wb_data[0] = REG_RD(bp, base_addr + offset);
+ wb_data[1] = REG_RD(bp, base_addr + offset + 0x4);
+ wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
+ REG_WR(bp, base_addr + offset, wb_data[0]);
+ REG_WR(bp, base_addr + offset + 0x4, wb_data[1]);
- /* clear the UNDI indication */
- REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
+ }
+ BNX2X_DEV_INFO("Disable emac Rx\n");
+ REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0);
- BNX2X_DEV_INFO("UNDI is active! reset device\n");
-
- /* try unload UNDI on port 0 */
- bp->pf_num = 0;
- bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
- reset_code = bnx2x_fw_command(bp, reset_code, 0);
-
- /* if UNDI is loaded on the other port */
- if (reset_code != FW_MSG_CODE_DRV_UNLOAD_COMMON) {
-
- /* send "DONE" for previous unload */
- bnx2x_fw_command(bp,
- DRV_MSG_CODE_UNLOAD_DONE, 0);
-
- /* unload UNDI on port 1 */
- bp->pf_num = 1;
- bp->fw_seq =
- (SHMEM_RD(bp, func_mb[bp->pf_num].drv_mb_header) &
- DRV_MSG_SEQ_NUMBER_MASK);
- reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS;
-
- bnx2x_fw_command(bp, reset_code, 0);
- }
-
- bnx2x_undi_int_disable(bp);
- port = BP_PORT(bp);
-
- /* close input traffic and wait for it */
- /* Do not rcv packets to BRB */
- REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_DRV_MASK :
- NIG_REG_LLH0_BRB1_DRV_MASK), 0x0);
- /* Do not direct rcv packets that are not for MCP to
- * the BRB */
- REG_WR(bp, (port ? NIG_REG_LLH1_BRB1_NOT_MCP :
- NIG_REG_LLH0_BRB1_NOT_MCP), 0x0);
- /* clear AEU */
- REG_WR(bp, (port ? MISC_REG_AEU_MASK_ATTN_FUNC_1 :
- MISC_REG_AEU_MASK_ATTN_FUNC_0), 0);
- msleep(10);
-
- /* save NIG port swap info */
- swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
- swap_en = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
- /* reset device */
- REG_WR(bp,
- GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
- 0xd3ffffff);
-
- value = 0x1400;
- if (CHIP_IS_E3(bp)) {
- value |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
- value |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
- }
-
- REG_WR(bp,
- GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
- value);
-
- /* take the NIG out of reset and restore swap values */
- REG_WR(bp,
- GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET,
- MISC_REGISTERS_RESET_REG_1_RST_NIG);
- REG_WR(bp, NIG_REG_PORT_SWAP, swap_val);
- REG_WR(bp, NIG_REG_STRAP_OVERRIDE, swap_en);
-
- /* send unload done to the MCP */
- bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
-
- /* restore our func and fw_seq */
- bp->pf_num = orig_pf_num;
+ mac_stopped = true;
+ } else {
+ if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) {
+ BNX2X_DEV_INFO("Disable xmac Rx\n");
+ base_addr = BP_PORT(bp) ? GRCBASE_XMAC1 : GRCBASE_XMAC0;
+ val = REG_RD(bp, base_addr + XMAC_REG_PFC_CTRL_HI);
+ REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
+ val & ~(1 << 1));
+ REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
+ val | (1 << 1));
+ REG_WR(bp, base_addr + XMAC_REG_CTRL, 0);
+ mac_stopped = true;
+ }
+ mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
+ if (mask & reset_reg) {
+ BNX2X_DEV_INFO("Disable umac Rx\n");
+ base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
+ REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0);
+ mac_stopped = true;
}
}
- /* now it's safe to release the lock */
- bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+ if (mac_stopped)
+ msleep(20);
+
+}
+
+#define BNX2X_PREV_UNDI_PROD_ADDR(p) (BAR_TSTRORM_INTMEM + 0x1508 + ((p) << 4))
+#define BNX2X_PREV_UNDI_RCQ(val) ((val) & 0xffff)
+#define BNX2X_PREV_UNDI_BD(val) ((val) >> 16 & 0xffff)
+#define BNX2X_PREV_UNDI_PROD(rcq, bd) ((bd) << 16 | (rcq))
+
+static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
+ u8 inc)
+{
+ u16 rcq, bd;
+ u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
+
+ rcq = BNX2X_PREV_UNDI_RCQ(tmp_reg) + inc;
+ bd = BNX2X_PREV_UNDI_BD(tmp_reg) + inc;
+
+ tmp_reg = BNX2X_PREV_UNDI_PROD(rcq, bd);
+ REG_WR(bp, BNX2X_PREV_UNDI_PROD_ADDR(port), tmp_reg);
+
+ BNX2X_DEV_INFO("UNDI producer [%d] rings bd -> 0x%04x, rcq -> 0x%04x\n",
+ port, bd, rcq);
+}
+
+static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
+{
+ u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE, 0);
+ if (!rc) {
+ BNX2X_ERR("MCP response failure, aborting\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
+{
+ struct bnx2x_prev_path_list *tmp_list;
+ int rc = false;
+
+ if (down_trylock(&bnx2x_prev_sem))
+ return false;
+
+ list_for_each_entry(tmp_list, &bnx2x_prev_list, list) {
+ if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
+ bp->pdev->bus->number == tmp_list->bus &&
+ BP_PATH(bp) == tmp_list->path) {
+ rc = true;
+ BNX2X_DEV_INFO("Path %d was already cleaned from previous drivers\n",
+ BP_PATH(bp));
+ break;
+ }
+ }
+
+ up(&bnx2x_prev_sem);
+
+ return rc;
+}
+
+static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
+{
+ struct bnx2x_prev_path_list *tmp_list;
+ int rc;
+
+ tmp_list = (struct bnx2x_prev_path_list *)
+ kmalloc(sizeof(struct bnx2x_prev_path_list), GFP_KERNEL);
+ if (!tmp_list) {
+ BNX2X_ERR("Failed to allocate 'bnx2x_prev_path_list'\n");
+ return -ENOMEM;
+ }
+
+ tmp_list->bus = bp->pdev->bus->number;
+ tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
+ tmp_list->path = BP_PATH(bp);
+
+ rc = down_interruptible(&bnx2x_prev_sem);
+ if (rc) {
+ BNX2X_ERR("Received %d when tried to take lock\n", rc);
+ kfree(tmp_list);
+ } else {
+ BNX2X_DEV_INFO("Marked path [%d] - finished previous unload\n",
+ BP_PATH(bp));
+ list_add(&tmp_list->list, &bnx2x_prev_list);
+ up(&bnx2x_prev_sem);
+ }
+
+ return rc;
+}
+
+static bool __devinit bnx2x_can_flr(struct bnx2x *bp)
+{
+ int pos;
+ u32 cap;
+ struct pci_dev *dev = bp->pdev;
+
+ pos = pci_pcie_cap(dev);
+ if (!pos)
+ return false;
+
+ pci_read_config_dword(dev, pos + PCI_EXP_DEVCAP, &cap);
+ if (!(cap & PCI_EXP_DEVCAP_FLR))
+ return false;
+
+ return true;
+}
+
+static int __devinit bnx2x_do_flr(struct bnx2x *bp)
+{
+ int i, pos;
+ u16 status;
+ struct pci_dev *dev = bp->pdev;
+
+ /* probe the capability first */
+ if (bnx2x_can_flr(bp))
+ return -ENOTTY;
+
+ pos = pci_pcie_cap(dev);
+ if (!pos)
+ return -ENOTTY;
+
+ /* Wait for Transaction Pending bit clean */
+ for (i = 0; i < 4; i++) {
+ if (i)
+ msleep((1 << (i - 1)) * 100);
+
+ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &status);
+ if (!(status & PCI_EXP_DEVSTA_TRPND))
+ goto clear;
+ }
+
+ dev_err(&dev->dev,
+ "transaction is not cleared; proceeding with reset anyway\n");
+
+clear:
+ if (bp->common.bc_ver < REQ_BC_VER_4_INITIATE_FLR) {
+ BNX2X_ERR("FLR not supported by BC_VER: 0x%x\n",
+ bp->common.bc_ver);
+ return -EINVAL;
+ }
+
+ bnx2x_fw_command(bp, DRV_MSG_CODE_INITIATE_FLR, 0);
+
+ return 0;
+}
+
+static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+{
+ int rc;
+
+ BNX2X_DEV_INFO("Uncommon unload Flow\n");
+
+ /* Test if previous unload process was already finished for this path */
+ if (bnx2x_prev_is_path_marked(bp))
+ return bnx2x_prev_mcp_done(bp);
+
+ /* If function has FLR capabilities, and existing FW version matches
+ * the one required, then FLR will be sufficient to clean any residue
+ * left by previous driver
+ */
+ if (bnx2x_test_firmware_version(bp, false) && bnx2x_can_flr(bp))
+ return bnx2x_do_flr(bp);
+
+ /* Close the MCP request, return failure*/
+ rc = bnx2x_prev_mcp_done(bp);
+ if (!rc)
+ rc = BNX2X_PREV_WAIT_NEEDED;
+
+ return rc;
+}
+
+static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
+{
+ u32 reset_reg, tmp_reg = 0, rc;
+ /* It is possible a previous function received 'common' answer,
+ * but hasn't loaded yet, therefore creating a scenario of
+ * multiple functions receiving 'common' on the same path.
+ */
+ BNX2X_DEV_INFO("Common unload Flow\n");
+
+ if (bnx2x_prev_is_path_marked(bp))
+ return bnx2x_prev_mcp_done(bp);
+
+ reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
+
+ /* Reset should be performed after BRB is emptied */
+ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
+ u32 timer_count = 1000;
+ bool prev_undi = false;
+
+ /* Close the MAC Rx to prevent BRB from filling up */
+ bnx2x_prev_unload_close_mac(bp);
+
+ /* Check if the UNDI driver was previously loaded
+ * UNDI driver initializes CID offset for normal bell to 0x7
+ */
+ reset_reg = REG_RD(bp, MISC_REG_RESET_REG_1);
+ if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_DORQ) {
+ tmp_reg = REG_RD(bp, DORQ_REG_NORM_CID_OFST);
+ if (tmp_reg == 0x7) {
+ BNX2X_DEV_INFO("UNDI previously loaded\n");
+ prev_undi = true;
+ /* clear the UNDI indication */
+ REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0);
+ }
+ }
+ /* wait until BRB is empty */
+ tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
+ while (timer_count) {
+ u32 prev_brb = tmp_reg;
+
+ tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
+ if (!tmp_reg)
+ break;
+
+ BNX2X_DEV_INFO("BRB still has 0x%08x\n", tmp_reg);
+
+ /* reset timer as long as BRB actually gets emptied */
+ if (prev_brb > tmp_reg)
+ timer_count = 1000;
+ else
+ timer_count--;
+
+ /* If UNDI resides in memory, manually increment it */
+ if (prev_undi)
+ bnx2x_prev_unload_undi_inc(bp, BP_PORT(bp), 1);
+
+ udelay(10);
+ }
+
+ if (!timer_count)
+ BNX2X_ERR("Failed to empty BRB, hope for the best\n");
+
+ }
+
+ /* No packets are in the pipeline, path is ready for reset */
+ bnx2x_reset_common(bp);
+
+ rc = bnx2x_prev_mark_path(bp);
+ if (rc) {
+ bnx2x_prev_mcp_done(bp);
+ return rc;
+ }
+
+ return bnx2x_prev_mcp_done(bp);
+}
+
+static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
+{
+ int time_counter = 10;
+ u32 rc, fw, hw_lock_reg, hw_lock_val;
+ BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
+
+ /* Release previously held locks */
+ hw_lock_reg = (BP_FUNC(bp) <= 5) ?
+ (MISC_REG_DRIVER_CONTROL_1 + BP_FUNC(bp) * 8) :
+ (MISC_REG_DRIVER_CONTROL_7 + (BP_FUNC(bp) - 6) * 8);
+
+ hw_lock_val = (REG_RD(bp, hw_lock_reg));
+ if (hw_lock_val) {
+ if (hw_lock_val & HW_LOCK_RESOURCE_NVRAM) {
+ BNX2X_DEV_INFO("Release Previously held NVRAM lock\n");
+ REG_WR(bp, MCP_REG_MCPR_NVM_SW_ARB,
+ (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << BP_PORT(bp)));
+ }
+
+ BNX2X_DEV_INFO("Release Previously held hw lock\n");
+ REG_WR(bp, hw_lock_reg, 0xffffffff);
+ } else
+ BNX2X_DEV_INFO("No need to release hw/nvram locks\n");
+
+ if (MCPR_ACCESS_LOCK_LOCK & REG_RD(bp, MCP_REG_MCPR_ACCESS_LOCK)) {
+ BNX2X_DEV_INFO("Release previously held alr\n");
+ REG_WR(bp, MCP_REG_MCPR_ACCESS_LOCK, 0);
+ }
+
+
+ do {
+ /* Lock MCP using an unload request */
+ fw = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS, 0);
+ if (!fw) {
+ BNX2X_ERR("MCP response failure, aborting\n");
+ rc = -EBUSY;
+ break;
+ }
+
+ if (fw == FW_MSG_CODE_DRV_UNLOAD_COMMON) {
+ rc = bnx2x_prev_unload_common(bp);
+ break;
+ }
+
+ /* non-common reply from MCP night require looping */
+ rc = bnx2x_prev_unload_uncommon(bp);
+ if (rc != BNX2X_PREV_WAIT_NEEDED)
+ break;
+
+ msleep(20);
+ } while (--time_counter);
+
+ if (!time_counter || rc) {
+ BNX2X_ERR("Failed unloading previous driver, aborting\n");
+ rc = -EBUSY;
+ }
+
+ BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
+
+ return rc;
}
static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
@@ -10100,8 +10367,16 @@
func = BP_FUNC(bp);
/* need to reset chip if undi was active */
- if (!BP_NOMCP(bp))
- bnx2x_undi_unload(bp);
+ if (!BP_NOMCP(bp)) {
+ /* init fw_seq */
+ bp->fw_seq =
+ SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
+ DRV_MSG_SEQ_NUMBER_MASK;
+ BNX2X_DEV_INFO("fw_seq 0x%08x\n", bp->fw_seq);
+
+ bnx2x_prev_unload(bp);
+ }
+
if (CHIP_REV_IS_FPGA(bp))
dev_err(&bp->pdev->dev, "FPGA detected\n");
@@ -11431,9 +11706,18 @@
static void __exit bnx2x_cleanup(void)
{
+ struct list_head *pos, *q;
pci_unregister_driver(&bnx2x_pci_driver);
destroy_workqueue(bnx2x_wq);
+
+ /* Free globablly allocated resources */
+ list_for_each_safe(pos, q, &bnx2x_prev_list) {
+ struct bnx2x_prev_path_list *tmp =
+ list_entry(pos, struct bnx2x_prev_path_list, list);
+ list_del(pos);
+ kfree(tmp);
+ }
}
void bnx2x_notify_link_changed(struct bnx2x *bp)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
index fd7fb45..c25803b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
@@ -987,6 +987,7 @@
* clear; 1 = set. Data valid only in addresses 0-4. all the rest are zero. */
#define IGU_REG_WRITE_DONE_PENDING 0x130480
#define MCP_A_REG_MCPR_SCRATCH 0x3a0000
+#define MCP_REG_MCPR_ACCESS_LOCK 0x8009c
#define MCP_REG_MCPR_CPU_PROGRAM_COUNTER 0x8501c
#define MCP_REG_MCPR_GP_INPUTS 0x800c0
#define MCP_REG_MCPR_GP_OENABLE 0x800c8
@@ -1686,6 +1687,7 @@
[10] rst_dbg; [11] rst_misc_core; [12] rst_dbue (UART); [13]
Pci_resetmdio_n; [14] rst_emac0_hard_core; [15] rst_emac1_hard_core; 16]
rst_pxp_rq_rd_wr; 31:17] reserved */
+#define MISC_REG_RESET_REG_1 0xa580
#define MISC_REG_RESET_REG_2 0xa590
/* [RW 20] 20 bit GRC address where the scratch-pad of the MCP that is
shared with the driver resides */
@@ -5352,6 +5354,7 @@
#define XMAC_CTRL_REG_TX_EN (0x1<<0)
#define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN (0x1<<18)
#define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN (0x1<<17)
+#define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON (0x1<<1)
#define XMAC_PFC_CTRL_HI_REG_PFC_REFRESH_EN (0x1<<0)
#define XMAC_PFC_CTRL_HI_REG_PFC_STATS_EN (0x1<<3)
#define XMAC_PFC_CTRL_HI_REG_RX_PFC_EN (0x1<<4)
@@ -5606,6 +5609,7 @@
/* [RC 32] Parity register #0 read clear */
#define XSEM_REG_XSEM_PRTY_STS_CLR_0 0x280128
#define XSEM_REG_XSEM_PRTY_STS_CLR_1 0x280138
+#define MCPR_ACCESS_LOCK_LOCK (1L<<31)
#define MCPR_NVM_ACCESS_ENABLE_EN (1L<<0)
#define MCPR_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
#define MCPR_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
@@ -5732,6 +5736,7 @@
#define MISC_REGISTERS_GPIO_PORT_SHIFT 4
#define MISC_REGISTERS_GPIO_SET_POS 8
#define MISC_REGISTERS_RESET_REG_1_CLEAR 0x588
+#define MISC_REGISTERS_RESET_REG_1_RST_BRB1 (0x1<<0)
#define MISC_REGISTERS_RESET_REG_1_RST_DORQ (0x1<<19)
#define MISC_REGISTERS_RESET_REG_1_RST_HC (0x1<<29)
#define MISC_REGISTERS_RESET_REG_1_RST_NIG (0x1<<7)
@@ -6816,10 +6821,13 @@
#define MDIO_AN_REG_8481_10GBASE_T_AN_CTRL 0x0020
#define MDIO_AN_REG_8481_LEGACY_MII_CTRL 0xffe0
+#define MDIO_AN_REG_8481_MII_CTRL_FORCE_1G 0x40
#define MDIO_AN_REG_8481_LEGACY_MII_STATUS 0xffe1
#define MDIO_AN_REG_8481_LEGACY_AN_ADV 0xffe4
#define MDIO_AN_REG_8481_LEGACY_AN_EXPANSION 0xffe6
#define MDIO_AN_REG_8481_1000T_CTRL 0xffe9
+#define MDIO_AN_REG_8481_1G_100T_EXT_CTRL 0xfff0
+#define MIDO_AN_REG_8481_EXT_CTRL_FORCE_LEDS_OFF 0x0008
#define MDIO_AN_REG_8481_EXPANSION_REG_RD_RW 0xfff5
#define MDIO_AN_REG_8481_EXPANSION_REG_ACCESS 0xfff7
#define MDIO_AN_REG_8481_AUX_CTRL 0xfff8
@@ -6939,6 +6947,10 @@
#define MDIO_WC_REG_GP2_STATUS_GP_2_2 0x81d2
#define MDIO_WC_REG_GP2_STATUS_GP_2_3 0x81d3
#define MDIO_WC_REG_GP2_STATUS_GP_2_4 0x81d4
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL73_AN_CMPL 0x1000
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CMPL 0x0100
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_LP_AN_CAP 0x0010
+#define MDIO_WC_REG_GP2_STATUS_GP_2_4_CL37_AN_CAP 0x1
#define MDIO_WC_REG_UC_INFO_B0_DEAD_TRAP 0x81EE
#define MDIO_WC_REG_UC_INFO_B1_VERSION 0x81F0
#define MDIO_WC_REG_UC_INFO_B1_FIRMWARE_MODE 0x81F2
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
index 3f52fad..5135733 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
@@ -3847,7 +3847,7 @@
continue;
/* If we've got here we are going to find a free entry */
- for (idx = vec * BNX2X_POOL_VEC_SIZE, i = 0;
+ for (idx = vec * BIT_VEC64_ELEM_SZ, i = 0;
i < BIT_VEC64_ELEM_SZ; idx++, i++)
if (BIT_VEC64_TEST_BIT(o->pool_mirror, idx)) {
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 4e4bb38..ceeab8e 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -879,8 +879,13 @@
if (sblk->status & SD_STATUS_LINK_CHG)
work_exists = 1;
}
- /* check for RX/TX work to do */
- if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
+
+ /* check for TX work to do */
+ if (sblk->idx[0].tx_consumer != tnapi->tx_cons)
+ work_exists = 1;
+
+ /* check for RX work to do */
+ if (tnapi->rx_rcb_prod_idx &&
*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
work_exists = 1;
@@ -2778,7 +2783,9 @@
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
- (tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
+ (tp->phy_flags & TG3_PHYFLG_MII_SERDES)) ||
+ (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 &&
+ !tp->pci_fn))
return;
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
@@ -6122,6 +6129,9 @@
return work_done;
}
+ if (!tnapi->rx_rcb_prod_idx)
+ return work_done;
+
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
* code synchronizes with tg3->napi.poll()
@@ -7565,6 +7575,12 @@
*/
switch (i) {
default:
+ if (tg3_flag(tp, ENABLE_RSS)) {
+ tnapi->rx_rcb_prod_idx = NULL;
+ break;
+ }
+ /* Fall through */
+ case 1:
tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
break;
case 2:
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 63bfdd1..abb6ce7 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -1150,6 +1150,48 @@
}
/**
+ * t3_synchronize_rx - wait for current Rx processing on a port to complete
+ * @adap: the adapter
+ * @p: the port
+ *
+ * Ensures that current Rx processing on any of the queues associated with
+ * the given port completes before returning. We do this by acquiring and
+ * releasing the locks of the response queues associated with the port.
+ */
+static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
+{
+ int i;
+
+ for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
+ struct sge_rspq *q = &adap->sge.qs[i].rspq;
+
+ spin_lock_irq(&q->lock);
+ spin_unlock_irq(&q->lock);
+ }
+}
+
+static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adapter = pi->adapter;
+
+ if (adapter->params.rev > 0) {
+ t3_set_vlan_accel(adapter, 1 << pi->port_id,
+ features & NETIF_F_HW_VLAN_RX);
+ } else {
+ /* single control for all ports */
+ unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
+
+ for_each_port(adapter, i)
+ have_vlans |=
+ adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
+
+ t3_set_vlan_accel(adapter, 1, have_vlans);
+ }
+ t3_synchronize_rx(adapter, pi);
+}
+
+/**
* cxgb_up - enable the adapter
* @adapter: adapter being enabled
*
@@ -1161,7 +1203,7 @@
*/
static int cxgb_up(struct adapter *adap)
{
- int err;
+ int i, err;
if (!(adap->flags & FULL_INIT_DONE)) {
err = t3_check_fw_version(adap);
@@ -1198,6 +1240,9 @@
if (err)
goto out;
+ for_each_port(adap, i)
+ cxgb_vlan_mode(adap->port[i], adap->port[i]->features);
+
setup_rss(adap);
if (!(adap->flags & NAPI_INIT))
init_napi(adap);
@@ -2508,48 +2553,6 @@
return 0;
}
-/**
- * t3_synchronize_rx - wait for current Rx processing on a port to complete
- * @adap: the adapter
- * @p: the port
- *
- * Ensures that current Rx processing on any of the queues associated with
- * the given port completes before returning. We do this by acquiring and
- * releasing the locks of the response queues associated with the port.
- */
-static void t3_synchronize_rx(struct adapter *adap, const struct port_info *p)
-{
- int i;
-
- for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
- struct sge_rspq *q = &adap->sge.qs[i].rspq;
-
- spin_lock_irq(&q->lock);
- spin_unlock_irq(&q->lock);
- }
-}
-
-static void cxgb_vlan_mode(struct net_device *dev, netdev_features_t features)
-{
- struct port_info *pi = netdev_priv(dev);
- struct adapter *adapter = pi->adapter;
-
- if (adapter->params.rev > 0) {
- t3_set_vlan_accel(adapter, 1 << pi->port_id,
- features & NETIF_F_HW_VLAN_RX);
- } else {
- /* single control for all ports */
- unsigned int i, have_vlans = features & NETIF_F_HW_VLAN_RX;
-
- for_each_port(adapter, i)
- have_vlans |=
- adapter->port[i]->features & NETIF_F_HW_VLAN_RX;
-
- t3_set_vlan_accel(adapter, 1, have_vlans);
- }
- t3_synchronize_rx(adapter, pi);
-}
-
static netdev_features_t cxgb_fix_features(struct net_device *dev,
netdev_features_t features)
{
@@ -3353,9 +3356,6 @@
err = sysfs_create_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
- for_each_port(adapter, i)
- cxgb_vlan_mode(adapter->port[i], adapter->port[i]->features);
-
print_port_info(adapter, ai);
return 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 05ff076a..b126b98 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2000,13 +2000,6 @@
/*
* debugfs support
*/
-
-static int mem_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
@@ -2050,7 +2043,7 @@
static const struct file_operations mem_debugfs_fops = {
.owner = THIS_MODULE,
- .open = mem_open,
+ .open = simple_open,
.read = mem_read,
.llseek = default_llseek,
};
diff --git a/drivers/net/ethernet/dlink/dl2k.c b/drivers/net/ethernet/dlink/dl2k.c
index b2dc2c8..2e09edb 100644
--- a/drivers/net/ethernet/dlink/dl2k.c
+++ b/drivers/net/ethernet/dlink/dl2k.c
@@ -1259,55 +1259,21 @@
{
int phy_addr;
struct netdev_private *np = netdev_priv(dev);
- struct mii_data *miidata = (struct mii_data *) &rq->ifr_ifru;
-
- struct netdev_desc *desc;
- int i;
+ struct mii_ioctl_data *miidata = if_mii(rq);
phy_addr = np->phy_addr;
switch (cmd) {
- case SIOCDEVPRIVATE:
+ case SIOCGMIIPHY:
+ miidata->phy_id = phy_addr;
break;
-
- case SIOCDEVPRIVATE + 1:
- miidata->out_value = mii_read (dev, phy_addr, miidata->reg_num);
+ case SIOCGMIIREG:
+ miidata->val_out = mii_read (dev, phy_addr, miidata->reg_num);
break;
- case SIOCDEVPRIVATE + 2:
- mii_write (dev, phy_addr, miidata->reg_num, miidata->in_value);
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ mii_write (dev, phy_addr, miidata->reg_num, miidata->val_in);
break;
- case SIOCDEVPRIVATE + 3:
- break;
- case SIOCDEVPRIVATE + 4:
- break;
- case SIOCDEVPRIVATE + 5:
- netif_stop_queue (dev);
- break;
- case SIOCDEVPRIVATE + 6:
- netif_wake_queue (dev);
- break;
- case SIOCDEVPRIVATE + 7:
- printk
- ("tx_full=%x cur_tx=%lx old_tx=%lx cur_rx=%lx old_rx=%lx\n",
- netif_queue_stopped(dev), np->cur_tx, np->old_tx, np->cur_rx,
- np->old_rx);
- break;
- case SIOCDEVPRIVATE + 8:
- printk("TX ring:\n");
- for (i = 0; i < TX_RING_SIZE; i++) {
- desc = &np->tx_ring[i];
- printk
- ("%02x:cur:%08x next:%08x status:%08x frag1:%08x frag0:%08x",
- i,
- (u32) (np->tx_ring_dma + i * sizeof (*desc)),
- (u32)le64_to_cpu(desc->next_desc),
- (u32)le64_to_cpu(desc->status),
- (u32)(le64_to_cpu(desc->fraginfo) >> 32),
- (u32)le64_to_cpu(desc->fraginfo));
- printk ("\n");
- }
- printk ("\n");
- break;
-
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/dlink/dl2k.h b/drivers/net/ethernet/dlink/dl2k.h
index ba0adca..30c2da3 100644
--- a/drivers/net/ethernet/dlink/dl2k.h
+++ b/drivers/net/ethernet/dlink/dl2k.h
@@ -365,13 +365,6 @@
char *data;
};
-struct mii_data {
- __u16 reserved;
- __u16 reg_num;
- __u16 in_value;
- __u16 out_value;
-};
-
/* The Rx and Tx buffer descriptors. */
struct netdev_desc {
__le64 next_desc;
diff --git a/drivers/net/ethernet/freescale/fsl_pq_mdio.c b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
index 9eb8159..f7f0bf5 100644
--- a/drivers/net/ethernet/freescale/fsl_pq_mdio.c
+++ b/drivers/net/ethernet/freescale/fsl_pq_mdio.c
@@ -356,13 +356,13 @@
if (prop)
tbiaddr = *prop;
- }
- if (tbiaddr == -1) {
- err = -EBUSY;
- goto err_free_irqs;
- } else {
- out_be32(tbipa, tbiaddr);
+ if (tbiaddr == -1) {
+ err = -EBUSY;
+ goto err_free_irqs;
+ } else {
+ out_be32(tbipa, tbiaddr);
+ }
}
err = of_mdiobus_register(new_bus, np);
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 4e3cd2f..9ac14f8 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -116,10 +116,10 @@
.maxGroupAddrInHash = 4,
.maxIndAddrInHash = 4,
.prel = 7,
- .maxFrameLength = 1518,
+ .maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
.minFrameLength = 64,
- .maxD1Length = 1520,
- .maxD2Length = 1520,
+ .maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
+ .maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */
.vlantype = 0x8100,
.ecamptr = ((uint32_t) NULL),
.eventRegMask = UCCE_OTHER,
@@ -3945,6 +3945,8 @@
}
if (max_speed == SPEED_1000) {
+ unsigned int snums = qe_get_num_of_snums();
+
/* configure muram FIFOs for gigabit operation */
ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
@@ -3954,11 +3956,11 @@
ug_info->uf_info.utftt = UCC_GETH_UTFTT_GIGA_INIT;
ug_info->numThreadsTx = UCC_GETH_NUM_OF_THREADS_4;
- /* If QE's snum number is 46 which means we need to support
+ /* If QE's snum number is 46/76 which means we need to support
* 4 UECs at 1000Base-T simultaneously, we need to allocate
* more Threads to Rx.
*/
- if (qe_get_num_of_snums() == 46)
+ if ((snums == 76) || (snums == 46))
ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_6;
else
ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4;
diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h
index 2e395a2..f71b3e7 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.h
+++ b/drivers/net/ethernet/freescale/ucc_geth.h
@@ -877,7 +877,7 @@
/* Driver definitions */
#define TX_BD_RING_LEN 0x10
-#define RX_BD_RING_LEN 0x10
+#define RX_BD_RING_LEN 0x20
#define TX_RING_MOD_MASK(size) (size-1)
#define RX_RING_MOD_MASK(size) (size-1)
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c
index 3516e17..c9069a2 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_main.c
+++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c
@@ -290,16 +290,18 @@
arr[i].adh = adapter->handle;
arr[i].port_id = port->logical_port_id;
- arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
- EHEA_BCMC_MULTICAST |
+ arr[i].reg_type = EHEA_BCMC_MULTICAST |
EHEA_BCMC_UNTAGGED;
+ if (mc_entry->macaddr == 0)
+ arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
arr[i++].macaddr = mc_entry->macaddr;
arr[i].adh = adapter->handle;
arr[i].port_id = port->logical_port_id;
- arr[i].reg_type = EHEA_BCMC_SCOPE_ALL |
- EHEA_BCMC_MULTICAST |
+ arr[i].reg_type = EHEA_BCMC_MULTICAST |
EHEA_BCMC_VLANID_ALL;
+ if (mc_entry->macaddr == 0)
+ arr[i].reg_type |= EHEA_BCMC_SCOPE_ALL;
arr[i++].macaddr = mc_entry->macaddr;
num_registrations -= 2;
}
@@ -1838,8 +1840,9 @@
u64 hret;
u8 reg_type;
- reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
- | EHEA_BCMC_UNTAGGED;
+ reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_UNTAGGED;
+ if (mc_mac_addr == 0)
+ reg_type |= EHEA_BCMC_SCOPE_ALL;
hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
port->logical_port_id,
@@ -1847,8 +1850,9 @@
if (hret)
goto out;
- reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
- | EHEA_BCMC_VLANID_ALL;
+ reg_type = EHEA_BCMC_MULTICAST | EHEA_BCMC_VLANID_ALL;
+ if (mc_mac_addr == 0)
+ reg_type |= EHEA_BCMC_SCOPE_ALL;
hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
port->logical_port_id,
@@ -1898,7 +1902,7 @@
netdev_err(dev,
"failed enabling IFF_ALLMULTI\n");
}
- } else
+ } else {
if (!enable) {
/* Disable ALLMULTI */
hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
@@ -1908,6 +1912,7 @@
netdev_err(dev,
"failed disabling IFF_ALLMULTI\n");
}
+ }
}
static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
@@ -1941,11 +1946,7 @@
struct netdev_hw_addr *ha;
int ret;
- if (port->promisc) {
- ehea_promiscuous(dev, 1);
- return;
- }
- ehea_promiscuous(dev, 0);
+ ehea_promiscuous(dev, !!(dev->flags & IFF_PROMISC));
if (dev->flags & IFF_ALLMULTI) {
ehea_allmulti(dev, 1);
@@ -2463,6 +2464,7 @@
return 0;
ehea_drop_multicast_list(dev);
+ ehea_allmulti(dev, 0);
ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
ehea_free_interrupts(dev);
@@ -3261,6 +3263,7 @@
struct ehea_adapter *adapter;
const u64 *adapter_handle;
int ret;
+ int i;
if (!dev || !dev->dev.of_node) {
pr_err("Invalid ibmebus device probed\n");
@@ -3314,17 +3317,9 @@
tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
(unsigned long)adapter);
- ret = ibmebus_request_irq(adapter->neq->attr.ist1,
- ehea_interrupt_neq, IRQF_DISABLED,
- "ehea_neq", adapter);
- if (ret) {
- dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
- goto out_kill_eq;
- }
-
ret = ehea_create_device_sysfs(dev);
if (ret)
- goto out_free_irq;
+ goto out_kill_eq;
ret = ehea_setup_ports(adapter);
if (ret) {
@@ -3332,15 +3327,28 @@
goto out_rem_dev_sysfs;
}
+ ret = ibmebus_request_irq(adapter->neq->attr.ist1,
+ ehea_interrupt_neq, IRQF_DISABLED,
+ "ehea_neq", adapter);
+ if (ret) {
+ dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
+ goto out_shutdown_ports;
+ }
+
+
ret = 0;
goto out;
+out_shutdown_ports:
+ for (i = 0; i < EHEA_MAX_PORTS; i++)
+ if (adapter->port[i]) {
+ ehea_shutdown_single_port(adapter->port[i]);
+ adapter->port[i] = NULL;
+ }
+
out_rem_dev_sysfs:
ehea_remove_device_sysfs(dev);
-out_free_irq:
- ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
-
out_kill_eq:
ehea_destroy_eq(adapter->neq);
diff --git a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
index 52c456e..8364815 100644
--- a/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
+++ b/drivers/net/ethernet/ibm/ehea/ehea_phyp.h
@@ -450,7 +450,7 @@
void *cb_addr);
#define H_REGBCMC_PN EHEA_BMASK_IBM(48, 63)
-#define H_REGBCMC_REGTYPE EHEA_BMASK_IBM(61, 63)
+#define H_REGBCMC_REGTYPE EHEA_BMASK_IBM(60, 63)
#define H_REGBCMC_MACADDR EHEA_BMASK_IBM(16, 63)
#define H_REGBCMC_VLANID EHEA_BMASK_IBM(52, 63)
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 0e9aec8..4348b6f 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -164,6 +164,8 @@
static bool e1000_vlan_used(struct e1000_adapter *adapter);
static void e1000_vlan_mode(struct net_device *netdev,
netdev_features_t features);
+static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
+ bool filter_on);
static int e1000_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
static int e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
static void e1000_restore_vlan(struct e1000_adapter *adapter);
@@ -215,7 +217,8 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-static int debug = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
@@ -979,7 +982,7 @@
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
- adapter->msg_enable = (1 << debug) - 1;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
adapter->bars = bars;
adapter->need_ioport = need_ioport;
@@ -1214,7 +1217,7 @@
if (err)
goto err_register;
- e1000_vlan_mode(netdev, netdev->features);
+ e1000_vlan_filter_on_off(adapter, false);
/* print bus type/speed/width info */
e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n",
@@ -4770,6 +4773,22 @@
return false;
}
+static void __e1000_vlan_mode(struct e1000_adapter *adapter,
+ netdev_features_t features)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ctrl;
+
+ ctrl = er32(CTRL);
+ if (features & NETIF_F_HW_VLAN_RX) {
+ /* enable VLAN tag insert/strip */
+ ctrl |= E1000_CTRL_VME;
+ } else {
+ /* disable VLAN tag insert/strip */
+ ctrl &= ~E1000_CTRL_VME;
+ }
+ ew32(CTRL, ctrl);
+}
static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter,
bool filter_on)
{
@@ -4779,6 +4798,7 @@
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_disable(adapter);
+ __e1000_vlan_mode(adapter, adapter->netdev->features);
if (filter_on) {
/* enable VLAN receive filtering */
rctl = er32(RCTL);
@@ -4799,24 +4819,14 @@
}
static void e1000_vlan_mode(struct net_device *netdev,
- netdev_features_t features)
+ netdev_features_t features)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
- u32 ctrl;
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_disable(adapter);
- ctrl = er32(CTRL);
- if (features & NETIF_F_HW_VLAN_RX) {
- /* enable VLAN tag insert/strip */
- ctrl |= E1000_CTRL_VME;
- } else {
- /* disable VLAN tag insert/strip */
- ctrl &= ~E1000_CTRL_VME;
- }
- ew32(CTRL, ctrl);
+ __e1000_vlan_mode(adapter, features);
if (!test_bit(__E1000_DOWN, &adapter->flags))
e1000_irq_enable(adapter);
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index 86cdd47..b83897f 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -161,6 +161,12 @@
/* Time to wait before putting the device into D3 if there's no link (in ms). */
#define LINK_TIMEOUT 100
+/*
+ * Count for polling __E1000_RESET condition every 10-20msec.
+ * Experimentation has shown the reset can take approximately 210msec.
+ */
+#define E1000_CHECK_RESET_COUNT 25
+
#define DEFAULT_RDTR 0
#define DEFAULT_RADV 8
#define BURST_RDTR 0x20
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
index 64c7644..b461c24 100644
--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
+++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
@@ -1310,10 +1310,6 @@
if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
oem_reg |= HV_OEM_BITS_LPLU;
-
- /* Set Restart auto-neg to activate the bits */
- if (!hw->phy.ops.check_reset_block(hw))
- oem_reg |= HV_OEM_BITS_RESTART_AN;
} else {
if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
@@ -1324,6 +1320,11 @@
oem_reg |= HV_OEM_BITS_LPLU;
}
+ /* Set Restart auto-neg to activate the bits */
+ if ((d0_state || (hw->mac.type != e1000_pchlan)) &&
+ !hw->phy.ops.check_reset_block(hw))
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+
ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
release:
@@ -3682,7 +3683,11 @@
if (hw->mac.type >= e1000_pchlan) {
e1000_oem_bits_config_ich8lan(hw, false);
- e1000_phy_hw_reset_ich8lan(hw);
+
+ /* Reset PHY to activate OEM bits on 82577/8 */
+ if (hw->mac.type == e1000_pchlan)
+ e1000e_phy_hw_reset_generic(hw);
+
ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 7152eb1..9520a6a 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -60,6 +60,11 @@
char e1000e_driver_name[] = "e1000e";
const char e1000e_driver_version[] = DRV_VERSION;
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state);
static const struct e1000_info *e1000_info_tbl[] = {
@@ -1054,6 +1059,13 @@
ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
/* execute the writes immediately */
e1e_flush();
+ /*
+ * Due to rare timing issues, write to TIDV again to ensure
+ * the write is successful
+ */
+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+ /* execute the writes immediately */
+ e1e_flush();
adapter->tx_hang_recheck = true;
return;
}
@@ -3611,6 +3623,16 @@
/* execute the writes immediately */
e1e_flush();
+
+ /*
+ * due to rare timing issues, write to TIDV/RDTR again to ensure the
+ * write is successful
+ */
+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+ ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD);
+
+ /* execute the writes immediately */
+ e1e_flush();
}
static void e1000e_update_stats(struct e1000_adapter *adapter);
@@ -3777,7 +3799,7 @@
/* fire an unusual interrupt on the test handler */
ew32(ICS, E1000_ICS_RXSEQ);
e1e_flush();
- msleep(50);
+ msleep(100);
e1000_irq_disable(adapter);
@@ -3963,6 +3985,10 @@
{
struct e1000_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = adapter->pdev;
+ int count = E1000_CHECK_RESET_COUNT;
+
+ while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
+ usleep_range(10000, 20000);
WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
@@ -5467,6 +5493,11 @@
netif_device_detach(netdev);
if (netif_running(netdev)) {
+ int count = E1000_CHECK_RESET_COUNT;
+
+ while (test_bit(__E1000_RESETTING, &adapter->state) && count--)
+ usleep_range(10000, 20000);
+
WARN_ON(test_bit(__E1000_RESETTING, &adapter->state));
e1000e_down(adapter);
e1000_free_irq(adapter);
@@ -6172,7 +6203,7 @@
adapter->hw.adapter = adapter;
adapter->hw.mac.type = ei->mac;
adapter->max_hw_frame_size = ei->max_hw_frame_size;
- adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
mmio_start = pci_resource_start(pdev, 0);
mmio_len = pci_resource_len(pdev, 0);
diff --git a/drivers/net/ethernet/intel/e1000e/param.c b/drivers/net/ethernet/intel/e1000e/param.c
index ff796e4..16adeb9 100644
--- a/drivers/net/ethernet/intel/e1000e/param.c
+++ b/drivers/net/ethernet/intel/e1000e/param.c
@@ -106,7 +106,7 @@
/*
* Interrupt Throttle Rate (interrupts/sec)
*
- * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
+ * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
*/
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
#define DEFAULT_ITR 3
@@ -344,53 +344,60 @@
if (num_InterruptThrottleRate > bd) {
adapter->itr = InterruptThrottleRate[bd];
- switch (adapter->itr) {
- case 0:
- e_info("%s turned off\n", opt.name);
- break;
- case 1:
- e_info("%s set to dynamic mode\n", opt.name);
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- break;
- case 3:
- e_info("%s set to dynamic conservative mode\n",
- opt.name);
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- break;
- case 4:
- e_info("%s set to simplified (2000-8000 ints) "
- "mode\n", opt.name);
- adapter->itr_setting = 4;
- break;
- default:
- /*
- * Save the setting, because the dynamic bits
- * change itr.
- */
- if (e1000_validate_option(&adapter->itr, &opt,
- adapter) &&
- (adapter->itr == 3)) {
- /*
- * In case of invalid user value,
- * default to conservative mode.
- */
- adapter->itr_setting = adapter->itr;
- adapter->itr = 20000;
- } else {
- /*
- * Clear the lower two bits because
- * they are used as control.
- */
- adapter->itr_setting =
- adapter->itr & ~3;
- }
- break;
- }
+
+ /*
+ * Make sure a message is printed for non-special
+ * values. And in case of an invalid option, display
+ * warning, use default and got through itr/itr_setting
+ * adjustment logic below
+ */
+ if ((adapter->itr > 4) &&
+ e1000_validate_option(&adapter->itr, &opt, adapter))
+ adapter->itr = opt.def;
} else {
- adapter->itr_setting = opt.def;
+ /*
+ * If no option specified, use default value and go
+ * through the logic below to adjust itr/itr_setting
+ */
+ adapter->itr = opt.def;
+
+ /*
+ * Make sure a message is printed for non-special
+ * default values
+ */
+ if (adapter->itr > 40)
+ e_info("%s set to default %d\n", opt.name,
+ adapter->itr);
+ }
+
+ adapter->itr_setting = adapter->itr;
+ switch (adapter->itr) {
+ case 0:
+ e_info("%s turned off\n", opt.name);
+ break;
+ case 1:
+ e_info("%s set to dynamic mode\n", opt.name);
adapter->itr = 20000;
+ break;
+ case 3:
+ e_info("%s set to dynamic conservative mode\n",
+ opt.name);
+ adapter->itr = 20000;
+ break;
+ case 4:
+ e_info("%s set to simplified (2000-8000 ints) mode\n",
+ opt.name);
+ break;
+ default:
+ /*
+ * Save the setting, because the dynamic bits
+ * change itr.
+ *
+ * Clear the lower two bits because
+ * they are used as control.
+ */
+ adapter->itr_setting &= ~3;
+ break;
}
}
{ /* Interrupt Mode */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index c490241..5ec3159 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -238,6 +238,11 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
struct igb_reg_info {
u32 ofs;
char *name;
@@ -1893,7 +1898,7 @@
adapter->pdev = pdev;
hw = &adapter->hw;
hw->back = adapter;
- adapter->msg_enable = NETIF_MSG_DRV | NETIF_MSG_PROBE;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
mmio_start = pci_resource_start(pdev, 0);
mmio_len = pci_resource_len(pdev, 0);
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 217c143..8ec74b0 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -55,6 +55,11 @@
static const char igbvf_copyright[] =
"Copyright (c) 2009 - 2012 Intel Corporation.";
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
static int igbvf_poll(struct napi_struct *napi, int budget);
static void igbvf_reset(struct igbvf_adapter *);
static void igbvf_set_interrupt_capability(struct igbvf_adapter *);
@@ -2649,7 +2654,7 @@
adapter->flags = ei->flags;
adapter->hw.back = adapter;
adapter->hw.mac.type = ei->mac;
- adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
/* PCI config space info */
@@ -2726,14 +2731,14 @@
netdev->addr_len);
}
- if (!is_valid_ether_addr(netdev->perm_addr)) {
+ if (!is_valid_ether_addr(netdev->dev_addr)) {
dev_err(&pdev->dev, "Invalid MAC Address: %pM\n",
netdev->dev_addr);
err = -EIO;
goto err_hw_init;
}
- memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
+ memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len);
setup_timer(&adapter->watchdog_timer, &igbvf_watchdog,
(unsigned long) adapter);
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 82aaa79..5fce363 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -134,8 +134,8 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-static int debug = DEFAULT_DEBUG_LEVEL_SHIFT;
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
@@ -442,7 +442,7 @@
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->hw.back = adapter;
- adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);
if (!adapter->hw.hw_addr) {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 80e26ff..74e1921 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -544,7 +544,7 @@
u16 action;
};
-enum ixbge_state_t {
+enum ixgbe_state_t {
__IXGBE_TESTING,
__IXGBE_RESETTING,
__IXGBE_DOWN,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index dde65f9..652e4b0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -44,62 +44,94 @@
#define DCB_NO_HW_CHG 1 /* DCB configuration did not change */
#define DCB_HW_CHG 2 /* DCB configuration changed, no reset */
-int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
- struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
+int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *scfg,
+ struct ixgbe_dcb_config *dcfg, int tc_max)
{
- struct tc_configuration *src_tc_cfg = NULL;
- struct tc_configuration *dst_tc_cfg = NULL;
- int i;
+ struct tc_configuration *src = NULL;
+ struct tc_configuration *dst = NULL;
+ int i, j;
+ int tx = DCB_TX_CONFIG;
+ int rx = DCB_RX_CONFIG;
+ int changes = 0;
- if (!src_dcb_cfg || !dst_dcb_cfg)
- return -EINVAL;
+ if (!scfg || !dcfg)
+ return changes;
for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
- src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
- dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
+ src = &scfg->tc_config[i - DCB_PG_ATTR_TC_0];
+ dst = &dcfg->tc_config[i - DCB_PG_ATTR_TC_0];
- dst_tc_cfg->path[DCB_TX_CONFIG].prio_type =
- src_tc_cfg->path[DCB_TX_CONFIG].prio_type;
+ if (dst->path[tx].prio_type != src->path[tx].prio_type) {
+ dst->path[tx].prio_type = src->path[tx].prio_type;
+ changes |= BIT_PG_TX;
+ }
- dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id =
- src_tc_cfg->path[DCB_TX_CONFIG].bwg_id;
+ if (dst->path[tx].bwg_id != src->path[tx].bwg_id) {
+ dst->path[tx].bwg_id = src->path[tx].bwg_id;
+ changes |= BIT_PG_TX;
+ }
- dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent =
- src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent;
+ if (dst->path[tx].bwg_percent != src->path[tx].bwg_percent) {
+ dst->path[tx].bwg_percent = src->path[tx].bwg_percent;
+ changes |= BIT_PG_TX;
+ }
- dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap =
- src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap;
+ if (dst->path[tx].up_to_tc_bitmap !=
+ src->path[tx].up_to_tc_bitmap) {
+ dst->path[tx].up_to_tc_bitmap =
+ src->path[tx].up_to_tc_bitmap;
+ changes |= (BIT_PG_TX | BIT_PFC | BIT_APP_UPCHG);
+ }
- dst_tc_cfg->path[DCB_RX_CONFIG].prio_type =
- src_tc_cfg->path[DCB_RX_CONFIG].prio_type;
+ if (dst->path[rx].prio_type != src->path[rx].prio_type) {
+ dst->path[rx].prio_type = src->path[rx].prio_type;
+ changes |= BIT_PG_RX;
+ }
- dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id =
- src_tc_cfg->path[DCB_RX_CONFIG].bwg_id;
+ if (dst->path[rx].bwg_id != src->path[rx].bwg_id) {
+ dst->path[rx].bwg_id = src->path[rx].bwg_id;
+ changes |= BIT_PG_RX;
+ }
- dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent =
- src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent;
+ if (dst->path[rx].bwg_percent != src->path[rx].bwg_percent) {
+ dst->path[rx].bwg_percent = src->path[rx].bwg_percent;
+ changes |= BIT_PG_RX;
+ }
- dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap =
- src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap;
+ if (dst->path[rx].up_to_tc_bitmap !=
+ src->path[rx].up_to_tc_bitmap) {
+ dst->path[rx].up_to_tc_bitmap =
+ src->path[rx].up_to_tc_bitmap;
+ changes |= (BIT_PG_RX | BIT_PFC | BIT_APP_UPCHG);
+ }
}
for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
- dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG]
- [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
- [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
- dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG]
- [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
- [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
+ j = i - DCB_PG_ATTR_BW_ID_0;
+ if (dcfg->bw_percentage[tx][j] != scfg->bw_percentage[tx][j]) {
+ dcfg->bw_percentage[tx][j] = scfg->bw_percentage[tx][j];
+ changes |= BIT_PG_TX;
+ }
+ if (dcfg->bw_percentage[rx][j] != scfg->bw_percentage[rx][j]) {
+ dcfg->bw_percentage[rx][j] = scfg->bw_percentage[rx][j];
+ changes |= BIT_PG_RX;
+ }
}
for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
- dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc =
- src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc;
+ j = i - DCB_PFC_UP_ATTR_0;
+ if (dcfg->tc_config[j].dcb_pfc != scfg->tc_config[j].dcb_pfc) {
+ dcfg->tc_config[j].dcb_pfc = scfg->tc_config[j].dcb_pfc;
+ changes |= BIT_PFC;
+ }
}
- dst_dcb_cfg->pfc_mode_enable = src_dcb_cfg->pfc_mode_enable;
+ if (dcfg->pfc_mode_enable != scfg->pfc_mode_enable) {
+ dcfg->pfc_mode_enable = scfg->pfc_mode_enable;
+ changes |= BIT_PFC;
+ }
- return 0;
+ return changes;
}
static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
@@ -179,20 +211,6 @@
if (up_map != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
up_map;
-
- if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
- adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
- adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
- adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
- adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
- adapter->dcb_set_bitmap |= BIT_PG_TX;
-
- if (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
- adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap)
- adapter->dcb_set_bitmap |= BIT_PFC | BIT_APP_UPCHG;
}
static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
@@ -201,10 +219,6 @@
struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
-
- if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
- adapter->dcb_cfg.bw_percentage[0][bwg_id])
- adapter->dcb_set_bitmap |= BIT_PG_TX;
}
static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
@@ -223,20 +237,6 @@
if (up_map != DCB_ATTR_VALUE_UNDEFINED)
adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
up_map;
-
- if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
- adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
- adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
- adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
- (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
- adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
- adapter->dcb_set_bitmap |= BIT_PG_RX;
-
- if (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
- adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap)
- adapter->dcb_set_bitmap |= BIT_PFC;
}
static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
@@ -245,10 +245,6 @@
struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
-
- if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
- adapter->dcb_cfg.bw_percentage[1][bwg_id])
- adapter->dcb_set_bitmap |= BIT_PG_RX;
}
static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
@@ -298,10 +294,8 @@
adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
- adapter->dcb_cfg.tc_config[priority].dcb_pfc) {
- adapter->dcb_set_bitmap |= BIT_PFC;
+ adapter->dcb_cfg.tc_config[priority].dcb_pfc)
adapter->temp_dcb_cfg.pfc_mode_enable = true;
- }
}
static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
@@ -336,7 +330,8 @@
static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int ret, i;
+ int ret = DCB_NO_HW_CHG;
+ int i;
#ifdef IXGBE_FCOE
struct dcb_app app = {
.selector = DCB_APP_IDTYPE_ETHTYPE,
@@ -355,12 +350,13 @@
/* Fail command if not in CEE mode */
if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
- return 1;
+ return ret;
- ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
- MAX_TRAFFIC_CLASS);
- if (ret)
- return DCB_NO_HW_CHG;
+ adapter->dcb_set_bitmap |= ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg,
+ &adapter->dcb_cfg,
+ MAX_TRAFFIC_CLASS);
+ if (!adapter->dcb_set_bitmap)
+ return ret;
if (adapter->dcb_cfg.pfc_mode_enable) {
switch (adapter->hw.mac.type) {
@@ -420,6 +416,8 @@
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
netdev_set_prio_tc_map(netdev, i, prio_tc[i]);
+
+ ret = DCB_HW_CHG_RST;
}
if (adapter->dcb_set_bitmap & BIT_PFC) {
@@ -430,7 +428,8 @@
DCB_TX_CONFIG, prio_tc);
ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en, prio_tc);
- ret = DCB_HW_CHG;
+ if (ret != DCB_HW_CHG_RST)
+ ret = DCB_HW_CHG;
}
if (adapter->dcb_cfg.pfc_mode_enable)
@@ -531,9 +530,6 @@
struct ixgbe_adapter *adapter = netdev_priv(netdev);
adapter->temp_dcb_cfg.pfc_mode_enable = state;
- if (adapter->temp_dcb_cfg.pfc_mode_enable !=
- adapter->dcb_cfg.pfc_mode_enable)
- adapter->dcb_set_bitmap |= BIT_PFC;
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
index 77ea4b7..bc07933 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
@@ -437,6 +437,7 @@
*/
if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) &&
(fctl & FC_FC_END_SEQ)) {
+ skb_linearize(skb);
crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
crc->fcoe_eof = FC_EOF_T;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 027d7a7..ed1b47d 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -622,6 +622,16 @@
if (adapter->hw.mac.type == ixgbe_mac_82599EB)
set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state);
+#ifdef IXGBE_FCOE
+ if (adapter->netdev->features & NETIF_F_FCOE_MTU) {
+ struct ixgbe_ring_feature *f;
+ f = &adapter->ring_feature[RING_F_FCOE];
+ if ((rxr_idx >= f->mask) &&
+ (rxr_idx < f->mask + f->indices))
+ set_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state);
+ }
+
+#endif /* IXGBE_FCOE */
/* apply Rx specific ring traits */
ring->count = adapter->rx_ring_count;
ring->queue_index = rxr_idx;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 398fc22..88f6b2e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -63,8 +63,8 @@
"Intel(R) 10 Gigabit Network Connection";
#endif
#define MAJ 3
-#define MIN 6
-#define BUILD 7
+#define MIN 8
+#define BUILD 21
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
__stringify(BUILD) "-k"
const char ixgbe_driver_version[] = DRV_VERSION;
@@ -141,13 +141,16 @@
MODULE_PARM_DESC(allow_unsupported_sfp,
"Allow unsupported and untested SFP+ modules on 82599-based adapters");
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
-
static void ixgbe_service_event_schedule(struct ixgbe_adapter *adapter)
{
if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
@@ -3151,14 +3154,6 @@
set_ring_rsc_enabled(rx_ring);
else
clear_ring_rsc_enabled(rx_ring);
-#ifdef IXGBE_FCOE
- if (netdev->features & NETIF_F_FCOE_MTU) {
- struct ixgbe_ring_feature *f;
- f = &adapter->ring_feature[RING_F_FCOE];
- if ((i >= f->mask) && (i < f->mask + f->indices))
- set_bit(__IXGBE_RX_FCOE_BUFSZ, &rx_ring->state);
- }
-#endif /* IXGBE_FCOE */
}
}
@@ -4833,7 +4828,9 @@
pci_wake_from_d3(pdev, false);
+ rtnl_lock();
err = ixgbe_init_interrupt_scheme(adapter);
+ rtnl_unlock();
if (err) {
e_dev_err("Cannot initialize interrupts for device\n");
return err;
@@ -4876,10 +4873,6 @@
}
ixgbe_clear_interrupt_scheme(adapter);
-#ifdef CONFIG_DCB
- kfree(adapter->ixgbe_ieee_pfc);
- kfree(adapter->ixgbe_ieee_ets);
-#endif
#ifdef CONFIG_PM
retval = pci_save_state(pdev);
@@ -4890,6 +4883,16 @@
if (wufc) {
ixgbe_set_rx_mode(netdev);
+ /*
+ * enable the optics for both mult-speed fiber and
+ * 82599 SFP+ fiber as we can WoL.
+ */
+ if (hw->mac.ops.enable_tx_laser &&
+ (hw->phy.multispeed_fiber ||
+ (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber &&
+ hw->mac.type == ixgbe_mac_82599EB)))
+ hw->mac.ops.enable_tx_laser(hw);
+
/* turn on all-multi mode if wake on multicast is enabled */
if (wufc & IXGBE_WUFC_MC) {
fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
@@ -6834,7 +6837,7 @@
adapter->pdev = pdev;
hw = &adapter->hw;
hw->back = adapter;
- adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
hw->hw_addr = ioremap(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0));
@@ -7217,6 +7220,11 @@
ixgbe_release_hw_control(adapter);
+#ifdef CONFIG_DCB
+ kfree(adapter->ixgbe_ieee_pfc);
+ kfree(adapter->ixgbe_ieee_ets);
+
+#endif
iounmap(adapter->hw.hw_addr);
pci_release_selected_regions(pdev, pci_select_bars(pdev,
IORESOURCE_MEM));
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 581c659..307611a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -91,7 +91,10 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-#define DEFAULT_DEBUG_LEVEL_SHIFT 3
+#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
+static int debug = -1;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
/* forward decls */
static void ixgbevf_set_itr_msix(struct ixgbevf_q_vector *q_vector);
@@ -3367,7 +3370,7 @@
adapter->pdev = pdev;
hw = &adapter->hw;
hw->back = adapter;
- adapter->msg_enable = (1 << DEFAULT_DEBUG_LEVEL_SHIFT) - 1;
+ adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
/*
* call save state here in standalone driver because it relies on
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 423a1a2..487a6c8 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -1767,13 +1767,14 @@
sky2_hw_up(sky2);
+ /* Enable interrupts from phy/mac for port */
+ imask = sky2_read32(hw, B0_IMSK);
+
if (hw->chip_id == CHIP_ID_YUKON_OPT ||
hw->chip_id == CHIP_ID_YUKON_PRM ||
hw->chip_id == CHIP_ID_YUKON_OP_2)
imask |= Y2_IS_PHY_QLNK; /* enable PHY Quick Link */
- /* Enable interrupts from phy/mac for port */
- imask = sky2_read32(hw, B0_IMSK);
imask |= portirq_msk[port];
sky2_write32(hw, B0_IMSK, imask);
sky2_read32(hw, B0_IMSK);
@@ -2468,6 +2469,17 @@
return err;
}
+static inline bool needs_copy(const struct rx_ring_info *re,
+ unsigned length)
+{
+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+ /* Some architectures need the IP header to be aligned */
+ if (!IS_ALIGNED(re->data_addr + ETH_HLEN, sizeof(u32)))
+ return true;
+#endif
+ return length < copybreak;
+}
+
/* For small just reuse existing skb for next receive */
static struct sk_buff *receive_copy(struct sky2_port *sky2,
const struct rx_ring_info *re,
@@ -2482,8 +2494,13 @@
skb_copy_from_linear_data(re->skb, skb->data, length);
skb->ip_summed = re->skb->ip_summed;
skb->csum = re->skb->csum;
+ skb->rxhash = re->skb->rxhash;
+ skb->vlan_tci = re->skb->vlan_tci;
+
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
length, PCI_DMA_FROMDEVICE);
+ re->skb->vlan_tci = 0;
+ re->skb->rxhash = 0;
re->skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, length);
}
@@ -2568,9 +2585,6 @@
struct sk_buff *skb = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
- if (status & GMR_FS_VLAN)
- count -= VLAN_HLEN; /* Account for vlan tag */
-
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
"rx slot %u status 0x%x len %d\n",
sky2->rx_next, status, length);
@@ -2578,6 +2592,9 @@
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
prefetch(sky2->rx_ring + sky2->rx_next);
+ if (vlan_tx_tag_present(re->skb))
+ count -= VLAN_HLEN; /* Account for vlan tag */
+
/* This chip has hardware problems that generates bogus status.
* So do only marginal checking and expect higher level protocols
* to handle crap frames.
@@ -2598,7 +2615,7 @@
goto error;
okay:
- if (length < copybreak)
+ if (needs_copy(re, length))
skb = receive_copy(sky2, re, length);
else
skb = receive_new(sky2, re, length);
@@ -2635,11 +2652,8 @@
}
static inline void sky2_skb_rx(const struct sky2_port *sky2,
- u32 status, struct sk_buff *skb)
+ struct sk_buff *skb)
{
- if (status & GMR_FS_VLAN)
- __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
-
if (skb->ip_summed == CHECKSUM_NONE)
netif_receive_skb(skb);
else
@@ -2693,6 +2707,14 @@
}
}
+static void sky2_rx_tag(struct sky2_port *sky2, u16 length)
+{
+ struct sk_buff *skb;
+
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(length));
+}
+
static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
{
struct sk_buff *skb;
@@ -2751,8 +2773,7 @@
}
skb->protocol = eth_type_trans(skb, dev);
-
- sky2_skb_rx(sky2, status, skb);
+ sky2_skb_rx(sky2, skb);
/* Stop after net poll weight */
if (++work_done >= to_do)
@@ -2760,11 +2781,11 @@
break;
case OP_RXVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
break;
case OP_RXCHKSVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
/* fall through */
case OP_RXCHKS:
if (likely(dev->features & NETIF_F_RXCSUM))
diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h
index ff6f58b..3c896ce 100644
--- a/drivers/net/ethernet/marvell/sky2.h
+++ b/drivers/net/ethernet/marvell/sky2.h
@@ -2241,7 +2241,6 @@
u16 rx_pending;
u16 rx_data_size;
u16 rx_nfrags;
- u16 rx_tag;
struct {
unsigned long last;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
index 9e2b911..d69fee4 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
@@ -83,8 +83,9 @@
#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
-#define MLX4_EN_ALLOC_ORDER 2
-#define MLX4_EN_ALLOC_SIZE (PAGE_SIZE << MLX4_EN_ALLOC_ORDER)
+/* Use the maximum between 16384 and a single page */
+#define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(16384)
+#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE)
#define MLX4_EN_MAX_LRO_DESCRIPTORS 32
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index c722aa6..f8dda00 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -889,16 +889,17 @@
netif_stop_queue(dev);
mutex_lock(&ks->lock);
+ /* turn off the IRQs and ack any outstanding */
+ ks8851_wrreg16(ks, KS_IER, 0x0000);
+ ks8851_wrreg16(ks, KS_ISR, 0xffff);
+ mutex_unlock(&ks->lock);
/* stop any outstanding work */
flush_work(&ks->irq_work);
flush_work(&ks->tx_work);
flush_work(&ks->rxctrl_work);
- /* turn off the IRQs and ack any outstanding */
- ks8851_wrreg16(ks, KS_IER, 0x0000);
- ks8851_wrreg16(ks, KS_ISR, 0xffff);
-
+ mutex_lock(&ks->lock);
/* shutdown RX process */
ks8851_wrreg16(ks, KS_RXCR1, 0x0000);
@@ -907,6 +908,7 @@
/* set powermode to soft power down to save power */
ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN);
+ mutex_unlock(&ks->lock);
/* ensure any queued tx buffers are dumped */
while (!skb_queue_empty(&ks->txq)) {
@@ -918,7 +920,6 @@
dev_kfree_skb(txb);
}
- mutex_unlock(&ks->lock);
return 0;
}
@@ -1418,6 +1419,7 @@
struct net_device *ndev;
struct ks8851_net *ks;
int ret;
+ unsigned cider;
ndev = alloc_etherdev(sizeof(struct ks8851_net));
if (!ndev)
@@ -1484,8 +1486,8 @@
ks8851_soft_reset(ks, GRR_GSR);
/* simple check for a valid chip being connected to the bus */
-
- if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
+ cider = ks8851_rdreg16(ks, KS_CIDER);
+ if ((cider & ~CIDER_REV_MASK) != CIDER_ID) {
dev_err(&spi->dev, "failed to read device ID\n");
ret = -ENODEV;
goto err_id;
@@ -1516,15 +1518,14 @@
}
netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n",
- CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)),
- ndev->dev_addr, ndev->irq,
+ CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq,
ks->rc_ccr & CCR_EEPROM ? "has" : "no");
return 0;
err_netdev:
- free_irq(ndev->irq, ndev);
+ free_irq(ndev->irq, ks);
err_id:
err_irq:
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index b8104d9..5ffde23 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -40,7 +40,7 @@
#define DRV_NAME "ks8851_mll"
static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 };
-#define MAX_RECV_FRAMES 32
+#define MAX_RECV_FRAMES 255
#define MAX_BUF_SIZE 2048
#define TX_BUF_SIZE 2000
#define RX_BUF_SIZE 2000
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index ef723b1..eaf9ff0 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -5675,7 +5675,7 @@
memcpy(hw->override_addr, mac->sa_data, ETH_ALEN);
}
- memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN);
+ memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN);
interrupt = hw_block_intr(hw);
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c
index 6944424..6dfc26d 100644
--- a/drivers/net/ethernet/nxp/lpc_eth.c
+++ b/drivers/net/ethernet/nxp/lpc_eth.c
@@ -1441,7 +1441,7 @@
}
#endif
if (!is_valid_ether_addr(ndev->dev_addr))
- dev_hw_addr_random(ndev, ndev->dev_addr);
+ eth_hw_addr_random(ndev);
/* Reset the ethernet controller */
__lpc_eth_reset(pldat);
diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c
index abc7907..b3287c0 100644
--- a/drivers/net/ethernet/realtek/8139cp.c
+++ b/drivers/net/ethernet/realtek/8139cp.c
@@ -958,6 +958,11 @@
cpw8(Cmd, RxOn | TxOn);
}
+static void cp_enable_irq(struct cp_private *cp)
+{
+ cpw16_f(IntrMask, cp_intr_mask);
+}
+
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
@@ -997,8 +1002,6 @@
cpw16(MultiIntr, 0);
- cpw16_f(IntrMask, cp_intr_mask);
-
cpw8_f(Cfg9346, Cfg9346_Lock);
}
@@ -1130,6 +1133,8 @@
if (rc)
goto err_out_hw;
+ cp_enable_irq(cp);
+
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
@@ -2031,6 +2036,7 @@
/* FIXME: sh*t may happen if the Rx ring buffer is depleted */
cp_init_rings_index (cp);
cp_init_hw (cp);
+ cp_enable_irq(cp);
netif_start_queue (dev);
spin_lock_irqsave (&cp->lock, flags);
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 7b23554..f545093 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -5810,7 +5810,10 @@
rtl_pll_power_up(tp);
+ rtl_lock_work(tp);
+ napi_enable(&tp->napi);
set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
+ rtl_unlock_work(tp);
rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
}
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index 9755b49..3fb2355 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -7,7 +7,8 @@
depends on SUPERH && \
(CPU_SUBTYPE_SH7710 || CPU_SUBTYPE_SH7712 || \
CPU_SUBTYPE_SH7763 || CPU_SUBTYPE_SH7619 || \
- CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7757)
+ CPU_SUBTYPE_SH7724 || CPU_SUBTYPE_SH7734 || \
+ CPU_SUBTYPE_SH7757)
select CRC32
select NET_CORE
select MII
@@ -16,4 +17,4 @@
---help---
Renesas SuperH Ethernet device driver.
This driver supporting CPUs are:
- - SH7710, SH7712, SH7763, SH7619, SH7724, and SH7757.
+ - SH7619, SH7710, SH7712, SH7724, SH7734, SH7763 and SH7757.
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 8615961..d63e09b 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1,8 +1,8 @@
/*
* SuperH Ethernet device driver
*
- * Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- * Copyright (C) 2008-2009 Renesas Solutions Corp.
+ * Copyright (C) 2006-2012 Nobuhiro Iwamatsu
+ * Copyright (C) 2008-2012 Renesas Solutions Corp.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
+#include <linux/clk.h>
#include <linux/sh_eth.h>
#include "sh_eth.h"
@@ -279,8 +280,9 @@
return &sh_eth_my_cpu_data;
}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
#define SH_ETH_HAS_TSU 1
+static void sh_eth_reset_hw_crc(struct net_device *ndev);
static void sh_eth_chip_reset(struct net_device *ndev)
{
struct sh_eth_private *mdp = netdev_priv(ndev);
@@ -314,6 +316,9 @@
sh_eth_write(ndev, 0x0, RDFAR);
sh_eth_write(ndev, 0x0, RDFXR);
sh_eth_write(ndev, 0x0, RDFFR);
+
+ /* Reset HW CRC register */
+ sh_eth_reset_hw_crc(ndev);
}
static void sh_eth_set_duplex(struct net_device *ndev)
@@ -370,8 +375,17 @@
.no_trimd = 1,
.no_ade = 1,
.tsu = 1,
+#if defined(CONFIG_CPU_SUBTYPE_SH7734)
+ .hw_crc = 1,
+#endif
};
+static void sh_eth_reset_hw_crc(struct net_device *ndev)
+{
+ if (sh_eth_my_cpu_data.hw_crc)
+ sh_eth_write(ndev, 0x0, CSMR);
+}
+
#elif defined(CONFIG_CPU_SUBTYPE_SH7619)
#define SH_ETH_RESET_DEFAULT 1
static struct sh_eth_cpu_data sh_eth_my_cpu_data = {
@@ -790,7 +804,7 @@
/* all sh_eth int mask */
sh_eth_write(ndev, 0, EESIPR);
-#if defined(__LITTLE_ENDIAN__)
+#if defined(__LITTLE_ENDIAN)
if (mdp->cd->hw_swap)
sh_eth_write(ndev, EDMR_EL, EDMR);
else
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h
index 57dc262..0fa14afc 100644
--- a/drivers/net/ethernet/renesas/sh_eth.h
+++ b/drivers/net/ethernet/renesas/sh_eth.h
@@ -1,8 +1,8 @@
/*
* SuperH Ethernet device driver
*
- * Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- * Copyright (C) 2008-2011 Renesas Solutions Corp.
+ * Copyright (C) 2006-2012 Nobuhiro Iwamatsu
+ * Copyright (C) 2008-2012 Renesas Solutions Corp.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -98,6 +98,8 @@
CEECR,
MAFCR,
RTRATE,
+ CSMR,
+ RMII_MII,
/* TSU Absolute address */
ARSTR,
@@ -172,6 +174,7 @@
[RMCR] = 0x0458,
[RPADIR] = 0x0460,
[FCFTR] = 0x0468,
+ [CSMR] = 0x04E4,
[ECMR] = 0x0500,
[ECSR] = 0x0510,
@@ -200,6 +203,7 @@
[CERCR] = 0x0768,
[CEECR] = 0x0770,
[MAFCR] = 0x0778,
+ [RMII_MII] = 0x0790,
[ARSTR] = 0x0000,
[TSU_CTRST] = 0x0004,
@@ -377,7 +381,7 @@
/*
* Register's bits
*/
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
+#if defined(CONFIG_CPU_SUBTYPE_SH7734) || defined(CONFIG_CPU_SUBTYPE_SH7763)
/* EDSR */
enum EDSR_BIT {
EDSR_ENT = 0x01, EDSR_ENR = 0x02,
@@ -689,7 +693,7 @@
*/
struct sh_eth_txdesc {
u32 status; /* TD0 */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN)
u16 pad0; /* TD1 */
u16 buffer_length; /* TD1 */
#else
@@ -706,7 +710,7 @@
*/
struct sh_eth_rxdesc {
u32 status; /* RD0 */
-#if defined(CONFIG_CPU_LITTLE_ENDIAN)
+#if defined(__LITTLE_ENDIAN)
u16 frame_length; /* RD1 */
u16 buffer_length; /* RD1 */
#else
@@ -751,6 +755,7 @@
unsigned rpadir:1; /* E-DMAC have RPADIR */
unsigned no_trimd:1; /* E-DMAC DO NOT have TRIMD */
unsigned no_ade:1; /* E-DMAC DO NOT have ADE bit in EESR */
+ unsigned hw_crc:1; /* E-DMAC have CSMR */
};
struct sh_eth_private {
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index 4a69710..cd3defb 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1166,10 +1166,8 @@
/* Quickly dumps bad packets */
static void
-smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
{
- unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
-
if (likely(pktwords >= 4)) {
unsigned int timeout = 500;
unsigned int val;
@@ -1233,7 +1231,7 @@
continue;
}
- skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(dev, pktwords << 2);
if (unlikely(!skb)) {
SMSC_WARN(pdata, rx_err,
"Unable to allocate skb for rx packet");
@@ -1243,14 +1241,12 @@
break;
}
- skb->data = skb->head;
- skb_reset_tail_pointer(skb);
+ pdata->ops->rx_readfifo(pdata,
+ (unsigned int *)skb->data, pktwords);
/* Align IP on 16B boundary */
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pktlength - 4);
- pdata->ops->rx_readfifo(pdata,
- (unsigned int *)skb->head, pktwords);
skb->protocol = eth_type_trans(skb, dev);
skb_checksum_none_assert(skb);
netif_receive_skb(skb);
@@ -1565,7 +1561,7 @@
smsc911x_reg_write(pdata, FIFO_INT, temp);
/* set RX Data offset to 2 bytes for alignment */
- smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+ smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
/* enable NAPI polling before enabling RX interrupts */
napi_enable(&pdata->napi);
@@ -2382,7 +2378,6 @@
SET_NETDEV_DEV(dev, &pdev->dev);
pdata = netdev_priv(dev);
-
dev->irq = irq_res->start;
irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
pdata->ioaddr = ioremap_nocache(res->start, res_size);
@@ -2446,7 +2441,7 @@
if (retval) {
SMSC_WARN(pdata, probe,
"Unable to claim requested irq: %d", dev->irq);
- goto out_free_irq;
+ goto out_disable_resources;
}
retval = register_netdev(dev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index e85ffbd..48d56da 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1737,10 +1737,12 @@
struct mac_device_info *mac;
/* Identify the MAC HW device */
- if (priv->plat->has_gmac)
+ if (priv->plat->has_gmac) {
+ priv->dev->priv_flags |= IFF_UNICAST_FLT;
mac = dwmac1000_setup(priv->ioaddr);
- else
+ } else {
mac = dwmac100_setup(priv->ioaddr);
+ }
if (!mac)
return -ENOMEM;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 558409f..4ba9690 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -2339,7 +2339,7 @@
netif_device_detach(dev);
/* Switch off chip, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
+ gp->asleep_wol = !!gp->wake_on_lan;
gem_do_stop(dev, gp->asleep_wol);
/* Unlock the network stack */
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 174a334..08aff1a 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1511,7 +1511,7 @@
static int match_first_device(struct device *dev, void *data)
{
- return 1;
+ return !strncmp(dev_name(dev), "davinci_mdio", 12);
}
/**
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index 2757c7d..e4e4708 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -181,6 +181,11 @@
__davinci_mdio_reset(data);
return -EAGAIN;
}
+
+ reg = __raw_readl(®s->user[0].access);
+ if ((reg & USERACCESS_GO) == 0)
+ return 0;
+
dev_err(data->dev, "timed out waiting for user access\n");
return -ETIMEDOUT;
}
diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c
index 817ad3b..efd3669 100644
--- a/drivers/net/ethernet/ti/tlan.c
+++ b/drivers/net/ethernet/ti/tlan.c
@@ -228,7 +228,7 @@
unsigned long addr;
addr = tag->buffer[9].address;
- addr |= (tag->buffer[8].address << 16) << 16;
+ addr |= ((unsigned long) tag->buffer[8].address << 16) << 16;
return (struct sk_buff *) addr;
}
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 261356c..3d501ec 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -342,6 +342,21 @@
}
+static void tile_net_return_credit(struct tile_net_cpu *info)
+{
+ struct tile_netio_queue *queue = &info->queue;
+ netio_queue_user_impl_t *qup = &queue->__user_part;
+
+ /* Return four credits after every fourth packet. */
+ if (--qup->__receive_credit_remaining == 0) {
+ u32 interval = qup->__receive_credit_interval;
+ qup->__receive_credit_remaining = interval;
+ __netio_fastio_return_credits(qup->__fastio_index, interval);
+ }
+}
+
+
+
/*
* Provide a linux buffer to LIPP.
*/
@@ -433,7 +448,7 @@
struct sk_buff **skb_ptr;
/* Request 96 extra bytes for alignment purposes. */
- skb = netdev_alloc_skb(info->napi->dev, len + padding);
+ skb = netdev_alloc_skb(info->napi.dev, len + padding);
if (skb == NULL)
return false;
@@ -864,19 +879,11 @@
stats->rx_packets++;
stats->rx_bytes += len;
-
- if (small)
- info->num_needed_small_buffers++;
- else
- info->num_needed_large_buffers++;
}
- /* Return four credits after every fourth packet. */
- if (--qup->__receive_credit_remaining == 0) {
- u32 interval = qup->__receive_credit_interval;
- qup->__receive_credit_remaining = interval;
- __netio_fastio_return_credits(qup->__fastio_index, interval);
- }
+ /* ISSUE: It would be nice to defer this until the packet has */
+ /* actually been processed. */
+ tile_net_return_credit(info);
/* Consume this packet. */
qup->__packet_receive_read = index2;
@@ -1543,7 +1550,7 @@
/* Drain all the LIPP buffers. */
while (true) {
- int buffer;
+ unsigned int buffer;
/* NOTE: This should never fail. */
if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&buffer,
@@ -1707,7 +1714,7 @@
if (!hash_default) {
void *va = pfn_to_kaddr(pfn) + f->page_offset;
BUG_ON(PageHighMem(skb_frag_page(f)));
- finv_buffer_remote(va, f->size, 0);
+ finv_buffer_remote(va, skb_frag_size(f), 0);
}
cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
@@ -1735,8 +1742,8 @@
* Sometimes, if "sendfile()" requires copying, we will be called with
* "data" containing the header and payload, with "frags" being empty.
*
- * In theory, "sh->nr_frags" could be 3, but in practice, it seems
- * that this will never actually happen.
+ * Sometimes, for example when using NFS over TCP, a single segment can
+ * span 3 fragments, which must be handled carefully in LEPP.
*
* See "emulate_large_send_offload()" for some reference code, which
* does not handle checksumming.
@@ -1844,10 +1851,8 @@
spin_lock_irqsave(&priv->eq_lock, irqflags);
- /*
- * Handle completions if needed to make room.
- * HACK: Spin until there is sufficient room.
- */
+ /* Handle completions if needed to make room. */
+ /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */
if (lepp_num_free_comp_slots(eq) == 0) {
nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
if (nolds == 0) {
@@ -1861,6 +1866,7 @@
cmd_tail = eq->cmd_tail;
/* Prepare to advance, detecting full queue. */
+ /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */
cmd_next = cmd_tail + cmd_size;
if (cmd_tail < cmd_head && cmd_next >= cmd_head)
goto busy;
@@ -2023,10 +2029,8 @@
spin_lock_irqsave(&priv->eq_lock, irqflags);
- /*
- * Handle completions if needed to make room.
- * HACK: Spin until there is sufficient room.
- */
+ /* Handle completions if needed to make room. */
+ /* NOTE: Return NETDEV_TX_BUSY if there is still no room. */
if (lepp_num_free_comp_slots(eq) == 0) {
nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
if (nolds == 0) {
@@ -2040,6 +2044,7 @@
cmd_tail = eq->cmd_tail;
/* Copy the commands, or fail. */
+ /* NOTE: Return NETDEV_TX_BUSY if the queue is full. */
for (i = 0; i < num_frags; i++) {
/* Prepare to advance, detecting full queue. */
@@ -2261,6 +2266,23 @@
return 0;
}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+ */
+static void tile_net_netpoll(struct net_device *dev)
+{
+ struct tile_net_priv *priv = netdev_priv(dev);
+ disable_percpu_irq(priv->intr_id);
+ tile_net_handle_ingress_interrupt(priv->intr_id, dev);
+ enable_percpu_irq(priv->intr_id, 0);
+}
+#endif
+
+
static const struct net_device_ops tile_net_ops = {
.ndo_open = tile_net_open,
.ndo_stop = tile_net_stop,
@@ -2269,7 +2291,10 @@
.ndo_get_stats = tile_net_get_stats,
.ndo_change_mtu = tile_net_change_mtu,
.ndo_tx_timeout = tile_net_tx_timeout,
- .ndo_set_mac_address = tile_net_set_mac_address
+ .ndo_set_mac_address = tile_net_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tile_net_netpoll,
+#endif
};
@@ -2409,7 +2434,7 @@
*/
static int tile_net_init_module(void)
{
- pr_info("Tilera IPP Net Driver\n");
+ pr_info("Tilera Network Driver\n");
tile_net_devs[0] = tile_net_dev_init("xgbe0");
tile_net_devs[1] = tile_net_dev_init("xgbe1");
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c
index 39b8cf3..fcfa01f 100644
--- a/drivers/net/ethernet/via/via-rhine.c
+++ b/drivers/net/ethernet/via/via-rhine.c
@@ -503,30 +503,32 @@
static int rhine_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
static void rhine_restart_tx(struct net_device *dev);
-static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool high)
+static void rhine_wait_bit(struct rhine_private *rp, u8 reg, u8 mask, bool low)
{
void __iomem *ioaddr = rp->base;
int i;
for (i = 0; i < 1024; i++) {
- if (high ^ !!(ioread8(ioaddr + reg) & mask))
+ bool has_mask_bits = !!(ioread8(ioaddr + reg) & mask);
+
+ if (low ^ has_mask_bits)
break;
udelay(10);
}
if (i > 64) {
netif_dbg(rp, hw, rp->dev, "%s bit wait (%02x/%02x) cycle "
- "count: %04d\n", high ? "high" : "low", reg, mask, i);
+ "count: %04d\n", low ? "low" : "high", reg, mask, i);
}
}
static void rhine_wait_bit_high(struct rhine_private *rp, u8 reg, u8 mask)
{
- rhine_wait_bit(rp, reg, mask, true);
+ rhine_wait_bit(rp, reg, mask, false);
}
static void rhine_wait_bit_low(struct rhine_private *rp, u8 reg, u8 mask)
{
- rhine_wait_bit(rp, reg, mask, false);
+ rhine_wait_bit(rp, reg, mask, true);
}
static u32 rhine_get_events(struct rhine_private *rp)
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h
index cc83af0..44b8d2b 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet.h
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h
@@ -2,9 +2,7 @@
* Definitions for Xilinx Axi Ethernet device driver.
*
* Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
*/
#ifndef XILINX_AXIENET_H
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index 2fcbeba..9c365e1 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -4,9 +4,9 @@
* Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi
* Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net>
* Copyright (c) 2008-2009 Secret Lab Technologies Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
*
* This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6
* and Spartan6.
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
index d70b6e7..e90e1f4 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c
@@ -2,9 +2,9 @@
* MDIO bus driver for the Xilinx Axi Ethernet device
*
* Copyright (c) 2009 Secret Lab Technologies, Ltd.
- * Copyright (c) 2010 Xilinx, Inc. All rights reserved.
- * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch>
- * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch>
+ * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu>
+ * Copyright (c) 2010 - 2011 PetaLogix
+ * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved.
*/
#include <linux/of_address.h>
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index dd29478..2d59138 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -44,6 +44,7 @@
/* point back to our device context */
struct hv_device *device_ctx;
struct delayed_work dwork;
+ struct work_struct work;
};
@@ -51,30 +52,22 @@
module_param(ring_size, int, S_IRUGO);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
-struct set_multicast_work {
- struct work_struct work;
- struct net_device *net;
-};
-
static void do_set_multicast(struct work_struct *w)
{
- struct set_multicast_work *swk =
- container_of(w, struct set_multicast_work, work);
- struct net_device *net = swk->net;
-
- struct net_device_context *ndevctx = netdev_priv(net);
+ struct net_device_context *ndevctx =
+ container_of(w, struct net_device_context, work);
struct netvsc_device *nvdev;
struct rndis_device *rdev;
nvdev = hv_get_drvdata(ndevctx->device_ctx);
- if (nvdev == NULL)
- goto out;
+ if (nvdev == NULL || nvdev->ndev == NULL)
+ return;
rdev = nvdev->extension;
if (rdev == NULL)
- goto out;
+ return;
- if (net->flags & IFF_PROMISC)
+ if (nvdev->ndev->flags & IFF_PROMISC)
rndis_filter_set_packet_filter(rdev,
NDIS_PACKET_TYPE_PROMISCUOUS);
else
@@ -82,21 +75,13 @@
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
-
-out:
- kfree(w);
}
static void netvsc_set_multicast_list(struct net_device *net)
{
- struct set_multicast_work *swk =
- kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC);
- if (swk == NULL)
- return;
+ struct net_device_context *net_device_ctx = netdev_priv(net);
- swk->net = net;
- INIT_WORK(&swk->work, do_set_multicast);
- schedule_work(&swk->work);
+ schedule_work(&net_device_ctx->work);
}
static int netvsc_open(struct net_device *net)
@@ -125,6 +110,8 @@
netif_tx_disable(net);
+ /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */
+ cancel_work_sync(&net_device_ctx->work);
ret = rndis_filter_close(device_obj);
if (ret != 0)
netdev_err(net, "unable to close device (ret %d).\n", ret);
@@ -335,6 +322,7 @@
nvdev->start_remove = true;
cancel_delayed_work_sync(&ndevctx->dwork);
+ cancel_work_sync(&ndevctx->work);
netif_tx_disable(ndev);
rndis_filter_device_remove(hdev);
@@ -403,6 +391,7 @@
net_device_ctx->device_ctx = dev;
hv_set_drvdata(dev, net);
INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp);
+ INIT_WORK(&net_device_ctx->work, do_set_multicast);
net->netdev_ops = &device_ops;
@@ -456,6 +445,7 @@
ndev_ctx = netdev_priv(net);
cancel_delayed_work_sync(&ndev_ctx->dwork);
+ cancel_work_sync(&ndev_ctx->work);
/* Stop outbound asap */
netif_tx_disable(net);
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index a0d1913..e250675 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -147,7 +147,7 @@
struct dma_async_tx_descriptor *desc;
struct dma_chan *chan = buf->chan;
- desc = chan->device->device_prep_slave_sg(chan, &buf->sg, 1, dir,
+ desc = dmaengine_prep_slave_sg(chan, &buf->sg, 1, dir,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (desc) {
desc->callback = cb;
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index 0856e1b..5ac46f5 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -40,6 +40,7 @@
#define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */
#define IP1001_APS_ON 11 /* IP1001 APS Mode bit */
#define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */
+#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */
static int ip175c_config_init(struct phy_device *phydev)
{
@@ -162,7 +163,8 @@
/* Enable Auto Power Saving mode */
c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
c |= IP101A_G_APS_ON;
- return c;
+
+ return phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
}
static int ip175c_read_status(struct phy_device *phydev)
@@ -184,6 +186,15 @@
return 0;
}
+static int ip101a_g_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static struct phy_driver ip175c_driver = {
.phy_id = 0x02430d80,
.name = "ICPlus IP175C",
@@ -203,7 +214,6 @@
.phy_id_mask = 0x0ffffff0,
.features = PHY_GBIT_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause,
- .flags = PHY_HAS_INTERRUPT,
.config_init = &ip1001_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
@@ -219,6 +229,7 @@
.features = PHY_BASIC_FEATURES | SUPPORTED_Pause |
SUPPORTED_Asym_Pause,
.flags = PHY_HAS_INTERRUPT,
+ .ack_interrupt = ip101a_g_ack_interrupt,
.config_init = &ip101a_g_config_init,
.config_aneg = &genphy_config_aneg,
.read_status = &genphy_read_status,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 159da29..21d7151 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -968,7 +968,6 @@
proto = npindex_to_proto[npi];
put_unaligned_be16(proto, pp);
- netif_stop_queue(dev);
skb_queue_tail(&ppp->file.xq, skb);
ppp_xmit_process(ppp);
return NETDEV_TX_OK;
@@ -1063,6 +1062,8 @@
code that we can accept some more. */
if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
netif_wake_queue(ppp->dev);
+ else
+ netif_stop_queue(ppp->dev);
}
ppp_xmit_unlock(ppp);
}
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index a57f057..91d2588 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -375,8 +375,8 @@
struct net_device *ndev = rio_get_drvdata(rdev);
struct rionet_peer *peer, *tmp;
- free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
- __fls(sizeof(void *)) + 4 : 0);
+ free_pages((unsigned long)rionet_active, get_order(sizeof(void *) *
+ RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
unregister_netdev(ndev);
free_netdev(ndev);
@@ -432,15 +432,16 @@
int rc = 0;
struct rionet_private *rnet;
u16 device_id;
+ const size_t rionet_active_bytes = sizeof(void *) *
+ RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
- mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
+ get_order(rionet_active_bytes));
if (!rionet_active) {
rc = -ENOMEM;
goto out;
}
- memset((void *)rionet_active, 0, sizeof(void *) *
- RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
+ memset((void *)rionet_active, 0, rionet_active_bytes);
/* Set up private area */
rnet = netdev_priv(ndev);
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 5ee032c..42b5151 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -355,7 +355,7 @@
u32 packet_len;
u32 padbytes = 0xffff0000;
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
if ((!skb_cloned(skb)) &&
((headroom + tailroom) >= (4 + padlen))) {
@@ -377,7 +377,7 @@
cpu_to_le32s(&packet_len);
skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
- if ((skb->len % 512) == 0) {
+ if (padlen) {
cpu_to_le32s(&padbytes);
memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
skb_put(skb, sizeof(padbytes));
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 3886b30..3e41b00 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -165,13 +165,13 @@
memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 1, req->actual_length,
- req->actual_length);
+ PAGE_SIZE);
page = NULL;
}
} else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, 0, req->actual_length,
- req->actual_length);
+ PAGE_SIZE);
page = NULL;
}
if (req->actual_length < PAGE_SIZE)
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index 439690b..685a4e2 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -93,6 +93,7 @@
/* no jumbogram (16K) support for now */
dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 552d24b..d316503b 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -365,6 +365,27 @@
.data = BIT(4), /* interface whitelist bitmap */
};
+/* Sierra Wireless provide equally useless interface descriptors
+ * Devices in QMI mode can be switched between two different
+ * configurations:
+ * a) USB interface #8 is QMI/wwan
+ * b) USB interfaces #8, #19 and #20 are QMI/wwan
+ *
+ * Both configurations provide a number of other interfaces (serial++),
+ * some of which have the same endpoint configuration as we expect, so
+ * a whitelist or blacklist is necessary.
+ *
+ * FIXME: The below whitelist should include BIT(20). It does not
+ * because I cannot get it to work...
+ */
+static const struct driver_info qmi_wwan_sierra = {
+ .description = "Sierra Wireless wwan/QMI device",
+ .flags = FLAG_WWAN,
+ .bind = qmi_wwan_bind_gobi,
+ .unbind = qmi_wwan_unbind_shared,
+ .manage_power = qmi_wwan_manage_power,
+ .data = BIT(8) | BIT(19), /* interface whitelist bitmap */
+};
#define HUAWEI_VENDOR_ID 0x12D1
#define QMI_GOBI_DEVICE(vend, prod) \
@@ -445,6 +466,15 @@
.bInterfaceProtocol = 0xff,
.driver_info = (unsigned long)&qmi_wwan_force_int4,
},
+ { /* Sierra Wireless MC77xx in QMI mode */
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = 0x1199,
+ .idProduct = 0x68a2,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .driver_info = (unsigned long)&qmi_wwan_sierra,
+ },
{QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
{QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
{QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 6dda2fe..d363b31 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -85,32 +85,6 @@
#define INT_CRERR_CNT 0x06
#define INT_COL_CNT 0x07
-/* Transmit status register errors */
-#define TSR_ECOL (1<<5)
-#define TSR_LCOL (1<<4)
-#define TSR_LOSS_CRS (1<<3)
-#define TSR_JBR (1<<2)
-#define TSR_ERRORS (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR)
-/* Receive status register errors */
-#define RSR_CRC (1<<2)
-#define RSR_FAE (1<<1)
-#define RSR_ERRORS (RSR_CRC | RSR_FAE)
-
-/* Media status register definitions */
-#define MSR_DUPLEX (1<<4)
-#define MSR_SPEED (1<<3)
-#define MSR_LINK (1<<2)
-
-/* Interrupt pipe data */
-#define INT_TSR 0x00
-#define INT_RSR 0x01
-#define INT_MSR 0x02
-#define INT_WAKSR 0x03
-#define INT_TXOK_CNT 0x04
-#define INT_RXLOST_CNT 0x05
-#define INT_CRERR_CNT 0x06
-#define INT_COL_CNT 0x07
-
#define RTL8150_MTU 1540
#define RTL8150_TX_TIMEOUT (HZ)
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 187d01c..00103a8 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -98,7 +98,7 @@
if (unlikely(ret < 0))
netdev_warn(dev->net,
- "Failed to read register index 0x%08x", index);
+ "Failed to read reg index 0x%08x: %d", index, ret);
le32_to_cpus(buf);
*data = *buf;
@@ -128,7 +128,7 @@
if (unlikely(ret < 0))
netdev_warn(dev->net,
- "Failed to write register index 0x%08x", index);
+ "Failed to write reg index 0x%08x: %d", index, ret);
kfree(buf);
@@ -171,7 +171,7 @@
idx &= dev->mii.reg_num_mask;
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
- | MII_ACCESS_READ;
+ | MII_ACCESS_READ | MII_ACCESS_BUSY;
ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
check_warn_goto_done(ret, "Error writing MII_ACCESS");
@@ -210,7 +210,7 @@
idx &= dev->mii.reg_num_mask;
addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
| ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
- | MII_ACCESS_WRITE;
+ | MII_ACCESS_WRITE | MII_ACCESS_BUSY;
ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
check_warn_goto_done(ret, "Error writing MII_ACCESS");
@@ -508,9 +508,10 @@
u16 lcladv, rmtadv;
int ret;
- /* clear interrupt status */
+ /* read and write to clear phy interrupt status */
ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
check_warn_return(ret, "Error reading PHY_INT_SRC");
+ smsc75xx_mdio_write(dev->net, mii->phy_id, PHY_INT_SRC, 0xffff);
ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
check_warn_return(ret, "Error writing INT_STS");
@@ -643,7 +644,7 @@
static int smsc75xx_phy_initialize(struct usbnet *dev)
{
- int bmcr, timeout = 0;
+ int bmcr, ret, timeout = 0;
/* Initialize MII structure */
dev->mii.dev = dev->net;
@@ -651,6 +652,7 @@
dev->mii.mdio_write = smsc75xx_mdio_write;
dev->mii.phy_id_mask = 0x1f;
dev->mii.reg_num_mask = 0x1f;
+ dev->mii.supports_gmii = 1;
dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID;
/* reset phy and wait for reset to complete */
@@ -661,7 +663,7 @@
bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
check_warn_return(bmcr, "Error reading MII_BMCR");
timeout++;
- } while ((bmcr & MII_BMCR) && (timeout < 100));
+ } while ((bmcr & BMCR_RESET) && (timeout < 100));
if (timeout >= 100) {
netdev_warn(dev->net, "timeout on PHY Reset");
@@ -671,10 +673,13 @@
smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
ADVERTISE_PAUSE_ASYM);
+ smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+ ADVERTISE_1000FULL);
- /* read to clear */
- smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
- check_warn_return(bmcr, "Error reading PHY_INT_SRC");
+ /* read and write to clear phy interrupt status */
+ ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+ check_warn_return(ret, "Error reading PHY_INT_SRC");
+ smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
PHY_INT_MASK_DEFAULT);
@@ -946,6 +951,14 @@
ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
+ /* allow mac to detect speed and duplex from phy */
+ ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
+ check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+
+ buf |= (MAC_CR_ADD | MAC_CR_ASD);
+ ret = smsc75xx_write_reg(dev, MAC_CR, buf);
+ check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
+
ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
@@ -1051,6 +1064,7 @@
dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
@@ -1211,7 +1225,7 @@
.rx_fixup = smsc75xx_rx_fixup,
.tx_fixup = smsc75xx_tx_fixup,
.status = smsc75xx_status,
- .flags = FLAG_ETHER | FLAG_SEND_ZLP,
+ .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
static const struct usb_device_id products[] = {
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 5f19f84..94ae669 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1017,6 +1017,7 @@
dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
@@ -1191,7 +1192,7 @@
.rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status,
- .flags = FLAG_ETHER | FLAG_SEND_ZLP,
+ .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
static const struct usb_device_id products[] = {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index b7b3f5b..2d927fb 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -210,6 +210,7 @@
} else {
usb_fill_int_urb(dev->interrupt, dev->udev, pipe,
buf, maxp, intr_complete, dev, period);
+ dev->interrupt->transfer_flags |= URB_FREE_BUFFER;
dev_dbg(&intf->dev,
"status ep%din, %d bytes period %d\n",
usb_pipeendpoint(pipe), maxp, period);
@@ -1443,7 +1444,7 @@
status = register_netdev (net);
if (status)
- goto out3;
+ goto out4;
netif_info(dev, probe, dev->net,
"register '%s' at usb-%s-%s, %s, %pM\n",
udev->dev.driver->name,
@@ -1461,6 +1462,8 @@
return 0;
+out4:
+ usb_free_urb(dev->interrupt);
out3:
if (info->unbind)
info->unbind (dev, udev);
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c
index c3197ce..34db195 100644
--- a/drivers/net/usb/zaurus.c
+++ b/drivers/net/usb/zaurus.c
@@ -337,6 +337,11 @@
.driver_info = ZAURUS_PXA_INFO,
},
{
+ /* Motorola Rokr E6 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
/* Motorola MOTOMAGX phones */
USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 019da01..af8acc8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -625,16 +625,16 @@
/* This can happen with OOM and indirect buffers. */
if (unlikely(capacity < 0)) {
- if (net_ratelimit()) {
- if (likely(capacity == -ENOMEM)) {
+ if (likely(capacity == -ENOMEM)) {
+ if (net_ratelimit())
dev_warn(&dev->dev,
"TX queue failure: out of memory\n");
- } else {
- dev->stats.tx_fifo_errors++;
+ } else {
+ dev->stats.tx_fifo_errors++;
+ if (net_ratelimit())
dev_warn(&dev->dev,
"Unexpected TX queue failure: %d\n",
capacity);
- }
}
dev->stats.tx_dropped++;
kfree_skb(skb);
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index ebb9f24..1a62318 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -2483,6 +2483,7 @@
pr_err("Control memory remap failed\n");
pci_release_regions(pdev);
pci_disable_device(pdev);
+ iounmap(card->mem);
kfree(card);
return -ENODEV;
}
diff --git a/drivers/net/wimax/i2400m/debugfs.c b/drivers/net/wimax/i2400m/debugfs.c
index 129ba36..4b66ab1 100644
--- a/drivers/net/wimax/i2400m/debugfs.c
+++ b/drivers/net/wimax/i2400m/debugfs.c
@@ -53,17 +53,6 @@
&fops_netdev_queue_stopped);
}
-
-/*
- * inode->i_private has the @data argument to debugfs_create_file()
- */
-static
-int i2400m_stats_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
/*
* We don't allow partial reads of this file, as then the reader would
* get weirdly confused data as it is updated.
@@ -117,7 +106,7 @@
static
const struct file_operations i2400m_rx_stats_fops = {
.owner = THIS_MODULE,
- .open = i2400m_stats_open,
+ .open = simple_open,
.read = i2400m_rx_stats_read,
.write = i2400m_rx_stats_write,
.llseek = default_llseek,
@@ -170,7 +159,7 @@
static
const struct file_operations i2400m_tx_stats_fops = {
.owner = THIS_MODULE,
- .open = i2400m_stats_open,
+ .open = simple_open,
.read = i2400m_tx_stats_read,
.write = i2400m_tx_stats_write,
.llseek = default_llseek,
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index 63e4b70..1d76ae8 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -597,7 +597,8 @@
struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1);
+ strncpy(info->fw_version,
+ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
if (net_dev->dev.parent)
strncpy(info->bus_info, dev_name(net_dev->dev.parent),
sizeof(info->bus_info) - 1);
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c
index 2c1b8b6..29b1e03 100644
--- a/drivers/net/wimax/i2400m/usb.c
+++ b/drivers/net/wimax/i2400m/usb.c
@@ -339,6 +339,23 @@
return result;
}
+static void i2400mu_get_drvinfo(struct net_device *net_dev,
+ struct ethtool_drvinfo *info)
+{
+ struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
+ struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
+ struct usb_device *udev = i2400mu->usb_dev;
+
+ strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
+ strncpy(info->fw_version,
+ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
+ usb_make_path(udev, info->bus_info, sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops i2400mu_ethtool_ops = {
+ .get_drvinfo = i2400mu_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+};
static
void i2400mu_netdev_setup(struct net_device *net_dev)
@@ -347,6 +364,7 @@
struct i2400mu *i2400mu = container_of(i2400m, struct i2400mu, i2400m);
i2400mu_init(i2400mu);
i2400m_netdev_setup(net_dev);
+ net_dev->ethtool_ops = &i2400mu_ethtool_ops;
}
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index 8faa129..aec33cc 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -19,6 +19,7 @@
#include <linux/nl80211.h>
#include <linux/platform_device.h>
#include <linux/etherdevice.h>
+#include <linux/export.h>
#include <ar231x_platform.h>
#include "ath5k.h"
#include "debug.h"
@@ -119,7 +120,7 @@
if (res == NULL) {
dev_err(&pdev->dev, "no IRQ resource found\n");
ret = -ENXIO;
- goto err_out;
+ goto err_iounmap;
}
irq = res->start;
@@ -128,7 +129,7 @@
if (hw == NULL) {
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
ret = -ENOMEM;
- goto err_out;
+ goto err_iounmap;
}
ah = hw->priv;
@@ -185,6 +186,8 @@
err_free_hw:
ieee80211_free_hw(hw);
platform_set_drvdata(pdev, NULL);
+ err_iounmap:
+ iounmap(mem);
err_out:
return ret;
}
@@ -217,6 +220,7 @@
}
ath5k_deinit_ah(ah);
+ iounmap(ah->iobase);
platform_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 8c5ce8b..e5e8f45 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -71,13 +71,6 @@
module_param_named(debug, ath5k_debug, uint, 0);
-static int ath5k_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-
/* debugfs: registers */
struct reg {
@@ -265,7 +258,7 @@
static const struct file_operations fops_beacon = {
.read = read_file_beacon,
.write = write_file_beacon,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -285,7 +278,7 @@
static const struct file_operations fops_reset = {
.write = write_file_reset,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = noop_llseek,
};
@@ -365,7 +358,7 @@
static const struct file_operations fops_debug = {
.read = read_file_debug,
.write = write_file_debug,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -477,7 +470,7 @@
static const struct file_operations fops_antenna = {
.read = read_file_antenna,
.write = write_file_antenna,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -532,7 +525,7 @@
static const struct file_operations fops_misc = {
.read = read_file_misc,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
};
@@ -647,7 +640,7 @@
static const struct file_operations fops_frameerrors = {
.read = read_file_frameerrors,
.write = write_file_frameerrors,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -810,7 +803,7 @@
static const struct file_operations fops_ani = {
.read = read_file_ani,
.write = write_file_ani,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -881,7 +874,7 @@
static const struct file_operations fops_queue = {
.read = read_file_queue,
.write = write_file_queue,
- .open = ath5k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index 552adb3..d01403a 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -217,12 +217,6 @@
target->credit_info->cur_free_credits);
}
-static int ath6kl_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
void ath6kl_debug_war(struct ath6kl *ar, enum ath6kl_war war)
{
switch (war) {
@@ -263,7 +257,7 @@
static const struct file_operations fops_war_stats = {
.read = read_file_war_stats,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -488,7 +482,7 @@
}
static const struct file_operations fops_fwlog_mask = {
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.read = ath6kl_fwlog_mask_read,
.write = ath6kl_fwlog_mask_write,
.owner = THIS_MODULE,
@@ -634,7 +628,7 @@
static const struct file_operations fops_tgt_stats = {
.read = read_file_tgt_stats,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -699,7 +693,7 @@
static const struct file_operations fops_credit_dist_stats = {
.read = read_file_credit_dist_stats,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -802,7 +796,7 @@
}
static const struct file_operations fops_endpoint_stats = {
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.read = ath6kl_endpoint_stats_read,
.write = ath6kl_endpoint_stats_write,
.owner = THIS_MODULE,
@@ -875,7 +869,7 @@
static const struct file_operations fops_diag_reg_read = {
.read = ath6kl_regread_read,
.write = ath6kl_regread_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -999,7 +993,7 @@
static const struct file_operations fops_lrssi_roam_threshold = {
.read = ath6kl_lrssi_roam_read,
.write = ath6kl_lrssi_roam_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1061,7 +1055,7 @@
static const struct file_operations fops_diag_reg_write = {
.read = ath6kl_regwrite_read,
.write = ath6kl_regwrite_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1166,7 +1160,7 @@
static const struct file_operations fops_roam_table = {
.read = ath6kl_roam_table_read,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1204,7 +1198,7 @@
static const struct file_operations fops_force_roam = {
.write = ath6kl_force_roam_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1244,7 +1238,7 @@
static const struct file_operations fops_roam_mode = {
.write = ath6kl_roam_mode_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1286,7 +1280,7 @@
}
static const struct file_operations fops_keepalive = {
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.read = ath6kl_keepalive_read,
.write = ath6kl_keepalive_write,
.owner = THIS_MODULE,
@@ -1331,7 +1325,7 @@
}
static const struct file_operations fops_disconnect_timeout = {
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.read = ath6kl_disconnect_timeout_read,
.write = ath6kl_disconnect_timeout_write,
.owner = THIS_MODULE,
@@ -1512,7 +1506,7 @@
static const struct file_operations fops_create_qos = {
.write = ath6kl_create_qos_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1560,7 +1554,7 @@
static const struct file_operations fops_delete_qos = {
.write = ath6kl_delete_qos_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1593,7 +1587,7 @@
static const struct file_operations fops_bgscan_int = {
.write = ath6kl_bgscan_int_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1651,7 +1645,7 @@
static const struct file_operations fops_listen_int = {
.read = ath6kl_listen_int_read,
.write = ath6kl_listen_int_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1711,7 +1705,7 @@
static const struct file_operations fops_power_params = {
.write = ath6kl_power_params_write,
- .open = ath6kl_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index d7d8e91..aba0880 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -869,7 +869,7 @@
ar5008_hw_set_channel_regs(ah, chan);
ar5008_hw_init_chain_masks(ah);
ath9k_olc_init(ah);
- ath9k_hw_apply_txpower(ah, chan);
+ ath9k_hw_apply_txpower(ah, chan, false);
/* Write analog registers */
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 59647a3..3d400e8 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -54,7 +54,7 @@
if (val) {
ah->paprd_table_write_done = true;
- ath9k_hw_apply_txpower(ah, chan);
+ ath9k_hw_apply_txpower(ah, chan, false);
}
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index bc992b2..deb6cfb 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -694,7 +694,7 @@
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
- ath9k_hw_apply_txpower(ah, chan);
+ ath9k_hw_apply_txpower(ah, chan, false);
if (AR_SREV_9462(ah)) {
if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 2f4b48e..e5cceb0 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -20,7 +20,6 @@
/* Common calibration code */
-#define ATH9K_NF_TOO_HIGH -60
static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
{
@@ -346,10 +345,10 @@
"NF calibrated [%s] [chain %d] is %d\n",
(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
- if (nf[i] > ATH9K_NF_TOO_HIGH) {
+ if (nf[i] > limit->max) {
ath_dbg(common, CALIBRATE,
"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
- i, nf[i], ATH9K_NF_TOO_HIGH);
+ i, nf[i], limit->max);
nf[i] = limit->max;
} else if (nf[i] < limit->min) {
ath_dbg(common, CALIBRATE,
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 35d1c8e..ff47b32 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -26,11 +26,6 @@
#define REG_READ_D(_ah, _reg) \
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -83,7 +78,7 @@
static const struct file_operations fops_debug = {
.read = read_file_debug,
.write = write_file_debug,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -129,7 +124,7 @@
static const struct file_operations fops_tx_chainmask = {
.read = read_file_tx_chainmask,
.write = write_file_tx_chainmask,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -172,7 +167,7 @@
static const struct file_operations fops_rx_chainmask = {
.read = read_file_rx_chainmask,
.write = write_file_rx_chainmask,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -223,7 +218,7 @@
static const struct file_operations fops_disable_ani = {
.read = read_file_disable_ani,
.write = write_file_disable_ani,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -324,7 +319,7 @@
static const struct file_operations fops_dma = {
.read = read_file_dma,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -446,7 +441,7 @@
static const struct file_operations fops_interrupt = {
.read = read_file_interrupt,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -852,28 +847,28 @@
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static const struct file_operations fops_stations = {
.read = read_file_stations,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static const struct file_operations fops_misc = {
.read = read_file_misc,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static const struct file_operations fops_reset = {
.read = read_file_reset,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1016,7 +1011,7 @@
static const struct file_operations fops_recv = {
.read = read_file_recv,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1055,7 +1050,7 @@
static const struct file_operations fops_regidx = {
.read = read_file_regidx,
.write = write_file_regidx,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1102,7 +1097,7 @@
static const struct file_operations fops_regval = {
.read = read_file_regval,
.write = write_file_regval,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1191,7 +1186,7 @@
static const struct file_operations fops_dump_nfcal = {
.read = read_file_dump_nfcal,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1219,7 +1214,7 @@
static const struct file_operations fops_base_eeprom = {
.read = read_file_base_eeprom,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -1247,7 +1242,7 @@
static const struct file_operations fops_modal_eeprom = {
.read = read_file_modal_eeprom,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/ath/ath9k/dfs_debug.c b/drivers/net/wireless/ath/ath9k/dfs_debug.c
index 106d031..4364c10 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_debug.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_debug.c
@@ -60,16 +60,9 @@
return retval;
}
-static int ath9k_dfs_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static const struct file_operations fops_dfs_stats = {
.read = read_file_dfs,
- .open = ath9k_dfs_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index f272236..b34e8b2 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -824,6 +824,8 @@
regulatory->max_power_level = ratesArray[i];
}
+ ath9k_hw_update_regulatory_maxpower(ah);
+
if (test)
return;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index d3ff33c..3035deb 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -16,12 +16,6 @@
#include "htc.h"
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t read_file_tgt_int_stats(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -75,7 +69,7 @@
static const struct file_operations fops_tgt_int_stats = {
.read = read_file_tgt_int_stats,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -145,7 +139,7 @@
static const struct file_operations fops_tgt_tx_stats = {
.read = read_file_tgt_tx_stats,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -191,7 +185,7 @@
static const struct file_operations fops_tgt_rx_stats = {
.read = read_file_tgt_rx_stats,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -243,7 +237,7 @@
static const struct file_operations fops_xmit = {
.read = read_file_xmit,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -364,7 +358,7 @@
static const struct file_operations fops_recv = {
.read = read_file_recv,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -399,7 +393,7 @@
static const struct file_operations fops_slot = {
.read = read_file_slot,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -446,7 +440,7 @@
static const struct file_operations fops_queue = {
.read = read_file_queue,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -487,7 +481,7 @@
static const struct file_operations fops_debug = {
.read = read_file_debug,
.write = write_file_debug,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -636,7 +630,7 @@
static const struct file_operations fops_base_eeprom = {
.read = read_file_base_eeprom,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -917,7 +911,7 @@
static const struct file_operations fops_modal_eeprom = {
.read = read_file_modal_eeprom,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 6c69e4e..fa84e37 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1454,7 +1454,7 @@
return false;
}
ath9k_hw_set_clockrate(ah);
- ath9k_hw_apply_txpower(ah, chan);
+ ath9k_hw_apply_txpower(ah, chan, false);
ath9k_hw_rfbus_done(ah);
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
@@ -2652,7 +2652,8 @@
return ah->eep_ops->get_eeprom(ah, gain_param);
}
-void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan)
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+ bool test)
{
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
struct ieee80211_channel *channel;
@@ -2673,7 +2674,7 @@
ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(reg, chan),
- ant_reduction, new_pwr, false);
+ ant_reduction, new_pwr, test);
}
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
@@ -2686,7 +2687,7 @@
if (test)
channel->max_power = MAX_RATE_POWER / 2;
- ath9k_hw_apply_txpower(ah, chan);
+ ath9k_hw_apply_txpower(ah, chan, test);
if (test)
channel->max_power = DIV_ROUND_UP(reg->max_power_level, 2);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index aa1680a..e88f182 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -985,7 +985,8 @@
/* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent);
-void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan,
+ bool test);
/*
* Code Specific to AR5008, AR9001 or AR9002,
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 60159f4..cb00645 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -680,7 +680,7 @@
hw->queues = 4;
hw->max_rates = 4;
hw->channel_change_time = 5000;
- hw->max_listen_interval = 10;
+ hw->max_listen_interval = 1;
hw->max_rate_tries = 10;
hw->sta_data_size = sizeof(struct ath_node);
hw->vif_data_size = sizeof(struct ath_vif);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3879485..798ea57 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -118,15 +118,13 @@
if (--sc->ps_usecount != 0)
goto unlock;
- if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
- goto unlock;
-
- if (sc->ps_idle)
+ if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK))
mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
- PS_WAIT_FOR_PSPOLL_DATA)))
+ PS_WAIT_FOR_PSPOLL_DATA |
+ PS_WAIT_FOR_TX_ACK)))
mode = ATH9K_PM_NETWORK_SLEEP;
else
goto unlock;
@@ -640,7 +638,7 @@
an->sta = sta;
an->vif = vif;
- if (sta->ht_cap.ht_supported) {
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
@@ -659,7 +657,7 @@
an->sta = NULL;
#endif
- if (sta->ht_cap.ht_supported)
+ if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ath_tx_node_cleanup(sc, an);
}
@@ -1550,6 +1548,7 @@
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &hw->conf;
+ bool reset_channel = false;
ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex);
@@ -1558,6 +1557,12 @@
sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
if (sc->ps_idle)
ath_cancel_work(sc);
+ else
+ /*
+ * The chip needs a reset to properly wake up from
+ * full sleep
+ */
+ reset_channel = ah->chip_fullsleep;
}
/*
@@ -1586,7 +1591,7 @@
}
}
- if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
int old_pos = -1;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 4f84849..08bb455 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1480,12 +1480,6 @@
#ifdef CONFIG_ATH9K_DEBUGFS
-static int ath9k_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1553,7 +1547,7 @@
static const struct file_operations fops_rcstat = {
.read = read_file_rcstat,
- .open = ath9k_debugfs_open,
+ .open = simple_open,
.owner = THIS_MODULE
};
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index f4ae3ba..1c4583c 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -1913,13 +1913,13 @@
if (sc->rx.frag) {
int space = skb->len - skb_tailroom(hdr_skb);
- sc->rx.frag = NULL;
-
if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
dev_kfree_skb(skb);
goto requeue_drop_frag;
}
+ sc->rx.frag = NULL;
+
skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
skb->len);
dev_kfree_skb_any(skb);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 834e6bc..23eaa1b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1820,6 +1820,7 @@
struct ath_frame_info *fi = get_frame_info(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_buf *bf;
+ int fragno;
u16 seqno;
bf = ath_tx_get_buffer(sc);
@@ -1831,9 +1832,16 @@
ATH_TXBUF_RESET(bf);
if (tid) {
+ fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
seqno = tid->seq_next;
hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT);
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
+ if (fragno)
+ hdr->seq_ctrl |= cpu_to_le16(fragno);
+
+ if (!ieee80211_has_morefrags(hdr->frame_control))
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+
bf->bf_state.seqno = seqno;
}
diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c
index 3c16422..93fe600 100644
--- a/drivers/net/wireless/ath/carl9170/debug.c
+++ b/drivers/net/wireless/ath/carl9170/debug.c
@@ -48,11 +48,6 @@
#define ADD(buf, off, max, fmt, args...) \
off += snprintf(&buf[off], max - off, fmt, ##args);
-static int carl9170_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
struct carl9170_debugfs_fops {
unsigned int read_bufsize;
@@ -178,7 +173,7 @@
.attr = _attr, \
.req_dev_state = _dstate, \
.fops = { \
- .open = carl9170_debugfs_open, \
+ .open = simple_open, \
.read = carl9170_debugfs_read, \
.write = carl9170_debugfs_write, \
.owner = THIS_MODULE \
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index e751fde..e807bd9 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -500,12 +500,6 @@
#undef fappend
-static int b43_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -624,7 +618,7 @@
.read = _read, \
.write = _write, \
.fops = { \
- .open = b43_debugfs_open, \
+ .open = simple_open, \
.read = b43_debugfs_read, \
.write = b43_debugfs_write, \
.llseek = generic_file_llseek, \
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index c79e663..e4d6dc2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4827,8 +4827,14 @@
out_mutex_unlock:
mutex_unlock(&wl->mutex);
- /* reload configuration */
- b43_op_config(hw, ~0);
+ /*
+ * Configuration may have been overwritten during initialization.
+ * Reload the configuration, but only if initialization was
+ * successful. Reloading the configuration after a failed init
+ * may hang the system.
+ */
+ if (!err)
+ b43_op_config(hw, ~0);
return err;
}
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 5e28ad0..1965edb 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -197,12 +197,6 @@
#undef fappend
-static int b43legacy_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -331,7 +325,7 @@
.read = _read, \
.write = _write, \
.fops = { \
- .open = b43legacy_debugfs_open, \
+ .open = simple_open, \
.read = b43legacy_debugfs_read, \
.write = b43legacy_debugfs_write, \
.llseek = generic_file_llseek, \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 4688904..758c115 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -108,9 +108,15 @@
sdio_release_host(sdfunc);
}
} else if (regaddr == SDIO_CCCR_ABORT) {
+ sdfunc = kmemdup(sdiodev->func[0], sizeof(struct sdio_func),
+ GFP_KERNEL);
+ if (!sdfunc)
+ return -ENOMEM;
+ sdfunc->num = 0;
sdio_claim_host(sdfunc);
sdio_writeb(sdfunc, *byte, regaddr, &err_ret);
sdio_release_host(sdfunc);
+ kfree(sdfunc);
} else if (regaddr < 0xF0) {
brcmf_dbg(ERROR, "F0 Wr:0x%02x: write disallowed\n", regaddr);
err_ret = -EPERM;
@@ -486,7 +492,7 @@
kfree(bus_if);
return -ENOMEM;
}
- sdiodev->func[0] = func->card->sdio_func[0];
+ sdiodev->func[0] = func;
sdiodev->func[1] = func;
sdiodev->bus_if = bus_if;
bus_if->bus_priv.sdio = sdiodev;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 2bf5dda..eb3829b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -574,6 +574,8 @@
struct task_struct *dpc_tsk;
struct completion dpc_wait;
+ struct list_head dpc_tsklst;
+ spinlock_t dpc_tl_lock;
struct semaphore sdsem;
@@ -2594,29 +2596,58 @@
return resched;
}
+static inline void brcmf_sdbrcm_adddpctsk(struct brcmf_sdio *bus)
+{
+ struct list_head *new_hd;
+ unsigned long flags;
+
+ if (in_interrupt())
+ new_hd = kzalloc(sizeof(struct list_head), GFP_ATOMIC);
+ else
+ new_hd = kzalloc(sizeof(struct list_head), GFP_KERNEL);
+ if (new_hd == NULL)
+ return;
+
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ list_add_tail(new_hd, &bus->dpc_tsklst);
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+}
+
static int brcmf_sdbrcm_dpc_thread(void *data)
{
struct brcmf_sdio *bus = (struct brcmf_sdio *) data;
+ struct list_head *cur_hd, *tmp_hd;
+ unsigned long flags;
allow_signal(SIGTERM);
/* Run until signal received */
while (1) {
if (kthread_should_stop())
break;
- if (!wait_for_completion_interruptible(&bus->dpc_wait)) {
- /* Call bus dpc unless it indicated down
- (then clean stop) */
- if (bus->sdiodev->bus_if->state != BRCMF_BUS_DOWN) {
- if (brcmf_sdbrcm_dpc(bus))
- complete(&bus->dpc_wait);
- } else {
+
+ if (list_empty(&bus->dpc_tsklst))
+ if (wait_for_completion_interruptible(&bus->dpc_wait))
+ break;
+
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ list_for_each_safe(cur_hd, tmp_hd, &bus->dpc_tsklst) {
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
+
+ if (bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) {
/* after stopping the bus, exit thread */
brcmf_sdbrcm_bus_stop(bus->sdiodev->dev);
bus->dpc_tsk = NULL;
break;
}
- } else
- break;
+
+ if (brcmf_sdbrcm_dpc(bus))
+ brcmf_sdbrcm_adddpctsk(bus);
+
+ spin_lock_irqsave(&bus->dpc_tl_lock, flags);
+ list_del(cur_hd);
+ kfree(cur_hd);
+ }
+ spin_unlock_irqrestore(&bus->dpc_tl_lock, flags);
}
return 0;
}
@@ -2669,8 +2700,10 @@
/* Schedule DPC if needed to send queued packet(s) */
if (!bus->dpc_sched) {
bus->dpc_sched = true;
- if (bus->dpc_tsk)
+ if (bus->dpc_tsk) {
+ brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait);
+ }
}
return ret;
@@ -3514,8 +3547,10 @@
brcmf_dbg(ERROR, "isr w/o interrupt configured!\n");
bus->dpc_sched = true;
- if (bus->dpc_tsk)
+ if (bus->dpc_tsk) {
+ brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait);
+ }
}
static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus)
@@ -3559,8 +3594,10 @@
bus->ipend = true;
bus->dpc_sched = true;
- if (bus->dpc_tsk)
+ if (bus->dpc_tsk) {
+ brcmf_sdbrcm_adddpctsk(bus);
complete(&bus->dpc_wait);
+ }
}
}
@@ -3897,6 +3934,8 @@
}
/* Initialize DPC thread */
init_completion(&bus->dpc_wait);
+ INIT_LIST_HEAD(&bus->dpc_tsklst);
+ spin_lock_init(&bus->dpc_tl_lock);
bus->dpc_tsk = kthread_run(brcmf_sdbrcm_dpc_thread,
bus, "brcmf_dpc");
if (IS_ERR(bus->dpc_tsk)) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 231ddf4..b4d9279 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -847,8 +847,7 @@
*/
if (!(txs->status & TX_STATUS_AMPDU)
&& (txs->status & TX_STATUS_INTERMEDIATE)) {
- wiphy_err(wlc->wiphy, "%s: INTERMEDIATE but not AMPDU\n",
- __func__);
+ BCMMSG(wlc->wiphy, "INTERMEDIATE but not AMPDU\n");
return false;
}
@@ -7614,6 +7613,7 @@
{
int len_mpdu;
struct ieee80211_rx_status rx_status;
+ struct ieee80211_hdr *hdr;
memset(&rx_status, 0, sizeof(rx_status));
prep_mac80211_status(wlc, rxh, p, &rx_status);
@@ -7623,6 +7623,13 @@
skb_pull(p, D11_PHY_HDR_LEN);
__skb_trim(p, len_mpdu);
+ /* unmute transmit */
+ if (wlc->hw->suspended_fifos) {
+ hdr = (struct ieee80211_hdr *)p->data;
+ if (ieee80211_is_beacon(hdr->frame_control))
+ brcms_b_mute(wlc->hw, false);
+ }
+
memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 4fcdac6..1779db3 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -2191,6 +2191,7 @@
{
int rc = 0;
unsigned long flags;
+ unsigned long now, end;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
@@ -2232,10 +2233,20 @@
}
spin_unlock_irqrestore(&priv->lock, flags);
+ now = jiffies;
+ end = now + HOST_COMPLETE_TIMEOUT;
+again:
rc = wait_event_interruptible_timeout(priv->wait_command_queue,
!(priv->
status & STATUS_HCMD_ACTIVE),
- HOST_COMPLETE_TIMEOUT);
+ end - now);
+ if (rc < 0) {
+ now = jiffies;
+ if (time_before(now, end))
+ goto again;
+ rc = 0;
+ }
+
if (rc == 0) {
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
@@ -11507,9 +11518,9 @@
rc = -ENOMEM;
goto out;
}
- /* translate geo->bg to a_band.channels */
+ /* translate geo->a to a_band.channels */
for (i = 0; i < geo->a_channels; i++) {
- a_band->channels[i].band = IEEE80211_BAND_2GHZ;
+ a_band->channels[i].band = IEEE80211_BAND_5GHZ;
a_band->channels[i].center_freq = geo->a[i].freq;
a_band->channels[i].hw_value = geo->a[i].channel;
a_band->channels[i].max_power = geo->a[i].max_power;
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index 0c12093..faec404 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -2673,8 +2673,6 @@
if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
mutex_lock(&il->mutex);
- /* FIXME: vif can be dereferenced */
- il->vif = NULL;
il->is_open = 0;
mutex_unlock(&il->mutex);
il3945_down(il);
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c
index 70bee1a..4b10157 100644
--- a/drivers/net/wireless/iwlegacy/3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/3945-rs.c
@@ -821,12 +821,6 @@
}
#ifdef CONFIG_MAC80211_DEBUGFS
-static int
-il3945_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
static ssize_t
il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
@@ -862,7 +856,7 @@
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.read = il3945_sta_dbgfs_stats_table_read,
- .open = il3945_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 17f1c68..c46275a 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5652,8 +5652,6 @@
if (test_and_clear_bit(S_FW_ERROR, &il->status)) {
mutex_lock(&il->mutex);
- /* FIXME: do we dereference vif without mutex locked ? */
- il->vif = NULL;
il->is_open = 0;
__il4965_down(il);
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c
index d7e2856..11ab124 100644
--- a/drivers/net/wireless/iwlegacy/4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/4965-rs.c
@@ -2518,12 +2518,6 @@
}
#ifdef CONFIG_MAC80211_DEBUGFS
-static int
-il4965_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
static void
il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
@@ -2695,7 +2689,7 @@
static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
.write = il4965_rs_sta_dbgfs_scale_table_write,
.read = il4965_rs_sta_dbgfs_scale_table_read,
- .open = il4965_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -2740,7 +2734,7 @@
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.read = il4965_rs_sta_dbgfs_stats_table_read,
- .open = il4965_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -2768,7 +2762,7 @@
static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
.read = il4965_rs_sta_dbgfs_rate_scale_data_read,
- .open = il4965_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index e5ac047..eaf24945 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -4508,6 +4508,7 @@
{
struct il_priv *il = hw->priv;
int err;
+ bool reset;
mutex_lock(&il->mutex);
D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr);
@@ -4518,7 +4519,12 @@
goto out;
}
- if (il->vif) {
+ /*
+ * We do not support multiple virtual interfaces, but on hardware reset
+ * we have to add the same interface again.
+ */
+ reset = (il->vif == vif);
+ if (il->vif && !reset) {
err = -EOPNOTSUPP;
goto out;
}
@@ -4528,8 +4534,11 @@
err = il_set_mode(il);
if (err) {
- il->vif = NULL;
- il->iw_mode = NL80211_IFTYPE_STATION;
+ IL_WARN("Fail to set mode %d\n", vif->type);
+ if (!reset) {
+ il->vif = NULL;
+ il->iw_mode = NL80211_IFTYPE_STATION;
+ }
}
out:
@@ -5279,9 +5288,9 @@
D_MAC80211("BSSID %pM\n", bss_conf->bssid);
/*
- * If there is currently a HW scan going on in the
- * background then we need to cancel it else the RXON
- * below/in post_associate will fail.
+ * If there is currently a HW scan going on in the background,
+ * then we need to cancel it, otherwise sometimes we are not
+ * able to authenticate (FIXME: why ?)
*/
if (il_scan_cancel_timeout(il, 100)) {
D_MAC80211("leave - scan abort failed\n");
@@ -5290,14 +5299,10 @@
}
/* mac80211 only sets assoc when in STATION mode */
- if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
- memcpy(il->staging.bssid_addr, bss_conf->bssid,
- ETH_ALEN);
+ memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
- /* currently needed in a few places */
- memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
- } else
- il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ /* FIXME: currently needed in a few places */
+ memcpy(il->bssid, bss_conf->bssid, ETH_ALEN);
}
/*
diff --git a/drivers/net/wireless/iwlegacy/debug.c b/drivers/net/wireless/iwlegacy/debug.c
index 2298491..eff2650 100644
--- a/drivers/net/wireless/iwlegacy/debug.c
+++ b/drivers/net/wireless/iwlegacy/debug.c
@@ -160,18 +160,12 @@
const char __user *user_buf, \
size_t count, loff_t *ppos);
-static int
-il_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
#define DEBUGFS_READ_FILE_OPS(name) \
DEBUGFS_READ_FUNC(name); \
static const struct file_operations il_dbgfs_##name##_ops = { \
.read = il_dbgfs_##name##_read, \
- .open = il_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -179,7 +173,7 @@
DEBUGFS_WRITE_FUNC(name); \
static const struct file_operations il_dbgfs_##name##_ops = { \
.write = il_dbgfs_##name##_write, \
- .open = il_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -189,7 +183,7 @@
static const struct file_operations il_dbgfs_##name##_ops = { \
.write = il_dbgfs_##name##_write, \
.read = il_dbgfs_##name##_read, \
- .open = il_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 5b0d888..8d80e23 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -46,8 +46,8 @@
#include "iwl-prph.h"
/* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 6
-#define IWL100_UCODE_API_MAX 6
+#define IWL1000_UCODE_API_MAX 5
+#define IWL100_UCODE_API_MAX 5
/* Oldest version we won't warn about */
#define IWL1000_UCODE_API_OK 5
@@ -226,5 +226,5 @@
IWL_DEVICE_100,
};
-MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL100_MODULE_FIRMWARE(IWL100_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 5635b9e..ea10862 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -51,10 +51,10 @@
#define IWL135_UCODE_API_MAX 6
/* Oldest version we won't warn about */
-#define IWL2030_UCODE_API_OK 5
-#define IWL2000_UCODE_API_OK 5
-#define IWL105_UCODE_API_OK 5
-#define IWL135_UCODE_API_OK 5
+#define IWL2030_UCODE_API_OK 6
+#define IWL2000_UCODE_API_OK 6
+#define IWL105_UCODE_API_OK 6
+#define IWL135_UCODE_API_OK 6
/* Lowest firmware API version supported */
#define IWL2030_UCODE_API_MIN 5
@@ -328,7 +328,7 @@
.ht_params = &iwl2000_ht_params,
};
-MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_OK));
+MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_OK));
+MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a805e97..de0920c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -51,6 +51,10 @@
#define IWL5000_UCODE_API_MAX 5
#define IWL5150_UCODE_API_MAX 2
+/* Oldest version we won't warn about */
+#define IWL5000_UCODE_API_OK 5
+#define IWL5150_UCODE_API_OK 2
+
/* Lowest firmware API version supported */
#define IWL5000_UCODE_API_MIN 1
#define IWL5150_UCODE_API_MIN 1
@@ -326,6 +330,7 @@
#define IWL_DEVICE_5000 \
.fw_name_pre = IWL5000_FW_PRE, \
.ucode_api_max = IWL5000_UCODE_API_MAX, \
+ .ucode_api_ok = IWL5000_UCODE_API_OK, \
.ucode_api_min = IWL5000_UCODE_API_MIN, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
@@ -371,6 +376,7 @@
.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_ok = IWL5000_UCODE_API_OK,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.max_inst_size = IWLAGN_RTC_INST_SIZE,
.max_data_size = IWLAGN_RTC_DATA_SIZE,
@@ -386,6 +392,7 @@
#define IWL_DEVICE_5150 \
.fw_name_pre = IWL5150_FW_PRE, \
.ucode_api_max = IWL5150_UCODE_API_MAX, \
+ .ucode_api_ok = IWL5150_UCODE_API_OK, \
.ucode_api_min = IWL5150_UCODE_API_MIN, \
.max_inst_size = IWLAGN_RTC_INST_SIZE, \
.max_data_size = IWLAGN_RTC_DATA_SIZE, \
@@ -409,5 +416,5 @@
IWL_DEVICE_5150,
};
-MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_OK));
+MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 64060cd..f0c9150 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -53,6 +53,8 @@
/* Oldest version we won't warn about */
#define IWL6000_UCODE_API_OK 4
#define IWL6000G2_UCODE_API_OK 5
+#define IWL6050_UCODE_API_OK 5
+#define IWL6000G2B_UCODE_API_OK 6
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 4
@@ -388,7 +390,7 @@
#define IWL_DEVICE_6030 \
.fw_name_pre = IWL6030_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
- .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
+ .ucode_api_ok = IWL6000G2B_UCODE_API_OK, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
@@ -557,6 +559,6 @@
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_OK));
-MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_OK));
+MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 53f8c51..7e590b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -3083,11 +3083,6 @@
}
#ifdef CONFIG_MAC80211_DEBUGFS
-static int open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
u32 *rate_n_flags, int index)
{
@@ -3226,7 +3221,7 @@
static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
.write = rs_sta_dbgfs_scale_table_write,
.read = rs_sta_dbgfs_scale_table_read,
- .open = open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
@@ -3269,7 +3264,7 @@
static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
.read = rs_sta_dbgfs_stats_table_read,
- .open = open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -3295,7 +3290,7 @@
static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = {
.read = rs_sta_dbgfs_rate_scale_data_read,
- .open = open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index f1226dbf..2a9a16f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -863,7 +863,6 @@
void iwlagn_prepare_restart(struct iwl_priv *priv)
{
- struct iwl_rxon_context *ctx;
bool bt_full_concurrent;
u8 bt_ci_compliance;
u8 bt_load;
@@ -872,8 +871,6 @@
lockdep_assert_held(&priv->mutex);
- for_each_context(priv, ctx)
- ctx->vif = NULL;
priv->is_open = 0;
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index b7b1c04..2bbaebd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -84,17 +84,11 @@
size_t count, loff_t *ppos);
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define DEBUGFS_READ_FILE_OPS(name) \
DEBUGFS_READ_FUNC(name); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.read = iwl_dbgfs_##name##_read, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -102,7 +96,7 @@
DEBUGFS_WRITE_FUNC(name); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -113,7 +107,7 @@
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.read = iwl_dbgfs_##name##_read, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index 9020809..74bce97 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -104,15 +104,29 @@
* (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04
* bytes from one another. Each TFD circular buffer in DRAM must be 256-byte
* aligned (address bits 0-7 must be 0).
+ * Later devices have 20 (5000 series) or 30 (higher) queues, but the registers
+ * for them are in different places.
*
* Bit fields in each pointer register:
* 27-0: TFD CB physical base address [35:8], must be 256-byte aligned
*/
-#define FH_MEM_CBBC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
-#define FH_MEM_CBBC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10)
+#define FH_MEM_CBBC_0_15_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_MEM_CBBC_0_15_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10)
+#define FH_MEM_CBBC_16_19_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBF0)
+#define FH_MEM_CBBC_16_19_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_CBBC_20_31_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xB20)
+#define FH_MEM_CBBC_20_31_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xB80)
-/* Find TFD CB base pointer for given queue (range 0-15). */
-#define FH_MEM_CBBC_QUEUE(x) (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
+/* Find TFD CB base pointer for given queue */
+static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
+{
+ if (chnl < 16)
+ return FH_MEM_CBBC_0_15_LOWER_BOUND + 4 * chnl;
+ if (chnl < 20)
+ return FH_MEM_CBBC_16_19_LOWER_BOUND + 4 * (chnl - 16);
+ WARN_ON_ONCE(chnl >= 32);
+ return FH_MEM_CBBC_20_31_LOWER_BOUND + 4 * (chnl - 20);
+}
/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index b6805f8..c24a713 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -1244,6 +1244,7 @@
struct iwl_rxon_context *tmp, *ctx = NULL;
int err;
enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
+ bool reset = false;
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
viftype, vif->addr);
@@ -1265,6 +1266,13 @@
tmp->interface_modes | tmp->exclusive_interface_modes;
if (tmp->vif) {
+ /* On reset we need to add the same interface again */
+ if (tmp->vif == vif) {
+ reset = true;
+ ctx = tmp;
+ break;
+ }
+
/* check if this busy context is exclusive */
if (tmp->exclusive_interface_modes &
BIT(tmp->vif->type)) {
@@ -1291,7 +1299,7 @@
ctx->vif = vif;
err = iwl_setup_interface(priv, ctx);
- if (!err)
+ if (!err || reset)
goto out;
ctx->vif = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 75dc20b..3b106929 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -223,12 +223,33 @@
#define SCD_AIT (SCD_BASE + 0x0c)
#define SCD_TXFACT (SCD_BASE + 0x10)
#define SCD_ACTIVE (SCD_BASE + 0x14)
-#define SCD_QUEUE_WRPTR(x) (SCD_BASE + 0x18 + (x) * 4)
-#define SCD_QUEUE_RDPTR(x) (SCD_BASE + 0x68 + (x) * 4)
#define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8)
#define SCD_AGGR_SEL (SCD_BASE + 0x248)
#define SCD_INTERRUPT_MASK (SCD_BASE + 0x108)
-#define SCD_QUEUE_STATUS_BITS(x) (SCD_BASE + 0x10c + (x) * 4)
+
+static inline unsigned int SCD_QUEUE_WRPTR(unsigned int chnl)
+{
+ if (chnl < 20)
+ return SCD_BASE + 0x18 + chnl * 4;
+ WARN_ON_ONCE(chnl >= 32);
+ return SCD_BASE + 0x284 + (chnl - 20) * 4;
+}
+
+static inline unsigned int SCD_QUEUE_RDPTR(unsigned int chnl)
+{
+ if (chnl < 20)
+ return SCD_BASE + 0x68 + chnl * 4;
+ WARN_ON_ONCE(chnl >= 32);
+ return SCD_BASE + 0x2B4 + (chnl - 20) * 4;
+}
+
+static inline unsigned int SCD_QUEUE_STATUS_BITS(unsigned int chnl)
+{
+ if (chnl < 20)
+ return SCD_BASE + 0x10c + chnl * 4;
+ WARN_ON_ONCE(chnl >= 32);
+ return SCD_BASE + 0x384 + (chnl - 20) * 4;
+}
/*********************** END TX SCHEDULER *************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index b4f796c..4d7b30d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1898,17 +1898,11 @@
size_t count, loff_t *ppos);
-static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define DEBUGFS_READ_FILE_OPS(name) \
DEBUGFS_READ_FUNC(name); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.read = iwl_dbgfs_##name##_read, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -1916,7 +1910,7 @@
DEBUGFS_WRITE_FUNC(name); \
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -1926,7 +1920,7 @@
static const struct file_operations iwl_dbgfs_##name##_ops = { \
.write = iwl_dbgfs_##name##_write, \
.read = iwl_dbgfs_##name##_read, \
- .open = iwl_dbgfs_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 87eef57..b6199d1 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -99,12 +99,6 @@
iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
"%llu\n");
-static int iwm_generic_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
@@ -401,28 +395,28 @@
static const struct file_operations iwm_debugfs_txq_fops = {
.owner = THIS_MODULE,
- .open = iwm_generic_open,
+ .open = simple_open,
.read = iwm_debugfs_txq_read,
.llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_tx_credit_fops = {
.owner = THIS_MODULE,
- .open = iwm_generic_open,
+ .open = simple_open,
.read = iwm_debugfs_tx_credit_read,
.llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_rx_ticket_fops = {
.owner = THIS_MODULE,
- .open = iwm_generic_open,
+ .open = simple_open,
.read = iwm_debugfs_rx_ticket_read,
.llseek = default_llseek,
};
static const struct file_operations iwm_debugfs_fw_err_fops = {
.owner = THIS_MODULE,
- .open = iwm_generic_open,
+ .open = simple_open,
.read = iwm_debugfs_fw_err_read,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
index 764b40d..0042f20 100644
--- a/drivers/net/wireless/iwmc3200wifi/sdio.c
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -264,13 +264,6 @@
return ret;
}
-/* debugfs hooks */
-static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -363,7 +356,7 @@
static const struct file_operations iwm_debugfs_sdio_fops = {
.owner = THIS_MODULE,
- .open = iwm_debugfs_sdio_open,
+ .open = simple_open,
.read = iwm_debugfs_sdio_read,
.llseek = default_llseek,
};
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 3fa1ece..2fa879b 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -103,7 +103,7 @@
* Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
* in the firmware spec
*/
-static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
+static int lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
{
int ret = -ENOTSUPP;
@@ -1411,7 +1411,12 @@
goto done;
}
- lbs_set_authtype(priv, sme);
+ ret = lbs_set_authtype(priv, sme);
+ if (ret == -ENOTSUPP) {
+ wiphy_err(wiphy, "unsupported authtype 0x%x\n", sme->auth_type);
+ goto done;
+ }
+
lbs_set_radio(priv, preamble, 1);
/* Do the actual association */
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index c192671..a06cc28 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -21,12 +21,6 @@
static void lbs_debug_init(struct lbs_private *priv);
#endif
-static int open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t write_file_dummy(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -696,7 +690,7 @@
#define FOPS(fread, fwrite) { \
.owner = THIS_MODULE, \
- .open = open_file_generic, \
+ .open = simple_open, \
.read = (fread), \
.write = (fwrite), \
.llseek = generic_file_llseek, \
@@ -962,7 +956,7 @@
static const struct file_operations lbs_debug_fops = {
.owner = THIS_MODULE,
- .open = open_file_generic,
+ .open = simple_open,
.write = lbs_debugfs_write,
.read = lbs_debugfs_read,
.llseek = default_llseek,
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c
index d26a78b..1a84507 100644
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -140,18 +140,6 @@
static int num_of_items = ARRAY_SIZE(items);
/*
- * Generic proc file open handler.
- *
- * This function is called every time a file is accessed for read or write.
- */
-static int
-mwifiex_open_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-/*
* Proc info file read handler.
*
* This function is called when the 'info' file is opened for reading.
@@ -676,19 +664,19 @@
static const struct file_operations mwifiex_dfs_##name##_fops = { \
.read = mwifiex_##name##_read, \
.write = mwifiex_##name##_write, \
- .open = mwifiex_open_generic, \
+ .open = simple_open, \
};
#define MWIFIEX_DFS_FILE_READ_OPS(name) \
static const struct file_operations mwifiex_dfs_##name##_fops = { \
.read = mwifiex_##name##_read, \
- .open = mwifiex_open_generic, \
+ .open = simple_open, \
};
#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \
static const struct file_operations mwifiex_dfs_##name##_fops = { \
.write = mwifiex_##name##_write, \
- .open = mwifiex_open_generic, \
+ .open = simple_open, \
};
diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h
index 445ff21..2f218f9 100644
--- a/drivers/net/wireless/mwifiex/pcie.h
+++ b/drivers/net/wireless/mwifiex/pcie.h
@@ -48,15 +48,15 @@
#define PCIE_HOST_INT_STATUS_MASK 0xC3C
#define PCIE_SCRATCH_2_REG 0xC40
#define PCIE_SCRATCH_3_REG 0xC44
-#define PCIE_SCRATCH_4_REG 0xCC0
-#define PCIE_SCRATCH_5_REG 0xCC4
-#define PCIE_SCRATCH_6_REG 0xCC8
-#define PCIE_SCRATCH_7_REG 0xCCC
-#define PCIE_SCRATCH_8_REG 0xCD0
-#define PCIE_SCRATCH_9_REG 0xCD4
-#define PCIE_SCRATCH_10_REG 0xCD8
-#define PCIE_SCRATCH_11_REG 0xCDC
-#define PCIE_SCRATCH_12_REG 0xCE0
+#define PCIE_SCRATCH_4_REG 0xCD0
+#define PCIE_SCRATCH_5_REG 0xCD4
+#define PCIE_SCRATCH_6_REG 0xCD8
+#define PCIE_SCRATCH_7_REG 0xCDC
+#define PCIE_SCRATCH_8_REG 0xCE0
+#define PCIE_SCRATCH_9_REG 0xCE4
+#define PCIE_SCRATCH_10_REG 0xCE8
+#define PCIE_SCRATCH_11_REG 0xCEC
+#define PCIE_SCRATCH_12_REG 0xCF0
#define CPU_INTR_DNLD_RDY BIT(0)
#define CPU_INTR_DOOR_BELL BIT(1)
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index dd6c64a..88e3ad2 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -1336,6 +1336,10 @@
unsigned long flags;
sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+ if (!sd) {
+ printk(KERN_ERR "%s: failed to alloc memory\n", __func__);
+ return;
+ }
sd->buf = buf;
sd->len = len;
sd->type = type;
@@ -1353,6 +1357,10 @@
unsigned long flags;
sd = kmalloc(sizeof(*sd), GFP_ATOMIC);
+ if (!sd) {
+ printk(KERN_ERR "%s: failed to alloc memory\n", __func__);
+ return;
+ }
sd->len = -1; /* Abort */
spin_lock_irqsave(&priv->scan_lock, flags);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index cd490ab..001735f 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -163,7 +163,13 @@
/* Reschedule urb to read TX status again instantly */
return true;
- } else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+ }
+
+ /* Check if there is any entry that timedout waiting on TX status */
+ if (rt2800usb_txstatus_timeout(rt2x00dev))
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+
+ if (rt2800usb_txstatus_pending(rt2x00dev)) {
/* Read register after 250 us */
hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000),
HRTIMER_MODE_REL);
@@ -178,7 +184,7 @@
* here again if status reading is needed.
*/
if (rt2800usb_txstatus_pending(rt2x00dev) &&
- test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
+ !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags))
return true;
else
return false;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index fc9901e..90cc5e7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1062,11 +1062,6 @@
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
- /*
- * Register the extra components.
- */
- rt2x00rfkill_register(rt2x00dev);
-
return 0;
}
@@ -1210,6 +1205,7 @@
rt2x00link_register(rt2x00dev);
rt2x00leds_register(rt2x00dev);
rt2x00debug_register(rt2x00dev);
+ rt2x00rfkill_register(rt2x00dev);
return 0;
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 5100235..e54488d 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -838,7 +838,10 @@
__le16 fc = hdr->frame_control;
txrate = ieee80211_get_tx_rate(hw, info);
- tcb_desc->hw_rate = txrate->hw_value;
+ if (txrate)
+ tcb_desc->hw_rate = txrate->hw_value;
+ else
+ tcb_desc->hw_rate = 0;
if (ieee80211_is_data(fc)) {
/*
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 07dd38e..cc15fdb 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -912,8 +912,13 @@
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
ring = &rtlpci->tx_ring[BEACON_QUEUE];
pskb = __skb_dequeue(&ring->queue);
- if (pskb)
+ if (pskb) {
+ struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+ pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc(
+ (u8 *) entry, true, HW_DESC_TXBUFF_ADDR),
+ pskb->len, PCI_DMA_TODEVICE);
kfree_skb(pskb);
+ }
/*NB: the beacon data buffer must be 32-bit aligned. */
pskb = ieee80211_beacon_get(hw, mac->vif);
@@ -1936,6 +1941,7 @@
rtl_deinit_deferred_work(hw);
rtlpriv->intf_ops->adapter_stop(hw);
}
+ rtlpriv->cfg->ops->disable_interrupt(hw);
/*deinit rfkill */
rtl_deinit_rfkill(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index 1eec3a0..4c01624 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -1893,7 +1893,7 @@
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
- dm_digtable.cur_igvalue = 0x17;
+ dm_digtable.cur_igvalue = 0x37;
rtl92c_dm_write_dig(hw);
break;
default:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
index 34591eeb..28fc5fb 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c
@@ -3077,7 +3077,7 @@
break;
case IO_CMD_PAUSE_DM_BY_SCAN:
rtlphy->initgain_backup.xaagccore1 = de_digtable.cur_igvalue;
- de_digtable.cur_igvalue = 0x17;
+ de_digtable.cur_igvalue = 0x37;
rtl92d_dm_write_dig(hw);
break;
default:
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index 4898c50..480862c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -91,7 +91,6 @@
u8 tid;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- static int header_print;
rtlpriv->dm.dm_initialgain_enable = true;
rtlpriv->dm.dm_flag = 0;
@@ -171,10 +170,6 @@
for (tid = 0; tid < 8; tid++)
skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]);
- /* Only load firmware for first MAC */
- if (header_print)
- return 0;
-
/* for firmware buf */
rtlpriv->rtlhal.pfirmware = vzalloc(0x8000);
if (!rtlpriv->rtlhal.pfirmware) {
@@ -186,7 +181,6 @@
rtlpriv->max_fw_size = 0x8000;
pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
- header_print++;
/* request fw */
err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 2e1e352..d04dbda 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -124,46 +124,38 @@
return status;
}
-static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len)
{
+ struct device *dev = rtlpriv->io.dev;
+ struct usb_device *udev = to_usb_device(dev);
u8 request;
u16 wvalue;
u16 index;
- u32 *data;
- u32 ret;
+ __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index];
- data = kmalloc(sizeof(u32), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
request = REALTEK_USB_VENQT_CMD_REQ;
index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
wvalue = (u16)addr;
_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
- ret = le32_to_cpu(*data);
- kfree(data);
- return ret;
+ if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT)
+ rtlpriv->usb_data_index = 0;
+ return le32_to_cpu(*data);
}
static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+ return (u8)_usb_read_sync(rtlpriv, addr, 1);
}
static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+ return (u16)_usb_read_sync(rtlpriv, addr, 2);
}
static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
{
- struct device *dev = rtlpriv->io.dev;
-
- return _usb_read_sync(to_usb_device(dev), addr, 4);
+ return _usb_read_sync(rtlpriv, addr, 4);
}
static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
@@ -955,6 +947,11 @@
return -ENOMEM;
}
rtlpriv = hw->priv;
+ rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+ GFP_KERNEL);
+ if (!rtlpriv->usb_data)
+ return -ENOMEM;
+ rtlpriv->usb_data_index = 0;
init_completion(&rtlpriv->firmware_loading_complete);
SET_IEEE80211_DEV(hw, &intf->dev);
udev = interface_to_usbdev(intf);
@@ -1025,6 +1022,7 @@
/* rtl_deinit_rfkill(hw); */
rtl_usb_deinit(hw);
rtl_deinit_core(hw);
+ kfree(rtlpriv->usb_data);
rtlpriv->cfg->ops->deinit_sw_leds(hw);
rtlpriv->cfg->ops->deinit_sw_vars(hw);
_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index b591614..28ebc69 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -67,7 +67,7 @@
#define QOS_QUEUE_NUM 4
#define RTL_MAC80211_NUM_QUEUE 5
#define REALTEK_USB_VENQT_MAX_BUF_SIZE 254
-
+#define RTL_USB_MAX_RX_COUNT 100
#define QBSS_LOAD_SIZE 5
#define MAX_WMMELE_LENGTH 64
@@ -1629,6 +1629,10 @@
interface or hardware */
unsigned long status;
+ /* data buffer pointer for USB reads */
+ __le32 *usb_data;
+ int usb_data_index;
+
/*This must be the last item so
that it points to the data allocated
beyond this structure like:
diff --git a/drivers/net/wireless/wl1251/debugfs.c b/drivers/net/wireless/wl1251/debugfs.c
index 6c27400..448da1f 100644
--- a/drivers/net/wireless/wl1251/debugfs.c
+++ b/drivers/net/wireless/wl1251/debugfs.c
@@ -47,7 +47,7 @@
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
- .open = wl1251_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -84,7 +84,7 @@
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
- .open = wl1251_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -117,12 +117,6 @@
mutex_unlock(&wl->mutex);
}
-static int wl1251_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
@@ -235,7 +229,7 @@
static const struct file_operations tx_queue_len_ops = {
.read = tx_queue_len_read,
- .open = wl1251_open_file_generic,
+ .open = simple_open,
.llseek = generic_file_llseek,
};
@@ -257,7 +251,7 @@
static const struct file_operations tx_queue_status_ops = {
.read = tx_queue_status_read,
- .open = wl1251_open_file_generic,
+ .open = simple_open,
.llseek = generic_file_llseek,
};
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 41302c7..d1afb8e 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -479,6 +479,7 @@
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->filter_work);
+ cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index f786942..1b851f6 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -315,8 +315,8 @@
if (wl->irq)
free_irq(wl->irq, wl);
- kfree(wl_sdio);
wl1251_free_hw(wl);
+ kfree(wl_sdio);
sdio_claim_host(func);
sdio_release_irq(func);
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index e1cf727..564d495 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -63,7 +63,7 @@
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
- .open = wl1271_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -96,7 +96,7 @@
\
static const struct file_operations sub## _ ##name## _ops = { \
.read = sub## _ ##name## _read, \
- .open = wl1271_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -126,12 +126,6 @@
mutex_unlock(&wl->mutex);
}
-static int wl1271_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, "%u");
DEBUGFS_FWSTATS_FILE(rx, out_of_mem, "%u");
@@ -243,7 +237,7 @@
static const struct file_operations tx_queue_len_ops = {
.read = tx_queue_len_read,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -289,7 +283,7 @@
static const struct file_operations gpio_power_ops = {
.read = gpio_power_read,
.write = gpio_power_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -308,7 +302,7 @@
static const struct file_operations start_recovery_ops = {
.write = start_recovery_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -372,7 +366,7 @@
static const struct file_operations dynamic_ps_timeout_ops = {
.read = dynamic_ps_timeout_read,
.write = dynamic_ps_timeout_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -441,7 +435,7 @@
static const struct file_operations forced_ps_ops = {
.read = forced_ps_read,
.write = forced_ps_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -483,7 +477,7 @@
static const struct file_operations split_scan_timeout_ops = {
.read = split_scan_timeout_read,
.write = split_scan_timeout_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -566,7 +560,7 @@
static const struct file_operations driver_state_ops = {
.read = driver_state_read,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -675,7 +669,7 @@
static const struct file_operations vifs_state_ops = {
.read = vifs_state_read,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -733,7 +727,7 @@
static const struct file_operations dtim_interval_ops = {
.read = dtim_interval_read,
.write = dtim_interval_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -791,7 +785,7 @@
static const struct file_operations suspend_dtim_interval_ops = {
.read = suspend_dtim_interval_read,
.write = suspend_dtim_interval_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -849,7 +843,7 @@
static const struct file_operations beacon_interval_ops = {
.read = beacon_interval_read,
.write = beacon_interval_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -904,7 +898,7 @@
static const struct file_operations rx_streaming_interval_ops = {
.read = rx_streaming_interval_read,
.write = rx_streaming_interval_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -959,7 +953,7 @@
static const struct file_operations rx_streaming_always_ops = {
.read = rx_streaming_always_read,
.write = rx_streaming_always_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -1003,7 +997,7 @@
static const struct file_operations beacon_filtering_ops = {
.write = beacon_filtering_write,
- .open = wl1271_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 663b32c..0ebbb19 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1965,7 +1965,7 @@
if (xen_initial_domain())
return 0;
- if (!xen_platform_pci_unplug)
+ if (xen_hvm_domain() && !xen_platform_pci_unplug)
return -ENODEV;
printk(KERN_INFO "Initialising Xen virtual ethernet driver.\n");
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index bba8121..bf984b6 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -140,7 +140,7 @@
if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells))
return -EINVAL;
- if (gpiospec->args[0] > gc->ngpio)
+ if (gpiospec->args[0] >= gc->ngpio)
return -EINVAL;
if (flags)
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index ee8fd03..849357c 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -117,25 +117,17 @@
}
-static int default_open(struct inode *inode, struct file *filp)
-{
- if (inode->i_private)
- filp->private_data = inode->i_private;
- return 0;
-}
-
-
static const struct file_operations ulong_fops = {
.read = ulong_read_file,
.write = ulong_write_file,
- .open = default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
static const struct file_operations ulong_ro_fops = {
.read = ulong_read_file,
- .open = default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -187,7 +179,7 @@
static const struct file_operations atomic_ro_fops = {
.read = atomic_read_file,
- .open = default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 083a49f..165274c 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -42,6 +42,7 @@
obj-$(CONFIG_PARISC) += setup-bus.o
obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
obj-$(CONFIG_PPC) += setup-bus.o
+obj-$(CONFIG_FRV) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_MN10300) += setup-bus.o
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 0f150f2..1929c0c 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -200,7 +200,7 @@
return PCI_D1;
case ACPI_STATE_D2:
return PCI_D2;
- case ACPI_STATE_D3:
+ case ACPI_STATE_D3_HOT:
return PCI_D3hot;
case ACPI_STATE_D3_COLD:
return PCI_D3cold;
@@ -223,7 +223,7 @@
[PCI_D0] = ACPI_STATE_D0,
[PCI_D1] = ACPI_STATE_D1,
[PCI_D2] = ACPI_STATE_D2,
- [PCI_D3hot] = ACPI_STATE_D3,
+ [PCI_D3hot] = ACPI_STATE_D3_HOT,
[PCI_D3cold] = ACPI_STATE_D3
};
int error = -EINVAL;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8156744..111569c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -967,16 +967,59 @@
return 0;
}
+static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
+ u32 saved_val, int retry)
+{
+ u32 val;
+
+ pci_read_config_dword(pdev, offset, &val);
+ if (val == saved_val)
+ return;
+
+ for (;;) {
+ dev_dbg(&pdev->dev, "restoring config space at offset "
+ "%#x (was %#x, writing %#x)\n", offset, val, saved_val);
+ pci_write_config_dword(pdev, offset, saved_val);
+ if (retry-- <= 0)
+ return;
+
+ pci_read_config_dword(pdev, offset, &val);
+ if (val == saved_val)
+ return;
+
+ mdelay(1);
+ }
+}
+
+static void pci_restore_config_space_range(struct pci_dev *pdev,
+ int start, int end, int retry)
+{
+ int index;
+
+ for (index = end; index >= start; index--)
+ pci_restore_config_dword(pdev, 4 * index,
+ pdev->saved_config_space[index],
+ retry);
+}
+
+static void pci_restore_config_space(struct pci_dev *pdev)
+{
+ if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
+ pci_restore_config_space_range(pdev, 10, 15, 0);
+ /* Restore BARs before the command register. */
+ pci_restore_config_space_range(pdev, 4, 9, 10);
+ pci_restore_config_space_range(pdev, 0, 3, 0);
+ } else {
+ pci_restore_config_space_range(pdev, 0, 15, 0);
+ }
+}
+
/**
* pci_restore_state - Restore the saved state of a PCI device
* @dev: - PCI device that we're dealing with
*/
void pci_restore_state(struct pci_dev *dev)
{
- int i;
- u32 val;
- int tries;
-
if (!dev->state_saved)
return;
@@ -984,24 +1027,8 @@
pci_restore_pcie_state(dev);
pci_restore_ats_state(dev);
- /*
- * The Base Address register should be programmed before the command
- * register(s)
- */
- for (i = 15; i >= 0; i--) {
- pci_read_config_dword(dev, i * 4, &val);
- tries = 10;
- while (tries && val != dev->saved_config_space[i]) {
- dev_dbg(&dev->dev, "restoring config "
- "space at offset %#x (was %#x, writing %#x)\n",
- i, val, (int)dev->saved_config_space[i]);
- pci_write_config_dword(dev,i * 4,
- dev->saved_config_space[i]);
- pci_read_config_dword(dev, i * 4, &val);
- mdelay(10);
- tries--;
- }
- }
+ pci_restore_config_space(dev);
+
pci_restore_pcix_state(dev);
pci_restore_msi_state(dev);
pci_restore_iov_state(dev);
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c
index fd00ff0..d6cc62c 100644
--- a/drivers/pci/xen-pcifront.c
+++ b/drivers/pci/xen-pcifront.c
@@ -290,6 +290,7 @@
} else {
printk(KERN_DEBUG "enable msix get value %x\n",
op.value);
+ err = op.value;
}
} else {
dev_err(&dev->dev, "enable msix get err %x\n", err);
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index ec3b8cc..df6296c 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -908,10 +908,6 @@
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
unsigned selector = 0;
- /* No grouping */
- if (!ops)
- return 0;
-
mutex_lock(&pinctrl_mutex);
seq_puts(s, "registered pin groups:\n");
@@ -1225,6 +1221,19 @@
#endif
+static int pinctrl_check_ops(struct pinctrl_dev *pctldev)
+{
+ const struct pinctrl_ops *ops = pctldev->desc->pctlops;
+
+ if (!ops ||
+ !ops->list_groups ||
+ !ops->get_group_name ||
+ !ops->get_group_pins)
+ return -EINVAL;
+
+ return 0;
+}
+
/**
* pinctrl_register() - register a pin controller device
* @pctldesc: descriptor for this pin controller
@@ -1256,6 +1265,14 @@
INIT_LIST_HEAD(&pctldev->gpio_ranges);
pctldev->dev = dev;
+ /* check core ops for sanity */
+ ret = pinctrl_check_ops(pctldev);
+ if (ret) {
+ pr_err("%s pinctrl ops lacks necessary functions\n",
+ pctldesc->name);
+ goto out_err;
+ }
+
/* If we're implementing pinmuxing, check the ops for sanity */
if (pctldesc->pmxops) {
ret = pinmux_check_ops(pctldev);
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index bc8384c..639db4d 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -50,7 +50,7 @@
*/
#undef START_IN_KERNEL_MODE
-#define DRV_VER "0.5.24"
+#define DRV_VER "0.5.26"
/*
* According to the Atom N270 datasheet,
@@ -83,8 +83,8 @@
#endif
static unsigned int interval = 10;
-static unsigned int fanon = 63000;
-static unsigned int fanoff = 58000;
+static unsigned int fanon = 60000;
+static unsigned int fanoff = 53000;
static unsigned int verbose;
static unsigned int fanstate = ACERHDF_FAN_AUTO;
static char force_bios[16];
@@ -150,6 +150,8 @@
{"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} },
{"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} },
{"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
+ /* LT1005u */
+ {"Acer", "LT-10Q", "v0.3310", 0x55, 0x58, {0x20, 0x00} },
/* Acer 1410 */
{"Acer", "Aspire 1410", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1410", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
@@ -161,6 +163,7 @@
{"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1410", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1410", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
+ {"Acer", "Aspire 1410", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
/* Acer 1810xx */
{"Acer", "Aspire 1810TZ", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1810T", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
@@ -183,29 +186,44 @@
{"Acer", "Aspire 1810TZ", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1810T", "v1.3310", 0x55, 0x58, {0x9e, 0x00} },
{"Acer", "Aspire 1810TZ", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
+ {"Acer", "Aspire 1810T", "v1.3314", 0x55, 0x58, {0x9e, 0x00} },
/* Acer 531 */
+ {"Acer", "AO531h", "v0.3104", 0x55, 0x58, {0x20, 0x00} },
{"Acer", "AO531h", "v0.3201", 0x55, 0x58, {0x20, 0x00} },
+ {"Acer", "AO531h", "v0.3304", 0x55, 0x58, {0x20, 0x00} },
+ /* Acer 751 */
+ {"Acer", "AO751h", "V0.3212", 0x55, 0x58, {0x21, 0x00} },
+ /* Acer 1825 */
+ {"Acer", "Aspire 1825PTZ", "V1.3118", 0x55, 0x58, {0x9e, 0x00} },
+ {"Acer", "Aspire 1825PTZ", "V1.3127", 0x55, 0x58, {0x9e, 0x00} },
+ /* Acer TravelMate 7730 */
+ {"Acer", "TravelMate 7730G", "v0.3509", 0x55, 0x58, {0xaf, 0x00} },
/* Gateway */
- {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
- {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
- {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} },
- {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
- {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} },
+ {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} },
+ {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x9e, 0x00} },
+ {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
+ {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+ {"Gateway", "LT31", "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
/* Packard Bell */
- {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
- {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
- {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
- {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
- {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
- {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} },
+ {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
+ {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} },
+ {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} },
+ {"Packard Bell", "ENBFT", "V1.3118", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "ENBFT", "V1.3127", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3108", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3113", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3115", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3117", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v0.3119", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMU", "v1.3204", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMA", "v1.3201", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMA", "v1.3302", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTMA", "v1.3303t", 0x55, 0x58, {0x9e, 0x00} },
+ {"Packard Bell", "DOTVR46", "v1.3308", 0x55, 0x58, {0x9e, 0x00} },
/* pewpew-terminator */
{"", "", "", 0, 0, {0, 0} }
};
@@ -701,15 +719,20 @@
MODULE_AUTHOR("Peter Feuerer");
MODULE_DESCRIPTION("Aspire One temperature and fan driver");
MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAO751h*:");
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1410*:");
MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1810*:");
+MODULE_ALIAS("dmi:*:*Acer*:pnAspire*1825PTZ:");
MODULE_ALIAS("dmi:*:*Acer*:pnAO531*:");
+MODULE_ALIAS("dmi:*:*Acer*:TravelMate*7730G:");
MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:");
MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnAOA*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOA*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMU*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnENBFT*:");
MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTMA*:");
+MODULE_ALIAS("dmi:*:*Packard*Bell*:pnDOTVR46*:");
module_init(acerhdf_init);
module_exit(acerhdf_exit);
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index a05fc9c..e6c08ee 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -212,6 +212,7 @@
},
.driver_data = &quirk_dell_vostro_v130,
},
+ { }
};
static struct calling_interface_buffer *buffer;
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index f7ba316e..0ffdb3c 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -1565,7 +1565,7 @@
ips->poll_turbo_status = true;
if (!ips_get_i915_syms(ips)) {
- dev_err(&dev->dev, "failed to get i915 symbols, graphics turbo disabled\n");
+ dev_info(&dev->dev, "failed to get i915 symbols, graphics turbo disabled until i915 loads\n");
ips->gpu_turbo_enabled = false;
} else {
dev_dbg(&dev->dev, "graphics turbo enabled\n");
diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c
index 0a3594c..bcbad84 100644
--- a/drivers/platform/x86/intel_mid_powerbtn.c
+++ b/drivers/platform/x86/intel_mid_powerbtn.c
@@ -78,7 +78,7 @@
input_set_capability(input, EV_KEY, KEY_POWER);
- error = request_threaded_irq(irq, NULL, mfld_pb_isr, 0,
+ error = request_threaded_irq(irq, NULL, mfld_pb_isr, IRQF_NO_SUSPEND,
DRIVER_NAME, input);
if (error) {
dev_err(&pdev->dev, "Unable to request irq %d for mfld power"
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 17499a5..81fd606 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -138,9 +138,10 @@
rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE;
sreg->mfd = anatopmfd;
- ret = of_property_read_u32(np, "reg", &sreg->control_reg);
+ ret = of_property_read_u32(np, "anatop-reg-offset",
+ &sreg->control_reg);
if (ret) {
- dev_err(dev, "no reg property set\n");
+ dev_err(dev, "no anatop-reg-offset property set\n");
goto anatop_probe_end;
}
ret = of_property_read_u32(np, "anatop-vol-bit-width",
@@ -213,7 +214,7 @@
{ /* end */ }
};
-static struct platform_driver anatop_regulator = {
+static struct platform_driver anatop_regulator_driver = {
.driver = {
.name = "anatop_regulator",
.owner = THIS_MODULE,
@@ -225,13 +226,13 @@
static int __init anatop_regulator_init(void)
{
- return platform_driver_register(&anatop_regulator);
+ return platform_driver_register(&anatop_regulator_driver);
}
postcore_initcall(anatop_regulator_init);
static void __exit anatop_regulator_exit(void)
{
- platform_driver_unregister(&anatop_regulator);
+ platform_driver_unregister(&anatop_regulator_driver);
}
module_exit(anatop_regulator_exit);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index c056abd..046fb1b 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1431,7 +1431,10 @@
rc = devres_destroy(regulator->dev, devm_regulator_release,
devm_regulator_match, regulator);
- WARN_ON(rc);
+ if (rc == 0)
+ regulator_put(regulator);
+ else
+ WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
@@ -2992,14 +2995,14 @@
if (rdev == NULL)
return;
+ if (rdev->supply)
+ regulator_put(rdev->supply);
mutex_lock(®ulator_list_mutex);
debugfs_remove_recursive(rdev->debugfs);
flush_work_sync(&rdev->disable_work.work);
WARN_ON(rdev->open_count);
unset_regulator_supplies(rdev);
list_del(&rdev->list);
- if (rdev->supply)
- regulator_put(rdev->supply);
kfree(rdev->constraints);
device_unregister(&rdev->dev);
mutex_unlock(®ulator_list_mutex);
diff --git a/drivers/regulator/fixed-helper.c b/drivers/regulator/fixed-helper.c
index 30d0a15..cacd33c 100644
--- a/drivers/regulator/fixed-helper.c
+++ b/drivers/regulator/fixed-helper.c
@@ -18,7 +18,6 @@
/**
* regulator_register_fixed - register a no-op fixed regulator
- * @name: supply name
* @id: platform device id
* @supplies: consumers for this regulator
* @num_supplies: number of consumers
@@ -32,7 +31,7 @@
if (!data)
return NULL;
- data->cfg.supply_name = "dummy";
+ data->cfg.supply_name = "fixed-dummy";
data->cfg.microvolts = 0;
data->cfg.gpio = -EINVAL;
data->cfg.enabled_at_boot = 1;
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index 9657929..17a58c5 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -684,7 +684,7 @@
}
new_val++;
- } while (desc->min + desc->step + new_val <= desc->max);
+ } while (desc->min + desc->step * new_val <= desc->max);
new_idx = tmp_idx;
new_val = tmp_val;
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c
index e8cfc99..845aa22 100644
--- a/drivers/regulator/mc13892-regulator.c
+++ b/drivers/regulator/mc13892-regulator.c
@@ -552,7 +552,7 @@
mc13xxx_lock(mc13892);
ret = mc13xxx_reg_read(mc13892, MC13892_REVISION, &val);
if (ret)
- goto err_free;
+ goto err_unlock;
/* enable switch auto mode */
if ((val & 0x0000FFFF) == 0x45d0) {
@@ -562,7 +562,7 @@
MC13892_SWITCHERS4_SW1MODE_AUTO |
MC13892_SWITCHERS4_SW2MODE_AUTO);
if (ret)
- goto err_free;
+ goto err_unlock;
ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS5,
MC13892_SWITCHERS5_SW3MODE_M |
@@ -570,7 +570,7 @@
MC13892_SWITCHERS5_SW3MODE_AUTO |
MC13892_SWITCHERS5_SW4MODE_AUTO);
if (ret)
- goto err_free;
+ goto err_unlock;
}
mc13xxx_unlock(mc13892);
@@ -612,10 +612,10 @@
err:
while (--i >= 0)
regulator_unregister(priv->regulators[i]);
+ return ret;
-err_free:
+err_unlock:
mc13xxx_unlock(mc13892);
-
return ret;
}
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 58447db..4ca2db0 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -311,8 +311,7 @@
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
const struct s5m_voltage_desc *desc;
int reg_id = rdev_get_id(rdev);
- int reg, mask, ret;
- int i;
+ int sel, reg, mask, ret;
u8 val;
switch (reg_id) {
@@ -333,19 +332,20 @@
desc = reg_voltage_map[reg_id];
- i = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
- if (i < 0)
- return i;
+ sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
+ if (sel < 0)
+ return sel;
ret = s5m8767_get_voltage_register(rdev, ®);
if (ret)
return ret;
s5m_reg_read(s5m8767->iodev, reg, &val);
- val = val & mask;
+ val &= ~mask;
+ val |= sel;
ret = s5m_reg_write(s5m8767->iodev, reg, val);
- *selector = i;
+ *selector = sel;
return ret;
}
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c
index 29b615c..cfc1f16 100644
--- a/drivers/regulator/tps6586x-regulator.c
+++ b/drivers/regulator/tps6586x-regulator.c
@@ -79,6 +79,11 @@
unsigned selector)
{
struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
+ int rid = rdev_get_id(rdev);
+
+ /* LDO0 has minimal voltage 1.2V rather than 1.25V */
+ if ((rid == TPS6586X_ID_LDO_0) && (selector == 0))
+ return (info->voltages[0] - 50) * 1000;
return info->voltages[selector] * 1000;
}
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 4904a40..ff810e7 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -380,13 +380,15 @@
int i;
for (i = 0; i < ARRAY_SIZE(wm831x_dcdc_ilim); i++) {
- if (max_uA <= wm831x_dcdc_ilim[i])
+ if ((min_uA <= wm831x_dcdc_ilim[i]) &&
+ (wm831x_dcdc_ilim[i] <= max_uA))
break;
}
if (i == ARRAY_SIZE(wm831x_dcdc_ilim))
return -EINVAL;
- return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK, i);
+ return wm831x_set_bits(wm831x, reg, WM831X_DC1_HC_THR_MASK,
+ i << WM831X_DC1_HC_THR_SHIFT);
}
static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
@@ -400,7 +402,8 @@
if (val < 0)
return val;
- return wm831x_dcdc_ilim[val & WM831X_DC1_HC_THR_MASK];
+ val = (val & WM831X_DC1_HC_THR_MASK) >> WM831X_DC1_HC_THR_SHIFT;
+ return wm831x_dcdc_ilim[val];
}
static struct regulator_ops wm831x_buckv_ops = {
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 634aac3..b414e09 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -101,7 +101,7 @@
for (i = 0; i < ARRAY_SIZE(wm831x_isinkv_values); i++) {
int val = wm831x_isinkv_values[i];
- if (min_uA >= val && val <= max_uA) {
+ if (min_uA <= val && val <= max_uA) {
ret = wm831x_set_bits(wm831x, isink->reg,
WM831X_CS1_ISEL_MASK, i);
return ret;
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index f1e4ab0..641e9f6 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -506,22 +506,19 @@
{
struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
struct wm831x *wm831x = ldo->wm831x;
- int ctrl_reg = ldo->base + WM831X_LDO_CONTROL;
int on_reg = ldo->base + WM831X_LDO_ON_CONTROL;
int ret;
switch (mode) {
case REGULATOR_MODE_NORMAL:
- ret = wm831x_set_bits(wm831x, on_reg,
- WM831X_LDO7_ON_MODE, 0);
+ ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE, 0);
if (ret < 0)
return ret;
break;
case REGULATOR_MODE_IDLE:
- ret = wm831x_set_bits(wm831x, ctrl_reg,
- WM831X_LDO7_ON_MODE,
+ ret = wm831x_set_bits(wm831x, on_reg, WM831X_LDO7_ON_MODE,
WM831X_LDO7_ON_MODE);
if (ret < 0)
return ret;
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index ab1e183..05ecfb8 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -99,7 +99,7 @@
{
int i;
- for (i = ARRAY_SIZE(isink_cur) - 1; i >= 0; i--) {
+ for (i = 0; i < ARRAY_SIZE(isink_cur); i++) {
if (min_uA <= isink_cur[i] && max_uA >= isink_cur[i]) {
*setting = i;
return 0;
@@ -186,7 +186,7 @@
return 0;
}
- return DIV_ROUND_CLOSEST(isink_cur[val], 100);
+ return isink_cur[val];
}
/* turn on ISINK followed by DCDC */
@@ -495,25 +495,25 @@
val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER)
& ~WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
- wm8350->pmic.dcdc1_hib_mode);
+ val | wm8350->pmic.dcdc1_hib_mode);
break;
case WM8350_DCDC_3:
val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER)
& ~WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
- wm8350->pmic.dcdc3_hib_mode);
+ val | wm8350->pmic.dcdc3_hib_mode);
break;
case WM8350_DCDC_4:
val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER)
& ~WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
- wm8350->pmic.dcdc4_hib_mode);
+ val | wm8350->pmic.dcdc4_hib_mode);
break;
case WM8350_DCDC_6:
val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER)
& ~WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
- wm8350->pmic.dcdc6_hib_mode);
+ val | wm8350->pmic.dcdc6_hib_mode);
break;
case WM8350_DCDC_2:
case WM8350_DCDC_5:
@@ -535,25 +535,25 @@
val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
wm8350->pmic.dcdc1_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC1_LOW_POWER,
- WM8350_DCDC_HIB_MODE_DIS);
+ val | WM8350_DCDC_HIB_MODE_DIS);
break;
case WM8350_DCDC_3:
val = wm8350_reg_read(wm8350, WM8350_DCDC3_LOW_POWER);
wm8350->pmic.dcdc3_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC3_LOW_POWER,
- WM8350_DCDC_HIB_MODE_DIS);
+ val | WM8350_DCDC_HIB_MODE_DIS);
break;
case WM8350_DCDC_4:
val = wm8350_reg_read(wm8350, WM8350_DCDC4_LOW_POWER);
wm8350->pmic.dcdc4_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC4_LOW_POWER,
- WM8350_DCDC_HIB_MODE_DIS);
+ val | WM8350_DCDC_HIB_MODE_DIS);
break;
case WM8350_DCDC_6:
val = wm8350_reg_read(wm8350, WM8350_DCDC6_LOW_POWER);
wm8350->pmic.dcdc6_hib_mode = val & WM8350_DCDC_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC6_LOW_POWER,
- WM8350_DCDC_HIB_MODE_DIS);
+ val | WM8350_DCDC_HIB_MODE_DIS);
break;
case WM8350_DCDC_2:
case WM8350_DCDC_5:
@@ -575,13 +575,13 @@
val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
& ~WM8350_DC2_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
- WM8350_DC2_HIB_MODE_ACTIVE);
+ (WM8350_DC2_HIB_MODE_ACTIVE << WM8350_DC2_HIB_MODE_SHIFT));
break;
case WM8350_DCDC_5:
val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
- & ~WM8350_DC2_HIB_MODE_MASK;
+ & ~WM8350_DC5_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
- WM8350_DC5_HIB_MODE_ACTIVE);
+ (WM8350_DC5_HIB_MODE_ACTIVE << WM8350_DC5_HIB_MODE_SHIFT));
break;
default:
return -EINVAL;
@@ -600,13 +600,13 @@
val = wm8350_reg_read(wm8350, WM8350_DCDC2_CONTROL)
& ~WM8350_DC2_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC2_CONTROL, val |
- WM8350_DC2_HIB_MODE_DISABLE);
+ (WM8350_DC2_HIB_MODE_DISABLE << WM8350_DC2_HIB_MODE_SHIFT));
break;
case WM8350_DCDC_5:
val = wm8350_reg_read(wm8350, WM8350_DCDC5_CONTROL)
- & ~WM8350_DC2_HIB_MODE_MASK;
+ & ~WM8350_DC5_HIB_MODE_MASK;
wm8350_reg_write(wm8350, WM8350_DCDC5_CONTROL, val |
- WM8350_DC2_HIB_MODE_DISABLE);
+ (WM8350_DC5_HIB_MODE_DISABLE << WM8350_DC5_HIB_MODE_SHIFT));
break;
default:
return -EINVAL;
@@ -749,7 +749,7 @@
/* all LDOs have same mV bits */
val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_HIB_MODE_MASK;
- wm8350_reg_write(wm8350, volt_reg, WM8350_LDO1_HIB_MODE_DIS);
+ wm8350_reg_write(wm8350, volt_reg, val | WM8350_LDO1_HIB_MODE_DIS);
return 0;
}
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
index 70277a5..85d31a6 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -50,16 +50,9 @@
return simple_read_from_buffer(userbuf, count, ppos, trace->va, len);
}
-static int rproc_open_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static const struct file_operations trace_rproc_ops = {
.read = rproc_trace_read,
- .open = rproc_open_generic,
+ .open = simple_open,
.llseek = generic_file_llseek,
};
@@ -94,7 +87,7 @@
static const struct file_operations rproc_state_ops = {
.read = rproc_state_read,
- .open = rproc_open_generic,
+ .open = simple_open,
.llseek = generic_file_llseek,
};
@@ -114,7 +107,7 @@
static const struct file_operations rproc_name_ops = {
.read = rproc_name_read,
- .open = rproc_open_generic,
+ .open = simple_open,
.llseek = generic_file_llseek,
};
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index afee0e8..feddefc 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -72,9 +72,9 @@
struct pm860x_rtc_info *info = dev_get_drvdata(dev);
if (enabled)
- pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, ALARM);
+ pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, ALARM_EN);
else
- pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM, 0);
+ pm860x_set_bits(info->i2c, PM8607_RTC1, ALARM_EN, 0);
return 0;
}
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index cd188ab..c293d0c 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -902,6 +902,7 @@
}
ds1307->nvram->attr.name = "nvram";
ds1307->nvram->attr.mode = S_IRUGO | S_IWUSR;
+ sysfs_bin_attr_init(ds1307->nvram);
ds1307->nvram->read = ds1307_nvram_read,
ds1307->nvram->write = ds1307_nvram_write,
ds1307->nvram->size = chip->nvram_size;
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index 5502923..c9f890b 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -213,7 +213,6 @@
.name = "rtc-efi",
.owner = THIS_MODULE,
},
- .probe = efi_rtc_probe,
.remove = __exit_p(efi_rtc_remove),
};
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 42f5f82..029e421 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -360,12 +360,11 @@
&mpc5200_rtc_ops, THIS_MODULE);
}
- rtc->rtc->uie_unsupported = 1;
-
if (IS_ERR(rtc->rtc)) {
err = PTR_ERR(rtc->rtc);
goto out_free_irq;
}
+ rtc->rtc->uie_unsupported = 1;
return 0;
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 692de73..684ef4b 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -339,8 +339,7 @@
dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision);
/* Enable the clockwatch on ST Variants */
- if ((ldata->hw_designer == AMBA_VENDOR_ST) &&
- (ldata->hw_revision > 1))
+ if (ldata->hw_designer == AMBA_VENDOR_ST)
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
ldata->base + RTC_CR);
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c
index 7f8e6c2..33b6ba0 100644
--- a/drivers/rtc/rtc-r9701.c
+++ b/drivers/rtc/rtc-r9701.c
@@ -122,6 +122,7 @@
static int __devinit r9701_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
+ struct rtc_time dt;
unsigned char tmp;
int res;
@@ -132,6 +133,27 @@
return -ENODEV;
}
+ /*
+ * The device seems to be present. Now check if the registers
+ * contain invalid values. If so, try to write a default date:
+ * 2000/1/1 00:00:00
+ */
+ r9701_get_datetime(&spi->dev, &dt);
+ if (rtc_valid_tm(&dt)) {
+ dev_info(&spi->dev, "trying to repair invalid date/time\n");
+ dt.tm_sec = 0;
+ dt.tm_min = 0;
+ dt.tm_hour = 0;
+ dt.tm_mday = 1;
+ dt.tm_mon = 0;
+ dt.tm_year = 100;
+
+ if (r9701_set_datetime(&spi->dev, &dt)) {
+ dev_err(&spi->dev, "cannot repair RTC register\n");
+ return -ENODEV;
+ }
+ }
+
rtc = rtc_device_register("r9701",
&spi->dev, &r9701_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 9ccea13..3f3a297 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -40,6 +40,10 @@
TYPE_S3C64XX,
};
+struct s3c_rtc_drv_data {
+ int cpu_type;
+};
+
/* I have yet to find an S3C implementation with more than one
* of these rtc blocks in */
@@ -446,10 +450,12 @@
static inline int s3c_rtc_get_driver_data(struct platform_device *pdev)
{
#ifdef CONFIG_OF
+ struct s3c_rtc_drv_data *data;
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(s3c_rtc_dt_match, pdev->dev.of_node);
- return match->data;
+ data = (struct s3c_rtc_drv_data *) match->data;
+ return data->cpu_type;
}
#endif
return platform_get_device_id(pdev)->driver_data;
@@ -664,20 +670,27 @@
#define s3c_rtc_resume NULL
#endif
+static struct s3c_rtc_drv_data s3c_rtc_drv_data_array[] = {
+ [TYPE_S3C2410] = { TYPE_S3C2410 },
+ [TYPE_S3C2416] = { TYPE_S3C2416 },
+ [TYPE_S3C2443] = { TYPE_S3C2443 },
+ [TYPE_S3C64XX] = { TYPE_S3C64XX },
+};
+
#ifdef CONFIG_OF
static const struct of_device_id s3c_rtc_dt_match[] = {
{
- .compatible = "samsung,s3c2410-rtc"
- .data = TYPE_S3C2410,
+ .compatible = "samsung,s3c2410-rtc",
+ .data = &s3c_rtc_drv_data_array[TYPE_S3C2410],
}, {
- .compatible = "samsung,s3c2416-rtc"
- .data = TYPE_S3C2416,
+ .compatible = "samsung,s3c2416-rtc",
+ .data = &s3c_rtc_drv_data_array[TYPE_S3C2416],
}, {
- .compatible = "samsung,s3c2443-rtc"
- .data = TYPE_S3C2443,
+ .compatible = "samsung,s3c2443-rtc",
+ .data = &s3c_rtc_drv_data_array[TYPE_S3C2443],
}, {
- .compatible = "samsung,s3c6410-rtc"
- .data = TYPE_S3C64XX,
+ .compatible = "samsung,s3c6410-rtc",
+ .data = &s3c_rtc_drv_data_array[TYPE_S3C64XX],
},
{},
};
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 4c2c6df..258abea 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -112,6 +112,7 @@
#define BIT_RTC_CTRL_REG_TEST_MODE_M 0x10
#define BIT_RTC_CTRL_REG_SET_32_COUNTER_M 0x20
#define BIT_RTC_CTRL_REG_GET_TIME_M 0x40
+#define BIT_RTC_CTRL_REG_RTC_V_OPT 0x80
/* RTC_STATUS_REG bitfields */
#define BIT_RTC_STATUS_REG_RUN_M 0x02
@@ -235,25 +236,57 @@
unsigned char rtc_data[ALL_TIME_REGS + 1];
int ret;
u8 save_control;
+ u8 rtc_control;
ret = twl_rtc_read_u8(&save_control, REG_RTC_CTRL_REG);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(dev, "%s: reading CTRL_REG, error %d\n", __func__, ret);
return ret;
+ }
+ /* for twl6030/32 make sure BIT_RTC_CTRL_REG_GET_TIME_M is clear */
+ if (twl_class_is_6030()) {
+ if (save_control & BIT_RTC_CTRL_REG_GET_TIME_M) {
+ save_control &= ~BIT_RTC_CTRL_REG_GET_TIME_M;
+ ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ if (ret < 0) {
+ dev_err(dev, "%s clr GET_TIME, error %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+ }
- save_control |= BIT_RTC_CTRL_REG_GET_TIME_M;
+ /* Copy RTC counting registers to static registers or latches */
+ rtc_control = save_control | BIT_RTC_CTRL_REG_GET_TIME_M;
- ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
- if (ret < 0)
+ /* for twl6030/32 enable read access to static shadowed registers */
+ if (twl_class_is_6030())
+ rtc_control |= BIT_RTC_CTRL_REG_RTC_V_OPT;
+
+ ret = twl_rtc_write_u8(rtc_control, REG_RTC_CTRL_REG);
+ if (ret < 0) {
+ dev_err(dev, "%s: writing CTRL_REG, error %d\n", __func__, ret);
return ret;
+ }
ret = twl_i2c_read(TWL_MODULE_RTC, rtc_data,
(rtc_reg_map[REG_SECONDS_REG]), ALL_TIME_REGS);
if (ret < 0) {
- dev_err(dev, "rtc_read_time error %d\n", ret);
+ dev_err(dev, "%s: reading data, error %d\n", __func__, ret);
return ret;
}
+ /* for twl6030 restore original state of rtc control register */
+ if (twl_class_is_6030()) {
+ ret = twl_rtc_write_u8(save_control, REG_RTC_CTRL_REG);
+ if (ret < 0) {
+ dev_err(dev, "%s: restore CTRL_REG, error %d\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
tm->tm_sec = bcd2bin(rtc_data[0]);
tm->tm_min = bcd2bin(rtc_data[1]);
tm->tm_hour = bcd2bin(rtc_data[2]);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index c21871a..bc2e8a7 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2844,6 +2844,7 @@
sector_t recid, trkid;
unsigned int offs;
unsigned int count, count_to_trk_end;
+ int ret;
basedev = block->base;
if (rq_data_dir(req) == READ) {
@@ -2884,8 +2885,8 @@
itcw = itcw_init(cqr->data, itcw_size, itcw_op, 0, ctidaw, 0);
if (IS_ERR(itcw)) {
- dasd_sfree_request(cqr, startdev);
- return ERR_PTR(-EINVAL);
+ ret = -EINVAL;
+ goto out_error;
}
cqr->cpaddr = itcw_get_tcw(itcw);
if (prepare_itcw(itcw, first_trk, last_trk,
@@ -2897,8 +2898,8 @@
/* Clock not in sync and XRC is enabled.
* Try again later.
*/
- dasd_sfree_request(cqr, startdev);
- return ERR_PTR(-EAGAIN);
+ ret = -EAGAIN;
+ goto out_error;
}
len_to_track_end = 0;
/*
@@ -2937,8 +2938,10 @@
tidaw_flags = 0;
last_tidaw = itcw_add_tidaw(itcw, tidaw_flags,
dst, part_len);
- if (IS_ERR(last_tidaw))
- return ERR_PTR(-EINVAL);
+ if (IS_ERR(last_tidaw)) {
+ ret = -EINVAL;
+ goto out_error;
+ }
dst += part_len;
}
}
@@ -2947,8 +2950,10 @@
dst = page_address(bv->bv_page) + bv->bv_offset;
last_tidaw = itcw_add_tidaw(itcw, 0x00,
dst, bv->bv_len);
- if (IS_ERR(last_tidaw))
- return ERR_PTR(-EINVAL);
+ if (IS_ERR(last_tidaw)) {
+ ret = -EINVAL;
+ goto out_error;
+ }
}
}
last_tidaw->flags |= TIDAW_FLAGS_LAST;
@@ -2968,6 +2973,9 @@
cqr->buildclk = get_clock();
cqr->status = DASD_CQR_FILLED;
return cqr;
+out_error:
+ dasd_sfree_request(cqr, startdev);
+ return ERR_PTR(ret);
}
static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 85f4a9a..73bef0b 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -903,7 +903,7 @@
goto fail_urdev_put;
}
- cdev_init(urd->char_device, &ur_fops);
+ urd->char_device->ops = &ur_fops;
urd->char_device->dev = MKDEV(major, minor);
urd->char_device->owner = ur_fops.owner;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 120955c..8334dad 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1672,7 +1672,8 @@
{
QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
- if (prcd[74] == 0xF0 && prcd[75] == 0xF0 && prcd[76] == 0xF5) {
+ if (prcd[74] == 0xF0 && prcd[75] == 0xF0 &&
+ (prcd[76] == 0xF5 || prcd[76] == 0xF6)) {
card->info.blkt.time_total = 250;
card->info.blkt.inter_packet = 5;
card->info.blkt.inter_packet_jumbo = 15;
@@ -4540,7 +4541,8 @@
goto out_offline;
}
qeth_configure_unitaddr(card, prcd);
- qeth_configure_blkt_default(card, prcd);
+ if (ddev_offline)
+ qeth_configure_blkt_default(card, prcd);
kfree(prcd);
rc = qdio_get_ssqd_desc(ddev, &card->ssqd);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index e002cd4..467dc38 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -4549,8 +4549,12 @@
ENTER;
if (sdev->sdev_target)
sata_port = sdev->sdev_target->hostdata;
- if (sata_port)
+ if (sata_port) {
rc = ata_sas_port_init(sata_port->ap);
+ if (rc == 0)
+ rc = ata_sas_sync_probe(sata_port->ap);
+ }
+
if (rc)
ipr_slave_destroy(sdev);
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index ef9560d..cc83b66 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -1742,17 +1742,19 @@
mfs = ntohs(flp->fl_csp.sp_bb_data) &
FC_SP_BB_DATA_MASK;
- if (mfs >= FC_SP_MIN_MAX_PAYLOAD &&
- mfs <= lport->mfs) {
- lport->mfs = mfs;
- fc_host_maxframe_size(lport->host) = mfs;
- } else {
+
+ if (mfs < FC_SP_MIN_MAX_PAYLOAD || mfs > FC_SP_MAX_MAX_PAYLOAD) {
FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
"lport->mfs:%hu\n", mfs, lport->mfs);
fc_lport_error(lport, fp);
goto err;
}
+ if (mfs <= lport->mfs) {
+ lport->mfs = mfs;
+ fc_host_maxframe_size(lport->host) = mfs;
+ }
+
csp_flags = ntohs(flp->fl_csp.sp_features);
r_a_tov = ntohl(flp->fl_csp.sp_r_a_tov);
e_d_tov = ntohl(flp->fl_csp.sp_e_d_tov);
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index bc0cecc..441d88a 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -546,11 +546,12 @@
.port_ops = &sas_sata_ops
};
-int sas_ata_init_host_and_port(struct domain_device *found_dev)
+int sas_ata_init(struct domain_device *found_dev)
{
struct sas_ha_struct *ha = found_dev->port->ha;
struct Scsi_Host *shost = ha->core.shost;
struct ata_port *ap;
+ int rc;
ata_host_init(&found_dev->sata_dev.ata_host,
ha->dev,
@@ -567,8 +568,11 @@
ap->private_data = found_dev;
ap->cbl = ATA_CBL_SATA;
ap->scsi_host = shost;
- /* publish initialized ata port */
- smp_wmb();
+ rc = ata_sas_port_init(ap);
+ if (rc) {
+ ata_sas_port_destroy(ap);
+ return rc;
+ }
found_dev->sata_dev.ap = ap;
return 0;
@@ -648,18 +652,13 @@
void sas_probe_sata(struct asd_sas_port *port)
{
struct domain_device *dev, *n;
- int err;
mutex_lock(&port->ha->disco_mutex);
- list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
+ list_for_each_entry(dev, &port->disco_list, disco_list_node) {
if (!dev_is_sata(dev))
continue;
- err = sas_ata_init_host_and_port(dev);
- if (err)
- sas_fail_probe(dev, __func__, err);
- else
- ata_sas_async_port_init(dev->sata_dev.ap);
+ ata_sas_async_probe(dev->sata_dev.ap);
}
mutex_unlock(&port->ha->disco_mutex);
@@ -718,18 +717,6 @@
sas_put_device(dev);
}
-static bool sas_ata_dev_eh_valid(struct domain_device *dev)
-{
- struct ata_port *ap;
-
- if (!dev_is_sata(dev))
- return false;
- ap = dev->sata_dev.ap;
- /* consume fully initialized ata ports */
- smp_rmb();
- return !!ap;
-}
-
void sas_ata_strategy_handler(struct Scsi_Host *shost)
{
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
@@ -753,7 +740,7 @@
spin_lock(&port->dev_list_lock);
list_for_each_entry(dev, &port->dev_list, dev_list_node) {
- if (!sas_ata_dev_eh_valid(dev))
+ if (!dev_is_sata(dev))
continue;
async_schedule_domain(async_sas_ata_eh, dev, &async);
}
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index 3646796..629a086 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -72,6 +72,7 @@
struct asd_sas_phy *phy;
struct sas_rphy *rphy;
struct domain_device *dev;
+ int rc = -ENODEV;
dev = sas_alloc_device();
if (!dev)
@@ -110,9 +111,16 @@
sas_init_dev(dev);
+ dev->port = port;
switch (dev->dev_type) {
- case SAS_END_DEV:
case SATA_DEV:
+ rc = sas_ata_init(dev);
+ if (rc) {
+ rphy = NULL;
+ break;
+ }
+ /* fall through */
+ case SAS_END_DEV:
rphy = sas_end_device_alloc(port->port);
break;
case EDGE_DEV:
@@ -131,19 +139,14 @@
if (!rphy) {
sas_put_device(dev);
- return -ENODEV;
+ return rc;
}
- spin_lock_irq(&port->phy_list_lock);
- list_for_each_entry(phy, &port->phy_list, port_phy_el)
- sas_phy_set_target(phy, dev);
- spin_unlock_irq(&port->phy_list_lock);
rphy->identify.phy_identifier = phy->phy->identify.phy_identifier;
memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE);
sas_fill_in_rphy(dev, rphy);
sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
port->port_dev = dev;
- dev->port = port;
dev->linkrate = port->linkrate;
dev->min_linkrate = port->linkrate;
dev->max_linkrate = port->linkrate;
@@ -155,6 +158,7 @@
sas_device_set_phy(dev, port->port);
dev->rphy = rphy;
+ get_device(&dev->rphy->dev);
if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
list_add_tail(&dev->disco_list_node, &port->disco_list);
@@ -164,6 +168,11 @@
spin_unlock_irq(&port->dev_list_lock);
}
+ spin_lock_irq(&port->phy_list_lock);
+ list_for_each_entry(phy, &port->phy_list, port_phy_el)
+ sas_phy_set_target(phy, dev);
+ spin_unlock_irq(&port->phy_list_lock);
+
return 0;
}
@@ -205,8 +214,7 @@
static void sas_probe_devices(struct work_struct *work)
{
struct domain_device *dev, *n;
- struct sas_discovery_event *ev =
- container_of(work, struct sas_discovery_event, work);
+ struct sas_discovery_event *ev = to_sas_discovery_event(work);
struct asd_sas_port *port = ev->port;
clear_bit(DISCE_PROBE, &port->disc.pending);
@@ -255,6 +263,9 @@
{
struct domain_device *dev = container_of(kref, typeof(*dev), kref);
+ put_device(&dev->rphy->dev);
+ dev->rphy = NULL;
+
if (dev->parent)
sas_put_device(dev->parent);
@@ -291,8 +302,7 @@
static void sas_destruct_devices(struct work_struct *work)
{
struct domain_device *dev, *n;
- struct sas_discovery_event *ev =
- container_of(work, struct sas_discovery_event, work);
+ struct sas_discovery_event *ev = to_sas_discovery_event(work);
struct asd_sas_port *port = ev->port;
clear_bit(DISCE_DESTRUCT, &port->disc.pending);
@@ -302,7 +312,6 @@
sas_remove_children(&dev->rphy->dev);
sas_rphy_delete(dev->rphy);
- dev->rphy = NULL;
sas_unregister_common_dev(port, dev);
}
}
@@ -314,11 +323,11 @@
/* this rphy never saw sas_rphy_add */
list_del_init(&dev->disco_list_node);
sas_rphy_free(dev->rphy);
- dev->rphy = NULL;
sas_unregister_common_dev(port, dev);
+ return;
}
- if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
+ if (!test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
sas_rphy_unlink(dev->rphy);
list_move_tail(&dev->disco_list_node, &port->destroy_list);
sas_discover_event(dev->port, DISCE_DESTRUCT);
@@ -377,8 +386,7 @@
{
struct domain_device *dev;
int error = 0;
- struct sas_discovery_event *ev =
- container_of(work, struct sas_discovery_event, work);
+ struct sas_discovery_event *ev = to_sas_discovery_event(work);
struct asd_sas_port *port = ev->port;
clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending);
@@ -419,8 +427,6 @@
if (error) {
sas_rphy_free(dev->rphy);
- dev->rphy = NULL;
-
list_del_init(&dev->disco_list_node);
spin_lock_irq(&port->dev_list_lock);
list_del_init(&dev->dev_list_node);
@@ -437,8 +443,7 @@
static void sas_revalidate_domain(struct work_struct *work)
{
int res = 0;
- struct sas_discovery_event *ev =
- container_of(work, struct sas_discovery_event, work);
+ struct sas_discovery_event *ev = to_sas_discovery_event(work);
struct asd_sas_port *port = ev->port;
struct sas_ha_struct *ha = port->ha;
@@ -466,21 +471,25 @@
/* ---------- Events ---------- */
-static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work)
+static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
{
- /* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */
- scsi_queue_work(ha->core.shost, work);
+ /* chained work is not subject to SA_HA_DRAINING or
+ * SAS_HA_REGISTERED, because it is either submitted in the
+ * workqueue, or known to be submitted from a context that is
+ * not racing against draining
+ */
+ scsi_queue_work(ha->core.shost, &sw->work);
}
static void sas_chain_event(int event, unsigned long *pending,
- struct work_struct *work,
+ struct sas_work *sw,
struct sas_ha_struct *ha)
{
if (!test_and_set_bit(event, pending)) {
unsigned long flags;
spin_lock_irqsave(&ha->state_lock, flags);
- sas_chain_work(ha, work);
+ sas_chain_work(ha, sw);
spin_unlock_irqrestore(&ha->state_lock, flags);
}
}
@@ -519,7 +528,7 @@
disc->pending = 0;
for (i = 0; i < DISC_NUM_EVENTS; i++) {
- INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
+ INIT_SAS_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
disc->disc_work[i].port = port;
}
}
diff --git a/drivers/scsi/libsas/sas_event.c b/drivers/scsi/libsas/sas_event.c
index 16639bb..4e4292d 100644
--- a/drivers/scsi/libsas/sas_event.c
+++ b/drivers/scsi/libsas/sas_event.c
@@ -27,19 +27,21 @@
#include "sas_internal.h"
#include "sas_dump.h"
-void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work)
+void sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw)
{
if (!test_bit(SAS_HA_REGISTERED, &ha->state))
return;
- if (test_bit(SAS_HA_DRAINING, &ha->state))
- list_add(&work->entry, &ha->defer_q);
- else
- scsi_queue_work(ha->core.shost, work);
+ if (test_bit(SAS_HA_DRAINING, &ha->state)) {
+ /* add it to the defer list, if not already pending */
+ if (list_empty(&sw->drain_node))
+ list_add(&sw->drain_node, &ha->defer_q);
+ } else
+ scsi_queue_work(ha->core.shost, &sw->work);
}
static void sas_queue_event(int event, unsigned long *pending,
- struct work_struct *work,
+ struct sas_work *work,
struct sas_ha_struct *ha)
{
if (!test_and_set_bit(event, pending)) {
@@ -55,7 +57,7 @@
void __sas_drain_work(struct sas_ha_struct *ha)
{
struct workqueue_struct *wq = ha->core.shost->work_q;
- struct work_struct *w, *_w;
+ struct sas_work *sw, *_sw;
set_bit(SAS_HA_DRAINING, &ha->state);
/* flush submitters */
@@ -66,9 +68,9 @@
spin_lock_irq(&ha->state_lock);
clear_bit(SAS_HA_DRAINING, &ha->state);
- list_for_each_entry_safe(w, _w, &ha->defer_q, entry) {
- list_del_init(&w->entry);
- sas_queue_work(ha, w);
+ list_for_each_entry_safe(sw, _sw, &ha->defer_q, drain_node) {
+ list_del_init(&sw->drain_node);
+ sas_queue_work(ha, sw);
}
spin_unlock_irq(&ha->state_lock);
}
@@ -151,7 +153,7 @@
int i;
for (i = 0; i < HA_NUM_EVENTS; i++) {
- INIT_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
+ INIT_SAS_WORK(&sas_ha->ha_events[i].work, sas_ha_event_fns[i]);
sas_ha->ha_events[i].ha = sas_ha;
}
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 05acd9e..caa0525 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -202,6 +202,7 @@
u8 sas_addr[SAS_ADDR_SIZE];
struct smp_resp *resp = rsp;
struct discover_resp *dr = &resp->disc;
+ struct sas_ha_struct *ha = dev->port->ha;
struct expander_device *ex = &dev->ex_dev;
struct ex_phy *phy = &ex->ex_phy[phy_id];
struct sas_rphy *rphy = dev->rphy;
@@ -209,6 +210,8 @@
char *type;
if (new_phy) {
+ if (WARN_ON_ONCE(test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)))
+ return;
phy->phy = sas_phy_alloc(&rphy->dev, phy_id);
/* FIXME: error_handling */
@@ -233,6 +236,8 @@
memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
phy->attached_dev_type = to_dev_type(dr);
+ if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
+ goto out;
phy->phy_id = phy_id;
phy->linkrate = dr->linkrate;
phy->attached_sata_host = dr->attached_sata_host;
@@ -240,7 +245,14 @@
phy->attached_sata_ps = dr->attached_sata_ps;
phy->attached_iproto = dr->iproto << 1;
phy->attached_tproto = dr->tproto << 1;
- memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
+ /* help some expanders that fail to zero sas_address in the 'no
+ * device' case
+ */
+ if (phy->attached_dev_type == NO_DEVICE ||
+ phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
+ memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ else
+ memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
phy->attached_phy_id = dr->attached_phy_id;
phy->phy_change_count = dr->change_count;
phy->routing_attr = dr->routing_attr;
@@ -266,6 +278,7 @@
return;
}
+ out:
switch (phy->attached_dev_type) {
case SATA_PENDING:
type = "stp pending";
@@ -304,7 +317,15 @@
else
return;
- SAS_DPRINTK("ex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
+ /* if the attached device type changed and ata_eh is active,
+ * make sure we run revalidation when eh completes (see:
+ * sas_enable_revalidation)
+ */
+ if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
+ set_bit(DISCE_REVALIDATE_DOMAIN, &dev->port->disc.pending);
+
+ SAS_DPRINTK("%sex %016llx phy%02d:%c:%X attached: %016llx (%s)\n",
+ test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state) ? "ata: " : "",
SAS_ADDR(dev->sas_addr), phy->phy_id,
sas_route_char(dev, phy), phy->linkrate,
SAS_ADDR(phy->attached_sas_addr), type);
@@ -776,13 +797,16 @@
if (res)
goto out_free;
+ sas_init_dev(child);
+ res = sas_ata_init(child);
+ if (res)
+ goto out_free;
rphy = sas_end_device_alloc(phy->port);
- if (unlikely(!rphy))
+ if (!rphy)
goto out_free;
- sas_init_dev(child);
-
child->rphy = rphy;
+ get_device(&rphy->dev);
list_add_tail(&child->disco_list_node, &parent->port->disco_list);
@@ -806,6 +830,7 @@
sas_init_dev(child);
child->rphy = rphy;
+ get_device(&rphy->dev);
sas_fill_in_rphy(child, rphy);
list_add_tail(&child->disco_list_node, &parent->port->disco_list);
@@ -830,8 +855,6 @@
out_list_del:
sas_rphy_free(child->rphy);
- child->rphy = NULL;
-
list_del(&child->disco_list_node);
spin_lock_irq(&parent->port->dev_list_lock);
list_del(&child->dev_list_node);
@@ -911,6 +934,7 @@
}
port = parent->port;
child->rphy = rphy;
+ get_device(&rphy->dev);
edev = rphy_to_expander_device(rphy);
child->dev_type = phy->attached_dev_type;
kref_get(&parent->kref);
@@ -934,6 +958,7 @@
res = sas_discover_expander(child);
if (res) {
+ sas_rphy_delete(rphy);
spin_lock_irq(&parent->port->dev_list_lock);
list_del(&child->dev_list_node);
spin_unlock_irq(&parent->port->dev_list_lock);
@@ -1718,9 +1743,17 @@
int phy_change_count = 0;
res = sas_get_phy_change_count(dev, i, &phy_change_count);
- if (res)
- goto out;
- else if (phy_change_count != ex->ex_phy[i].phy_change_count) {
+ switch (res) {
+ case SMP_RESP_PHY_VACANT:
+ case SMP_RESP_NO_PHY:
+ continue;
+ case SMP_RESP_FUNC_ACC:
+ break;
+ default:
+ return res;
+ }
+
+ if (phy_change_count != ex->ex_phy[i].phy_change_count) {
if (update)
ex->ex_phy[i].phy_change_count =
phy_change_count;
@@ -1728,8 +1761,7 @@
return 0;
}
}
-out:
- return res;
+ return 0;
}
static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 120bff6..10cb5ae 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -94,8 +94,7 @@
void sas_hae_reset(struct work_struct *work)
{
- struct sas_ha_event *ev =
- container_of(work, struct sas_ha_event, work);
+ struct sas_ha_event *ev = to_sas_ha_event(work);
struct sas_ha_struct *ha = ev->ha;
clear_bit(HAE_RESET, &ha->pending);
@@ -369,14 +368,14 @@
static void phy_reset_work(struct work_struct *work)
{
- struct sas_phy_data *d = container_of(work, typeof(*d), reset_work);
+ struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work);
d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset);
}
static void phy_enable_work(struct work_struct *work)
{
- struct sas_phy_data *d = container_of(work, typeof(*d), enable_work);
+ struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work);
d->enable_result = sas_phy_enable(d->phy, d->enable);
}
@@ -389,8 +388,8 @@
return -ENOMEM;
mutex_init(&d->event_lock);
- INIT_WORK(&d->reset_work, phy_reset_work);
- INIT_WORK(&d->enable_work, phy_enable_work);
+ INIT_SAS_WORK(&d->reset_work, phy_reset_work);
+ INIT_SAS_WORK(&d->enable_work, phy_enable_work);
d->phy = phy;
phy->hostdata = d;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index f05c638..507e4cf 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -45,10 +45,10 @@
struct mutex event_lock;
int hard_reset;
int reset_result;
- struct work_struct reset_work;
+ struct sas_work reset_work;
int enable;
int enable_result;
- struct work_struct enable_work;
+ struct sas_work enable_work;
};
void sas_scsi_recover_host(struct Scsi_Host *shost);
@@ -80,7 +80,7 @@
void sas_porte_link_reset_err(struct work_struct *work);
void sas_porte_timer_event(struct work_struct *work);
void sas_porte_hard_reset(struct work_struct *work);
-void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work);
+void sas_queue_work(struct sas_ha_struct *ha, struct sas_work *sw);
int sas_notify_lldd_dev_found(struct domain_device *);
void sas_notify_lldd_dev_gone(struct domain_device *);
diff --git a/drivers/scsi/libsas/sas_phy.c b/drivers/scsi/libsas/sas_phy.c
index dcfd4a9..521422e 100644
--- a/drivers/scsi/libsas/sas_phy.c
+++ b/drivers/scsi/libsas/sas_phy.c
@@ -32,8 +32,7 @@
static void sas_phye_loss_of_signal(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PHYE_LOSS_OF_SIGNAL, &phy->phy_events_pending);
@@ -43,8 +42,7 @@
static void sas_phye_oob_done(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PHYE_OOB_DONE, &phy->phy_events_pending);
@@ -53,8 +51,7 @@
static void sas_phye_oob_error(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
struct sas_ha_struct *sas_ha = phy->ha;
struct asd_sas_port *port = phy->port;
@@ -85,8 +82,7 @@
static void sas_phye_spinup_hold(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
struct sas_ha_struct *sas_ha = phy->ha;
struct sas_internal *i =
@@ -127,14 +123,12 @@
phy->error = 0;
INIT_LIST_HEAD(&phy->port_phy_el);
for (k = 0; k < PORT_NUM_EVENTS; k++) {
- INIT_WORK(&phy->port_events[k].work,
- sas_port_event_fns[k]);
+ INIT_SAS_WORK(&phy->port_events[k].work, sas_port_event_fns[k]);
phy->port_events[k].phy = phy;
}
for (k = 0; k < PHY_NUM_EVENTS; k++) {
- INIT_WORK(&phy->phy_events[k].work,
- sas_phy_event_fns[k]);
+ INIT_SAS_WORK(&phy->phy_events[k].work, sas_phy_event_fns[k]);
phy->phy_events[k].phy = phy;
}
@@ -144,8 +138,7 @@
spin_lock_init(&phy->sas_prim_lock);
phy->frame_rcvd_size = 0;
- phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev,
- i);
+ phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev, i);
if (!phy->phy)
return -ENOMEM;
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c
index eb19c01..e884a8c 100644
--- a/drivers/scsi/libsas/sas_port.c
+++ b/drivers/scsi/libsas/sas_port.c
@@ -123,7 +123,7 @@
spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
if (!port->port) {
- port->port = sas_port_alloc(phy->phy->dev.parent, phy->id);
+ port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
BUG_ON(!port->port);
sas_port_add(port->port);
}
@@ -208,8 +208,7 @@
void sas_porte_bytes_dmaed(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PORTE_BYTES_DMAED, &phy->port_events_pending);
@@ -219,8 +218,7 @@
void sas_porte_broadcast_rcvd(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
unsigned long flags;
u32 prim;
@@ -237,8 +235,7 @@
void sas_porte_link_reset_err(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PORTE_LINK_RESET_ERR, &phy->port_events_pending);
@@ -248,8 +245,7 @@
void sas_porte_timer_event(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PORTE_TIMER_EVENT, &phy->port_events_pending);
@@ -259,8 +255,7 @@
void sas_porte_hard_reset(struct work_struct *work)
{
- struct asd_sas_event *ev =
- container_of(work, struct asd_sas_event, work);
+ struct asd_sas_event *ev = to_asd_sas_event(work);
struct asd_sas_phy *phy = ev->phy;
clear_bit(PORTE_HARD_RESET, &phy->port_events_pending);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 5bdf2ee..af04b0d 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -997,13 +997,6 @@
return nbytes;
}
-static int
-lpfc_debugfs_dif_err_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t
lpfc_debugfs_dif_err_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
@@ -3541,7 +3534,7 @@
#undef lpfc_debugfs_op_dif_err
static const struct file_operations lpfc_debugfs_op_dif_err = {
.owner = THIS_MODULE,
- .open = lpfc_debugfs_dif_err_open,
+ .open = simple_open,
.llseek = lpfc_debugfs_lseek,
.read = lpfc_debugfs_dif_err_read,
.write = lpfc_debugfs_dif_err_write,
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2cfcbff..386f0c5 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -835,7 +835,7 @@
scsi_eh_restore_cmnd(scmd, &ses);
- if (sdrv->eh_action)
+ if (sdrv && sdrv->eh_action)
rtn = sdrv->eh_action(scmd, cmnd, cmnd_size, rtn);
return rtn;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index ead6405..5dfd749 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1638,7 +1638,7 @@
request_fn_proc *request_fn)
{
struct request_queue *q;
- struct device *dev = shost->shost_gendev.parent;
+ struct device *dev = shost->dma_dev;
q = blk_init_queue(request_fn, NULL);
if (!q)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3ed7483..00c0240 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -74,7 +74,7 @@
This selects a driver for the Atmel SPI Controller, present on
many AT32 (AVR32) and AT91 (ARM) chips.
-config SPI_BFIN
+config SPI_BFIN5XX
tristate "SPI controller driver for ADI Blackfin5xx"
depends on BLACKFIN
help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index a1d48e0..9d75d21 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -15,7 +15,7 @@
obj-$(CONFIG_SPI_ATH79) += spi-ath79.o
obj-$(CONFIG_SPI_AU1550) += spi-au1550.o
obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o
-obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o
+obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o
obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o
obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o
obj-$(CONFIG_SPI_BUTTERFLY) += spi-butterfly.o
diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c
index f01b264..7491971 100644
--- a/drivers/spi/spi-bcm63xx.c
+++ b/drivers/spi/spi-bcm63xx.c
@@ -1,7 +1,7 @@
/*
* Broadcom BCM63xx SPI controller support
*
- * Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2009-2012 Florian Fainelli <florian@openwrt.org>
* Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
*
* This program is free software; you can redistribute it and/or
@@ -30,6 +30,8 @@
#include <linux/spi/spi.h>
#include <linux/completion.h>
#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
#include <bcm63xx_dev_spi.h>
@@ -37,8 +39,6 @@
#define DRV_VER "0.1.2"
struct bcm63xx_spi {
- spinlock_t lock;
- int stopping;
struct completion done;
void __iomem *regs;
@@ -96,17 +96,12 @@
{ 391000, SPI_CLK_0_391MHZ }
};
-static int bcm63xx_spi_setup_transfer(struct spi_device *spi,
- struct spi_transfer *t)
+static int bcm63xx_spi_check_transfer(struct spi_device *spi,
+ struct spi_transfer *t)
{
- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
u8 bits_per_word;
- u8 clk_cfg, reg;
- u32 hz;
- int i;
bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
- hz = (t) ? t->speed_hz : spi->max_speed_hz;
if (bits_per_word != 8) {
dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n",
__func__, bits_per_word);
@@ -119,6 +114,19 @@
return -EINVAL;
}
+ return 0;
+}
+
+static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
+ struct spi_transfer *t)
+{
+ struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+ u32 hz;
+ u8 clk_cfg, reg;
+ int i;
+
+ hz = (t) ? t->speed_hz : spi->max_speed_hz;
+
/* Find the closest clock configuration */
for (i = 0; i < SPI_CLK_MASK; i++) {
if (hz <= bcm63xx_spi_freq_table[i][0]) {
@@ -139,8 +147,6 @@
bcm_spi_writeb(bs, reg, SPI_CLK_CFG);
dev_dbg(&spi->dev, "Setting clock register to %02x (hz %d)\n",
clk_cfg, hz);
-
- return 0;
}
/* the spi->mode bits understood by this driver: */
@@ -153,9 +159,6 @@
bs = spi_master_get_devdata(spi->master);
- if (bs->stopping)
- return -ESHUTDOWN;
-
if (!spi->bits_per_word)
spi->bits_per_word = 8;
@@ -165,7 +168,7 @@
return -EINVAL;
}
- ret = bcm63xx_spi_setup_transfer(spi, NULL);
+ ret = bcm63xx_spi_check_transfer(spi, NULL);
if (ret < 0) {
dev_err(&spi->dev, "setup: unsupported mode bits %x\n",
spi->mode & ~MODEBITS);
@@ -190,28 +193,29 @@
bs->remaining_bytes -= size;
}
-static int bcm63xx_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
+ struct spi_transfer *t)
{
struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
u16 msg_ctl;
u16 cmd;
+ /* Disable the CMD_DONE interrupt */
+ bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+
dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n",
t->tx_buf, t->rx_buf, t->len);
/* Transmitter is inhibited */
bs->tx_ptr = t->tx_buf;
bs->rx_ptr = t->rx_buf;
- init_completion(&bs->done);
if (t->tx_buf) {
bs->remaining_bytes = t->len;
bcm63xx_spi_fill_tx_fifo(bs);
}
- /* Enable the command done interrupt which
- * we use to determine completion of a command */
- bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
+ init_completion(&bs->done);
/* Fill in the Message control register */
msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
@@ -230,33 +234,76 @@
cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
cmd |= (spi->chip_select << SPI_CMD_DEVICE_ID_SHIFT);
bcm_spi_writew(bs, cmd, SPI_CMD);
- wait_for_completion(&bs->done);
- /* Disable the CMD_DONE interrupt */
- bcm_spi_writeb(bs, 0, SPI_INT_MASK);
+ /* Enable the CMD_DONE interrupt */
+ bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
return t->len - bs->remaining_bytes;
}
-static int bcm63xx_transfer(struct spi_device *spi, struct spi_message *m)
+static int bcm63xx_spi_prepare_transfer(struct spi_master *master)
{
- struct bcm63xx_spi *bs = spi_master_get_devdata(spi->master);
+ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+
+ pm_runtime_get_sync(&bs->pdev->dev);
+
+ return 0;
+}
+
+static int bcm63xx_spi_unprepare_transfer(struct spi_master *master)
+{
+ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+
+ pm_runtime_put(&bs->pdev->dev);
+
+ return 0;
+}
+
+static int bcm63xx_spi_transfer_one(struct spi_master *master,
+ struct spi_message *m)
+{
+ struct bcm63xx_spi *bs = spi_master_get_devdata(master);
struct spi_transfer *t;
- int ret = 0;
-
- if (unlikely(list_empty(&m->transfers)))
- return -EINVAL;
-
- if (bs->stopping)
- return -ESHUTDOWN;
+ struct spi_device *spi = m->spi;
+ int status = 0;
+ unsigned int timeout = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
- ret += bcm63xx_txrx_bufs(spi, t);
+ unsigned int len = t->len;
+ u8 rx_tail;
+
+ status = bcm63xx_spi_check_transfer(spi, t);
+ if (status < 0)
+ goto exit;
+
+ /* configure adapter for a new transfer */
+ bcm63xx_spi_setup_transfer(spi, t);
+
+ while (len) {
+ /* send the data */
+ len -= bcm63xx_txrx_bufs(spi, t);
+
+ timeout = wait_for_completion_timeout(&bs->done, HZ);
+ if (!timeout) {
+ status = -ETIMEDOUT;
+ goto exit;
+ }
+
+ /* read out all data */
+ rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
+
+ /* Read out all the data */
+ if (rx_tail)
+ memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
+ }
+
+ m->actual_length += t->len;
}
+exit:
+ m->status = status;
+ spi_finalize_current_message(master);
- m->complete(m->context);
-
- return ret;
+ return 0;
}
/* This driver supports single master mode only. Hence
@@ -267,39 +314,15 @@
struct spi_master *master = (struct spi_master *)dev_id;
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
u8 intr;
- u16 cmd;
/* Read interupts and clear them immediately */
intr = bcm_spi_readb(bs, SPI_INT_STATUS);
bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
- /* A tansfer completed */
- if (intr & SPI_INTR_CMD_DONE) {
- u8 rx_tail;
-
- rx_tail = bcm_spi_readb(bs, SPI_RX_TAIL);
-
- /* Read out all the data */
- if (rx_tail)
- memcpy_fromio(bs->rx_ptr, bs->rx_io, rx_tail);
-
- /* See if there is more data to send */
- if (bs->remaining_bytes > 0) {
- bcm63xx_spi_fill_tx_fifo(bs);
-
- /* Start the transfer */
- bcm_spi_writew(bs, SPI_HD_W << SPI_MSG_TYPE_SHIFT,
- SPI_MSG_CTL);
- cmd = bcm_spi_readw(bs, SPI_CMD);
- cmd |= SPI_CMD_START_IMMEDIATE;
- cmd |= (0 << SPI_CMD_PREPEND_BYTE_CNT_SHIFT);
- bcm_spi_writeb(bs, SPI_INTR_CMD_DONE, SPI_INT_MASK);
- bcm_spi_writew(bs, cmd, SPI_CMD);
- } else {
- complete(&bs->done);
- }
- }
+ /* A transfer completed */
+ if (intr & SPI_INTR_CMD_DONE)
+ complete(&bs->done);
return IRQ_HANDLED;
}
@@ -345,7 +368,6 @@
}
bs = spi_master_get_devdata(master);
- init_completion(&bs->done);
platform_set_drvdata(pdev, master);
bs->pdev = pdev;
@@ -379,12 +401,13 @@
master->bus_num = pdata->bus_num;
master->num_chipselect = pdata->num_chipselect;
master->setup = bcm63xx_spi_setup;
- master->transfer = bcm63xx_transfer;
+ master->prepare_transfer_hardware = bcm63xx_spi_prepare_transfer;
+ master->unprepare_transfer_hardware = bcm63xx_spi_unprepare_transfer;
+ master->transfer_one_message = bcm63xx_spi_transfer_one;
+ master->mode_bits = MODEBITS;
bs->speed_hz = pdata->speed_hz;
- bs->stopping = 0;
bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
- spin_lock_init(&bs->lock);
/* Initialize hardware */
clk_enable(bs->clk);
@@ -418,18 +441,16 @@
struct spi_master *master = platform_get_drvdata(pdev);
struct bcm63xx_spi *bs = spi_master_get_devdata(master);
+ spi_unregister_master(master);
+
/* reset spi block */
bcm_spi_writeb(bs, 0, SPI_INT_MASK);
- spin_lock(&bs->lock);
- bs->stopping = 1;
/* HW shutdown */
clk_disable(bs->clk);
clk_put(bs->clk);
- spin_unlock(&bs->lock);
platform_set_drvdata(pdev, 0);
- spi_unregister_master(master);
return 0;
}
diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c
index 248a2cc..1fe5119 100644
--- a/drivers/spi/spi-bfin-sport.c
+++ b/drivers/spi/spi-bfin-sport.c
@@ -252,19 +252,15 @@
bfin_sport_spi_restore_state(struct bfin_sport_spi_master_data *drv_data)
{
struct bfin_sport_spi_slave_data *chip = drv_data->cur_chip;
- unsigned int bits = (drv_data->ops == &bfin_sport_transfer_ops_u8 ? 7 : 15);
bfin_sport_spi_disable(drv_data);
dev_dbg(drv_data->dev, "restoring spi ctl state\n");
bfin_write(&drv_data->regs->tcr1, chip->ctl_reg);
- bfin_write(&drv_data->regs->tcr2, bits);
bfin_write(&drv_data->regs->tclkdiv, chip->baud);
- bfin_write(&drv_data->regs->tfsdiv, bits);
SSYNC();
bfin_write(&drv_data->regs->rcr1, chip->ctl_reg & ~(ITCLK | ITFS));
- bfin_write(&drv_data->regs->rcr2, bits);
SSYNC();
bfin_sport_spi_cs_active(chip);
@@ -420,11 +416,15 @@
drv_data->cs_change = transfer->cs_change;
/* Bits per word setup */
- bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
- if (bits_per_word == 8)
- drv_data->ops = &bfin_sport_transfer_ops_u8;
- else
+ bits_per_word = transfer->bits_per_word ? :
+ message->spi->bits_per_word ? : 8;
+ if (bits_per_word % 16 == 0)
drv_data->ops = &bfin_sport_transfer_ops_u16;
+ else
+ drv_data->ops = &bfin_sport_transfer_ops_u8;
+ bfin_write(&drv_data->regs->tcr2, bits_per_word - 1);
+ bfin_write(&drv_data->regs->tfsdiv, bits_per_word - 1);
+ bfin_write(&drv_data->regs->rcr2, bits_per_word - 1);
drv_data->state = RUNNING_STATE;
@@ -598,11 +598,12 @@
}
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
chip->idle_tx_val = chip_info->idle_tx_val;
- spi->bits_per_word = chip_info->bits_per_word;
}
}
- if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+ if (spi->bits_per_word % 8) {
+ dev_err(&spi->dev, "%d bits_per_word is not supported\n",
+ spi->bits_per_word);
ret = -EINVAL;
goto error;
}
diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c
index 3b83ff8..9bb4d4a 100644
--- a/drivers/spi/spi-bfin5xx.c
+++ b/drivers/spi/spi-bfin5xx.c
@@ -396,7 +396,7 @@
/* last read */
if (drv_data->rx) {
dev_dbg(&drv_data->pdev->dev, "last read\n");
- if (n_bytes % 2) {
+ if (!(n_bytes % 2)) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++)
*buf++ = bfin_read(&drv_data->regs->rdbr);
@@ -424,7 +424,7 @@
if (drv_data->rx && drv_data->tx) {
/* duplex */
dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
- if (n_bytes % 2) {
+ if (!(n_bytes % 2)) {
u16 *buf = (u16 *)drv_data->rx;
u16 *buf2 = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
@@ -442,7 +442,7 @@
} else if (drv_data->rx) {
/* read */
dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
- if (n_bytes % 2) {
+ if (!(n_bytes % 2)) {
u16 *buf = (u16 *)drv_data->rx;
for (loop = 0; loop < n_bytes / 2; loop++) {
*buf++ = bfin_read(&drv_data->regs->rdbr);
@@ -458,7 +458,7 @@
} else if (drv_data->tx) {
/* write */
dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
- if (n_bytes % 2) {
+ if (!(n_bytes % 2)) {
u16 *buf = (u16 *)drv_data->tx;
for (loop = 0; loop < n_bytes / 2; loop++) {
bfin_read(&drv_data->regs->rdbr);
@@ -587,6 +587,7 @@
if (message->state == DONE_STATE) {
dev_dbg(&drv_data->pdev->dev, "transfer: all done!\n");
message->status = 0;
+ bfin_spi_flush(drv_data);
bfin_spi_giveback(drv_data);
return;
}
@@ -870,8 +871,10 @@
message->actual_length += drv_data->len_in_bytes;
/* Move to next transfer of this msg */
message->state = bfin_spi_next_transfer(drv_data);
- if (drv_data->cs_change)
+ if (drv_data->cs_change && message->state != DONE_STATE) {
+ bfin_spi_flush(drv_data);
bfin_spi_cs_deactive(drv_data, chip);
+ }
}
/* Schedule next transfer tasklet */
@@ -1026,7 +1029,6 @@
chip->cs_chg_udelay = chip_info->cs_chg_udelay;
chip->idle_tx_val = chip_info->idle_tx_val;
chip->pio_interrupt = chip_info->pio_interrupt;
- spi->bits_per_word = chip_info->bits_per_word;
} else {
/* force a default base state */
chip->ctl_reg &= bfin_ctl_reg;
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 31bfba8..9b2901f 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -653,7 +653,7 @@
dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
rx_buf_count);
if (t->tx_buf)
- dma_unmap_single(NULL, t->tx_dma, t->len,
+ dma_unmap_single(&spi->dev, t->tx_dma, t->len,
DMA_TO_DEVICE);
return -ENOMEM;
}
@@ -692,10 +692,10 @@
if (spicfg->io_type == SPI_IO_TYPE_DMA) {
if (t->tx_buf)
- dma_unmap_single(NULL, t->tx_dma, t->len,
+ dma_unmap_single(&spi->dev, t->tx_dma, t->len,
DMA_TO_DEVICE);
- dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
+ dma_unmap_single(&spi->dev, t->rx_dma, rx_buf_count,
DMA_FROM_DEVICE);
clear_io_bits(dspi->base + SPIINT, SPIINT_DMA_REQ_EN);
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 082458d..d1a495f 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -63,12 +63,6 @@
};
#ifdef CONFIG_DEBUG_FS
-static int spi_show_regs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define SPI_REGS_BUFSIZE 1024
static ssize_t spi_show_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -128,7 +122,7 @@
static const struct file_operations mrst_spi_regs_ops = {
.owner = THIS_MODULE,
- .open = spi_show_regs_open,
+ .open = simple_open,
.read = spi_show_regs,
.llseek = default_llseek,
};
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index 6db2887..e805507 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -545,13 +545,12 @@
* in case of failure.
*/
static struct dma_async_tx_descriptor *
-ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_data_direction dir)
+ep93xx_spi_dma_prepare(struct ep93xx_spi *espi, enum dma_transfer_direction dir)
{
struct spi_transfer *t = espi->current_msg->state;
struct dma_async_tx_descriptor *txd;
enum dma_slave_buswidth buswidth;
struct dma_slave_config conf;
- enum dma_transfer_direction slave_dirn;
struct scatterlist *sg;
struct sg_table *sgt;
struct dma_chan *chan;
@@ -567,14 +566,13 @@
memset(&conf, 0, sizeof(conf));
conf.direction = dir;
- if (dir == DMA_FROM_DEVICE) {
+ if (dir == DMA_DEV_TO_MEM) {
chan = espi->dma_rx;
buf = t->rx_buf;
sgt = &espi->rx_sgt;
conf.src_addr = espi->sspdr_phys;
conf.src_addr_width = buswidth;
- slave_dirn = DMA_DEV_TO_MEM;
} else {
chan = espi->dma_tx;
buf = t->tx_buf;
@@ -582,7 +580,6 @@
conf.dst_addr = espi->sspdr_phys;
conf.dst_addr_width = buswidth;
- slave_dirn = DMA_MEM_TO_DEV;
}
ret = dmaengine_slave_config(chan, &conf);
@@ -633,8 +630,7 @@
if (!nents)
return ERR_PTR(-ENOMEM);
- txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents,
- slave_dirn, DMA_CTRL_ACK);
+ txd = dmaengine_prep_slave_sg(chan, sgt->sgl, nents, dir, DMA_CTRL_ACK);
if (!txd) {
dma_unmap_sg(chan->device->dev, sgt->sgl, sgt->nents, dir);
return ERR_PTR(-ENOMEM);
@@ -651,12 +647,12 @@
* unmapped.
*/
static void ep93xx_spi_dma_finish(struct ep93xx_spi *espi,
- enum dma_data_direction dir)
+ enum dma_transfer_direction dir)
{
struct dma_chan *chan;
struct sg_table *sgt;
- if (dir == DMA_FROM_DEVICE) {
+ if (dir == DMA_DEV_TO_MEM) {
chan = espi->dma_rx;
sgt = &espi->rx_sgt;
} else {
@@ -677,16 +673,16 @@
struct spi_message *msg = espi->current_msg;
struct dma_async_tx_descriptor *rxd, *txd;
- rxd = ep93xx_spi_dma_prepare(espi, DMA_FROM_DEVICE);
+ rxd = ep93xx_spi_dma_prepare(espi, DMA_DEV_TO_MEM);
if (IS_ERR(rxd)) {
dev_err(&espi->pdev->dev, "DMA RX failed: %ld\n", PTR_ERR(rxd));
msg->status = PTR_ERR(rxd);
return;
}
- txd = ep93xx_spi_dma_prepare(espi, DMA_TO_DEVICE);
+ txd = ep93xx_spi_dma_prepare(espi, DMA_MEM_TO_DEV);
if (IS_ERR(txd)) {
- ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+ ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
dev_err(&espi->pdev->dev, "DMA TX failed: %ld\n", PTR_ERR(rxd));
msg->status = PTR_ERR(txd);
return;
@@ -705,8 +701,8 @@
wait_for_completion(&espi->wait);
- ep93xx_spi_dma_finish(espi, DMA_TO_DEVICE);
- ep93xx_spi_dma_finish(espi, DMA_FROM_DEVICE);
+ ep93xx_spi_dma_finish(espi, DMA_MEM_TO_DEV);
+ ep93xx_spi_dma_finish(espi, DMA_DEV_TO_MEM);
}
/**
diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
index 24cacff..5f748c0 100644
--- a/drivers/spi/spi-fsl-spi.c
+++ b/drivers/spi/spi-fsl-spi.c
@@ -139,10 +139,12 @@
static void fsl_spi_chipselect(struct spi_device *spi, int value)
{
struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(spi->master);
- struct fsl_spi_platform_data *pdata = spi->dev.parent->platform_data;
+ struct fsl_spi_platform_data *pdata;
bool pol = spi->mode & SPI_CS_HIGH;
struct spi_mpc8xxx_cs *cs = spi->controller_state;
+ pdata = spi->dev.parent->parent->platform_data;
+
if (value == BITBANG_CS_INACTIVE) {
if (pdata->cs_control)
pdata->cs_control(spi, !pol);
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 31054e3..570f220 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -83,7 +83,7 @@
struct spi_bitbang bitbang;
struct completion xfer_done;
- void *base;
+ void __iomem *base;
int irq;
struct clk *clk;
unsigned long spi_clk;
@@ -766,8 +766,12 @@
}
ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
- if (ret < 0)
- num_cs = mxc_platform_info->num_chipselect;
+ if (ret < 0) {
+ if (mxc_platform_info)
+ num_cs = mxc_platform_info->num_chipselect;
+ else
+ return ret;
+ }
master = spi_alloc_master(&pdev->dev,
sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
@@ -784,7 +788,7 @@
for (i = 0; i < master->num_chipselect; i++) {
int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
- if (cs_gpio < 0)
+ if (cs_gpio < 0 && mxc_platform_info)
cs_gpio = mxc_platform_info->chipselect[i];
spi_imx->chipselect[i] = cs_gpio;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 96f0da6..400ae21 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -1667,9 +1667,15 @@
/* cpsdvsr = 254 & scr = 255 */
min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
- if (!((freq <= max_tclk) && (freq >= min_tclk))) {
+ if (freq > max_tclk)
+ dev_warn(&pl022->adev->dev,
+ "Max speed that can be programmed is %d Hz, you requested %d\n",
+ max_tclk, freq);
+
+ if (freq < min_tclk) {
dev_err(&pl022->adev->dev,
- "controller data is incorrect: out of range frequency");
+ "Requested frequency: %d Hz is less than minimum possible %d Hz\n",
+ freq, min_tclk);
return -EINVAL;
}
@@ -1681,26 +1687,37 @@
while (scr <= SCR_MAX) {
tmp = spi_rate(rate, cpsdvsr, scr);
- if (tmp > freq)
+ if (tmp > freq) {
+ /* we need lower freq */
scr++;
+ continue;
+ }
+
/*
- * If found exact value, update and break.
- * If found more closer value, update and continue.
+ * If found exact value, mark found and break.
+ * If found more closer value, update and break.
*/
- else if ((tmp == freq) || (tmp > best_freq)) {
+ if (tmp > best_freq) {
best_freq = tmp;
best_cpsdvsr = cpsdvsr;
best_scr = scr;
if (tmp == freq)
- break;
+ found = 1;
}
- scr++;
+ /*
+ * increased scr will give lower rates, which are not
+ * required
+ */
+ break;
}
cpsdvsr += 2;
scr = SCR_MIN;
}
+ WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
+ freq);
+
clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
clk_freq->scr = (u8) (best_scr & 0xFF);
dev_dbg(&pl022->adev->dev,
@@ -1823,9 +1840,12 @@
} else
chip->cs_control = chip_info->cs_control;
- if (bits <= 3) {
- /* PL022 doesn't support less than 4-bits */
+ /* Check bits per word with vendor specific range */
+ if ((bits <= 3) || (bits > pl022->vendor->max_bpw)) {
status = -ENOTSUPP;
+ dev_err(&spi->dev, "illegal data size for this controller!\n");
+ dev_err(&spi->dev, "This controller can only handle 4 <= n <= %d bit words\n",
+ pl022->vendor->max_bpw);
goto err_config_params;
} else if (bits <= 8) {
dev_dbg(&spi->dev, "4 <= n <=8 bits per word\n");
@@ -1838,20 +1858,10 @@
chip->read = READING_U16;
chip->write = WRITING_U16;
} else {
- if (pl022->vendor->max_bpw >= 32) {
- dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
- chip->n_bytes = 4;
- chip->read = READING_U32;
- chip->write = WRITING_U32;
- } else {
- dev_err(&spi->dev,
- "illegal data size for this controller!\n");
- dev_err(&spi->dev,
- "a standard pl022 can only handle "
- "1 <= n <= 16 bit words\n");
- status = -ENOTSUPP;
- goto err_config_params;
- }
+ dev_dbg(&spi->dev, "17 <= n <= 32 bits per word\n");
+ chip->n_bytes = 4;
+ chip->read = READING_U32;
+ chip->write = WRITING_U32;
}
/* Now Initialize all register settings required for this chip */
@@ -2195,7 +2205,6 @@
struct pl022 *pl022 = dev_get_drvdata(dev);
clk_disable(pl022->clk);
- amba_vcore_disable(pl022->adev);
return 0;
}
@@ -2204,7 +2213,6 @@
{
struct pl022 *pl022 = dev_get_drvdata(dev);
- amba_vcore_enable(pl022->adev);
clk_enable(pl022->clk);
return 0;
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 08a3b11..eb1dee2 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -27,13 +27,14 @@
config ANDROID_PERSISTENT_RAM
bool
+ depends on HAVE_MEMBLOCK
select REED_SOLOMON
select REED_SOLOMON_ENC8
select REED_SOLOMON_DEC8
config ANDROID_RAM_CONSOLE
bool "Android RAM buffer console"
- depends on !S390 && !UML
+ depends on !S390 && !UML && HAVE_MEMBLOCK
select ANDROID_PERSISTENT_RAM
default n
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 052b43e..b91e4bc 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -55,7 +55,6 @@
};
static int lowmem_minfree_size = 4;
-static struct task_struct *lowmem_deathpending;
static unsigned long lowmem_deathpending_timeout;
#define lowmem_print(level, x...) \
@@ -64,24 +63,6 @@
printk(x); \
} while (0)
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data);
-
-static struct notifier_block task_nb = {
- .notifier_call = task_notify_func,
-};
-
-static int
-task_notify_func(struct notifier_block *self, unsigned long val, void *data)
-{
- struct task_struct *task = data;
-
- if (task == lowmem_deathpending)
- lowmem_deathpending = NULL;
-
- return NOTIFY_OK;
-}
-
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -97,19 +78,6 @@
int other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
- /*
- * If we already have a death outstanding, then
- * bail out right away; indicating to vmscan
- * that we have nothing further to offer on
- * this pass.
- *
- * Note: Currently you need CONFIG_PROFILING
- * for this to work correctly.
- */
- if (lowmem_deathpending &&
- time_before_eq(jiffies, lowmem_deathpending_timeout))
- return 0;
-
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
@@ -148,6 +116,12 @@
if (!p)
continue;
+ if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
+ time_before_eq(jiffies, lowmem_deathpending_timeout)) {
+ task_unlock(p);
+ rcu_read_unlock();
+ return 0;
+ }
oom_score_adj = p->signal->oom_score_adj;
if (oom_score_adj < min_score_adj) {
task_unlock(p);
@@ -174,15 +148,9 @@
lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
selected->pid, selected->comm,
selected_oom_score_adj, selected_tasksize);
- /*
- * If CONFIG_PROFILING is off, then we don't want to stall
- * the killer by setting lowmem_deathpending.
- */
-#ifdef CONFIG_PROFILING
- lowmem_deathpending = selected;
lowmem_deathpending_timeout = jiffies + HZ;
-#endif
send_sig(SIGKILL, selected, 0);
+ set_tsk_thread_flag(selected, TIF_MEMDIE);
rem -= selected_tasksize;
}
lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",
@@ -198,7 +166,6 @@
static int __init lowmem_init(void)
{
- task_handoff_register(&task_nb);
register_shrinker(&lowmem_shrinker);
return 0;
}
@@ -206,7 +173,6 @@
static void __exit lowmem_exit(void)
{
unregister_shrinker(&lowmem_shrinker);
- task_handoff_unregister(&task_nb);
}
module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
diff --git a/drivers/staging/android/persistent_ram.c b/drivers/staging/android/persistent_ram.c
index e08f257..8d8c1e3 100644
--- a/drivers/staging/android/persistent_ram.c
+++ b/drivers/staging/android/persistent_ram.c
@@ -399,12 +399,12 @@
struct persistent_ram_zone *__persistent_ram_init(struct device *dev, bool ecc)
{
struct persistent_ram_zone *prz;
- int ret;
+ int ret = -ENOMEM;
prz = kzalloc(sizeof(struct persistent_ram_zone), GFP_KERNEL);
if (!prz) {
pr_err("persistent_ram: failed to allocate persistent ram zone\n");
- return ERR_PTR(-ENOMEM);
+ goto err;
}
INIT_LIST_HEAD(&prz->node);
@@ -412,13 +412,13 @@
ret = persistent_ram_buffer_init(dev_name(dev), prz);
if (ret) {
pr_err("persistent_ram: failed to initialize buffer\n");
- return ERR_PTR(ret);
+ goto err;
}
prz->ecc = ecc;
ret = persistent_ram_init_ecc(prz, prz->buffer_size);
if (ret)
- return ERR_PTR(ret);
+ goto err;
if (prz->buffer->sig == PERSISTENT_RAM_SIG) {
if (buffer_size(prz) > prz->buffer_size ||
@@ -442,6 +442,9 @@
atomic_set(&prz->buffer->size, 0);
return prz;
+err:
+ kfree(prz);
+ return ERR_PTR(ret);
}
struct persistent_ram_zone * __init
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
index bc723ef..45c522c 100644
--- a/drivers/staging/android/timed_gpio.c
+++ b/drivers/staging/android/timed_gpio.c
@@ -85,7 +85,7 @@
struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
struct timed_gpio *cur_gpio;
struct timed_gpio_data *gpio_data, *gpio_dat;
- int i, j, ret = 0;
+ int i, ret;
if (!pdata)
return -EBUSY;
@@ -108,18 +108,12 @@
gpio_dat->dev.get_time = gpio_get_time;
gpio_dat->dev.enable = gpio_enable;
ret = gpio_request(cur_gpio->gpio, cur_gpio->name);
- if (ret >= 0) {
- ret = timed_output_dev_register(&gpio_dat->dev);
- if (ret < 0)
- gpio_free(cur_gpio->gpio);
- }
+ if (ret < 0)
+ goto err_out;
+ ret = timed_output_dev_register(&gpio_dat->dev);
if (ret < 0) {
- for (j = 0; j < i; j++) {
- timed_output_dev_unregister(&gpio_data[i].dev);
- gpio_free(gpio_data[i].gpio);
- }
- kfree(gpio_data);
- return ret;
+ gpio_free(cur_gpio->gpio);
+ goto err_out;
}
gpio_dat->gpio = cur_gpio->gpio;
@@ -131,6 +125,15 @@
platform_set_drvdata(pdev, gpio_data);
return 0;
+
+err_out:
+ while (--i >= 0) {
+ timed_output_dev_unregister(&gpio_data[i].dev);
+ gpio_free(gpio_data[i].gpio);
+ }
+ kfree(gpio_data);
+
+ return ret;
}
static int timed_gpio_remove(struct platform_device *pdev)
diff --git a/drivers/staging/iio/inkern.c b/drivers/staging/iio/inkern.c
index de2c8ea..ef07a02 100644
--- a/drivers/staging/iio/inkern.c
+++ b/drivers/staging/iio/inkern.c
@@ -82,6 +82,7 @@
ret = -ENODEV;
goto error_ret;
}
+ i++;
}
error_ret:
mutex_unlock(&iio_map_list_lock);
diff --git a/drivers/staging/iio/magnetometer/ak8975.c b/drivers/staging/iio/magnetometer/ak8975.c
index d5ddac3..ebc2d08 100644
--- a/drivers/staging/iio/magnetometer/ak8975.c
+++ b/drivers/staging/iio/magnetometer/ak8975.c
@@ -108,7 +108,8 @@
static int ak8975_write_data(struct i2c_client *client,
u8 reg, u8 val, u8 mask, u8 shift)
{
- struct ak8975_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak8975_data *data = iio_priv(indio_dev);
u8 regval;
int ret;
@@ -159,7 +160,8 @@
*/
static int ak8975_setup(struct i2c_client *client)
{
- struct ak8975_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct ak8975_data *data = iio_priv(indio_dev);
u8 device_id;
int ret;
@@ -509,6 +511,7 @@
goto exit_gpio;
}
data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
/* Perform some basic start-of-day setup of the device. */
err = ak8975_setup(client);
if (err < 0) {
@@ -516,7 +519,6 @@
goto exit_free_iio;
}
- i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
data->eoc_irq = client->irq;
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index 91dd3da..e00b416 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -521,7 +521,9 @@
/* Called when we have found a new HMC5843. */
static void hmc5843_init_client(struct i2c_client *client)
{
- struct hmc5843_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
+
hmc5843_set_meas_conf(client, data->meas_conf);
hmc5843_set_rate(client, data->rate);
hmc5843_configure(client, data->operating_mode);
diff --git a/drivers/staging/media/as102/as102_fw.c b/drivers/staging/media/as102/as102_fw.c
index 43ebc43..1075fb1 100644
--- a/drivers/staging/media/as102/as102_fw.c
+++ b/drivers/staging/media/as102/as102_fw.c
@@ -165,7 +165,7 @@
int as102_fw_upload(struct as10x_bus_adapter_t *bus_adap)
{
int errno = -EFAULT;
- const struct firmware *firmware;
+ const struct firmware *firmware = NULL;
unsigned char *cmd_buf = NULL;
char *fw1, *fw2;
struct usb_device *dev = bus_adap->usb_dev;
diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c
index 400df8c..d91751f 100644
--- a/drivers/staging/octeon/ethernet-rx.c
+++ b/drivers/staging/octeon/ethernet-rx.c
@@ -36,6 +36,7 @@
#include <linux/prefetch.h>
#include <linux/ratelimit.h>
#include <linux/smp.h>
+#include <linux/interrupt.h>
#include <net/dst.h>
#ifdef CONFIG_XFRM
#include <linux/xfrm.h>
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 56d74dc..91a97b3 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -32,6 +32,7 @@
#include <linux/ip.h>
#include <linux/ratelimit.h>
#include <linux/string.h>
+#include <linux/interrupt.h>
#include <net/dst.h>
#ifdef CONFIG_XFRM
#include <linux/xfrm.h>
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index 9112cd8..60cba81 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -31,6 +31,7 @@
#include <linux/etherdevice.h>
#include <linux/phy.h>
#include <linux/slab.h>
+#include <linux/interrupt.h>
#include <net/dst.h>
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 3df5b4c..620b8d5 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -803,9 +803,6 @@
static int pdev_probe(struct platform_device *device)
{
DBG("%s", device->name);
- if (platform_driver_register(&omap_dmm_driver))
- dev_err(&device->dev, "DMM registration failed\n");
-
return drm_platform_init(&omap_drm_driver, device);
}
@@ -833,6 +830,10 @@
static int __init omap_drm_init(void)
{
DBG("init");
+ if (platform_driver_register(&omap_dmm_driver)) {
+ /* we can continue on without DMM.. so not fatal */
+ dev_err(NULL, "DMM registration failed\n");
+ }
return platform_driver_register(&pdev);
}
diff --git a/drivers/staging/ozwpan/TODO b/drivers/staging/ozwpan/TODO
index f7a9c12..c2d30a71 100644
--- a/drivers/staging/ozwpan/TODO
+++ b/drivers/staging/ozwpan/TODO
@@ -8,5 +8,7 @@
- code review by USB developer community.
- testing with as many devices as possible.
-Please send any patches for this driver to Chris Kelly <ckelly@ozmodevices.com>
+Please send any patches for this driver to
+Rupesh Gujare <rgujare@ozmodevices.com>
+Chris Kelly <ckelly@ozmodevices.com>
and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index 2b45d3d..04cd57f 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -383,8 +383,6 @@
pd->tx_pool = &f->link;
pd->tx_pool_count++;
f = 0;
- } else {
- kfree(f);
}
spin_unlock_bh(&pd->tx_frame_lock);
if (f)
diff --git a/drivers/staging/ramster/Kconfig b/drivers/staging/ramster/Kconfig
index 8b57b87..4af1f8d 100644
--- a/drivers/staging/ramster/Kconfig
+++ b/drivers/staging/ramster/Kconfig
@@ -1,10 +1,6 @@
-# Dependency on CONFIG_BROKEN is because there is a commit dependency
-# on a cleancache naming change to be submitted by Konrad Wilk
-# a39c00ded70339603ffe1b0ffdf3ade85bcf009a "Merge branch 'stable/cleancache.v13'
-# into linux-next. Once this commit is present, BROKEN can be removed
config RAMSTER
bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
- depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM && BROKEN
+ depends on (CLEANCACHE || FRONTSWAP) && CONFIGFS_FS=y && !ZCACHE && !XVMALLOC && !HIGHMEM
select LZO_COMPRESS
select LZO_DECOMPRESS
default n
diff --git a/drivers/staging/rts_pstor/ms.c b/drivers/staging/rts_pstor/ms.c
index 66341df..f9a4498 100644
--- a/drivers/staging/rts_pstor/ms.c
+++ b/drivers/staging/rts_pstor/ms.c
@@ -3498,7 +3498,8 @@
log_blk++;
- for (seg_no = 0; seg_no < sizeof(ms_start_idx)/2; seg_no++) {
+ for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
+ seg_no++) {
if (log_blk < ms_start_idx[seg_no+1])
break;
}
diff --git a/drivers/staging/rts_pstor/rtsx.c b/drivers/staging/rts_pstor/rtsx.c
index a7feb3e..1dccd93 100644
--- a/drivers/staging/rts_pstor/rtsx.c
+++ b/drivers/staging/rts_pstor/rtsx.c
@@ -1000,6 +1000,11 @@
rtsx_init_chip(dev->chip);
+ /* set the supported max_lun and max_id for the scsi host
+ * NOTE: the minimal value of max_id is 1 */
+ host->max_id = 1;
+ host->max_lun = dev->chip->max_lun;
+
/* Start up our control thread */
th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
if (IS_ERR(th)) {
diff --git a/drivers/staging/rts_pstor/rtsx_transport.c b/drivers/staging/rts_pstor/rtsx_transport.c
index 4e3d2c1..9b2e5c9 100644
--- a/drivers/staging/rts_pstor/rtsx_transport.c
+++ b/drivers/staging/rts_pstor/rtsx_transport.c
@@ -335,6 +335,7 @@
int sg_cnt, i, resid;
int err = 0;
long timeleft;
+ struct scatterlist *sg_ptr;
u32 val = TRIG_DMA;
if ((sg == NULL) || (num_sg <= 0) || !offset || !index)
@@ -371,7 +372,7 @@
sg_cnt = dma_map_sg(&(rtsx->pci->dev), sg, num_sg, dma_dir);
resid = size;
-
+ sg_ptr = sg;
chip->sgi = 0;
/* Usually the next entry will be @sg@ + 1, but if this sg element
* is part of a chained scatterlist, it could jump to the start of
@@ -379,14 +380,14 @@
* the proper sg
*/
for (i = 0; i < *index; i++)
- sg = sg_next(sg);
+ sg_ptr = sg_next(sg_ptr);
for (i = *index; i < sg_cnt; i++) {
dma_addr_t addr;
unsigned int len;
u8 option;
- addr = sg_dma_address(sg);
- len = sg_dma_len(sg);
+ addr = sg_dma_address(sg_ptr);
+ len = sg_dma_len(sg_ptr);
RTSX_DEBUGP("DMA addr: 0x%x, Len: 0x%x\n",
(unsigned int)addr, len);
@@ -415,7 +416,7 @@
if (!resid)
break;
- sg = sg_next(sg);
+ sg_ptr = sg_next(sg_ptr);
}
RTSX_DEBUGP("SG table count = %d\n", chip->sgi);
diff --git a/drivers/staging/sep/sep_main.c b/drivers/staging/sep/sep_main.c
index ad54c2e..f1701bc 100644
--- a/drivers/staging/sep/sep_main.c
+++ b/drivers/staging/sep/sep_main.c
@@ -3114,7 +3114,7 @@
current->pid);
if (1 == test_bit(SEP_LEGACY_SENDMSG_DONE_OFFSET,
&call_status->status)) {
- dev_warn(&sep->pdev->dev,
+ dev_dbg(&sep->pdev->dev,
"[PID%d] dcb prep needed before send msg\n",
current->pid);
error = -EPROTO;
@@ -3122,9 +3122,9 @@
}
if (!arg) {
- dev_warn(&sep->pdev->dev,
+ dev_dbg(&sep->pdev->dev,
"[PID%d] dcb null arg\n", current->pid);
- error = EINVAL;
+ error = -EINVAL;
goto end_function;
}
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index 7862513..9cf29fc 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -79,10 +79,6 @@
#define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
#define OMAP343X_CONTROL_IVA2_BOOTMOD (OMAP2_CONTROL_GENERAL + 0x0194)
-#define OMAP343X_CTRL_REGADDR(reg) \
- OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
-
-
/* Forward Declarations: */
static int bridge_brd_monitor(struct bridge_dev_context *dev_ctxt);
static int bridge_brd_read(struct bridge_dev_context *dev_ctxt,
@@ -418,19 +414,27 @@
/* Assert RST1 i.e only the RST only for DSP megacell */
if (!status) {
+ /*
+ * XXX: ioremapping MUST be removed once ctrl
+ * function is made available.
+ */
+ void __iomem *ctrl = ioremap(OMAP343X_CTRL_BASE, SZ_4K);
+ if (!ctrl)
+ return -ENOMEM;
+
(*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
OMAP2_RM_RSTCTRL);
/* Mask address with 1K for compatibility */
__raw_writel(dsp_addr & OMAP3_IVA2_BOOTADDR_MASK,
- OMAP343X_CTRL_REGADDR(
- OMAP343X_CONTROL_IVA2_BOOTADDR));
+ ctrl + OMAP343X_CONTROL_IVA2_BOOTADDR);
/*
* Set bootmode to self loop if dsp_debug flag is true
*/
__raw_writel((dsp_debug) ? OMAP3_IVA2_BOOTMOD_IDLE : 0,
- OMAP343X_CTRL_REGADDR(
- OMAP343X_CONTROL_IVA2_BOOTMOD));
+ ctrl + OMAP343X_CONTROL_IVA2_BOOTMOD);
+
+ iounmap(ctrl);
}
}
if (!status) {
diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c
index 70055c8..870f934 100644
--- a/drivers/staging/tidspbridge/core/wdt.c
+++ b/drivers/staging/tidspbridge/core/wdt.c
@@ -53,7 +53,10 @@
int ret = 0;
dsp_wdt.sm_wdt = NULL;
- dsp_wdt.reg_base = OMAP2_L4_IO_ADDRESS(OMAP34XX_WDT3_BASE);
+ dsp_wdt.reg_base = ioremap(OMAP34XX_WDT3_BASE, SZ_4K);
+ if (!dsp_wdt.reg_base)
+ return -ENOMEM;
+
tasklet_init(&dsp_wdt.wdt3_tasklet, dsp_wdt_dpc, 0);
dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
@@ -99,6 +102,9 @@
dsp_wdt.fclk = NULL;
dsp_wdt.iclk = NULL;
dsp_wdt.sm_wdt = NULL;
+
+ if (dsp_wdt.reg_base)
+ iounmap(dsp_wdt.reg_base);
dsp_wdt.reg_base = NULL;
}
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index 9fedc44..573c800 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -35,10 +35,10 @@
static int vector_num;
static int level[PIO2_CARDS_MAX];
static int level_num;
-static const char *variant[PIO2_CARDS_MAX];
+static char *variant[PIO2_CARDS_MAX];
static int variant_num;
-static int loopback;
+static bool loopback;
static int pio2_match(struct vme_dev *);
static int __devinit pio2_probe(struct vme_dev *);
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
index 0ff8d7b..774b0d4 100644
--- a/drivers/staging/vt6655/key.c
+++ b/drivers/staging/vt6655/key.c
@@ -655,6 +655,9 @@
return (false);
}
+ if (uKeyLength > MAX_KEY_LEN)
+ return false;
+
pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = true;
for(ii=0;ii<ETH_ALEN;ii++)
pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF;
diff --git a/drivers/staging/vt6656/ioctl.c b/drivers/staging/vt6656/ioctl.c
index 1463d76..d59456c 100644
--- a/drivers/staging/vt6656/ioctl.c
+++ b/drivers/staging/vt6656/ioctl.c
@@ -565,7 +565,7 @@
result = -ENOMEM;
break;
}
- pNodeList = (PSNodeList)kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
+ pNodeList = kmalloc(sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)), (int)GFP_ATOMIC);
if (pNodeList == NULL) {
result = -ENOMEM;
break;
@@ -601,6 +601,7 @@
}
}
if (copy_to_user(pReq->data, pNodeList, sizeof(SNodeList) + (sNodeList.uItem * sizeof(SNodeItem)))) {
+ kfree(pNodeList);
result = -EFAULT;
break;
}
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
index 27bb523..ee62a06 100644
--- a/drivers/staging/vt6656/key.c
+++ b/drivers/staging/vt6656/key.c
@@ -684,6 +684,9 @@
return (FALSE);
}
+ if (uKeyLength > MAX_KEY_LEN)
+ return false;
+
pTable->KeyTable[MAX_KEY_TABLE-1].bInUse = TRUE;
for (ii = 0; ii < ETH_ALEN; ii++)
pTable->KeyTable[MAX_KEY_TABLE-1].abyBSSID[ii] = 0xFF;
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index 94d5c35..3650bbf 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -61,7 +61,7 @@
}
temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
/* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
- if ((temp & 0x88) == 0x80)
+ if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
data = 0; /* DDR */
else
data = 1; /* DDRII */
diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c
index 2919924..60d4adf 100644
--- a/drivers/staging/xgifb/vb_setmode.c
+++ b/drivers/staging/xgifb/vb_setmode.c
@@ -152,6 +152,7 @@
pVBInfo->pXGINew_CR97 = &XG20_CR97;
if (ChipType == XG27) {
+ unsigned char temp;
pVBInfo->MCLKData
= (struct SiS_MCLKData *) XGI27New_MCLKData;
pVBInfo->CR40 = XGI27_cr41;
@@ -162,7 +163,13 @@
pVBInfo->pCRDE = XG27_CRDE;
pVBInfo->pSR40 = &XG27_SR40;
pVBInfo->pSR41 = &XG27_SR41;
+ pVBInfo->SR15 = XG27_SR13;
+ /*Z11m DDR*/
+ temp = xgifb_reg_get(pVBInfo->P3c4, 0x3B);
+ /* SR3B[7][3]MAA15 MAA11 (Power on Trapping) */
+ if (((temp & 0x88) == 0x80) || ((temp & 0x88) == 0x08))
+ pVBInfo->pXGINew_CR97 = &Z11m_CR97;
}
if (ChipType >= XG20) {
diff --git a/drivers/staging/xgifb/vb_table.h b/drivers/staging/xgifb/vb_table.h
index dddf261..e8d6f67 100644
--- a/drivers/staging/xgifb/vb_table.h
+++ b/drivers/staging/xgifb/vb_table.h
@@ -33,6 +33,13 @@
{0x5c, 0x23, 0x01, 166}
};
+static unsigned char XG27_SR13[4][8] = {
+ {0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
+ {0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
+ {0x32, 0x32, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR18 */
+ {0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00} /* SR1B */
+};
+
static unsigned char XGI340_SR13[4][8] = {
{0x35, 0x45, 0xb1, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR13 */
{0x41, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00}, /* SR14 */
@@ -71,7 +78,7 @@
{0x20, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0 CR41 */
{0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1 CR8A */
{0xC4, 0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2 CR8B */
- {0xB5, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7],
+ {0xB3, 0x13, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3 CR40[7],
CR99[2:0],
CR45[3:0]*/
{0xf0, 0xf5, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 4 CR59 */
@@ -2803,6 +2810,8 @@
static unsigned char XG27_SR40 = 0x04 ;
static unsigned char XG27_SR41 = 0x00 ;
+static unsigned char Z11m_CR97 = 0x80 ;
+
static struct XGI330_VCLKDataStruct XGI_VCLKData[] = {
/* SR2B,SR2C,SR2D */
{0x1B, 0xE1, 25}, /* 00 (25.175MHz) */
diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig
index 3ed2c8f..7048e01 100644
--- a/drivers/staging/zcache/Kconfig
+++ b/drivers/staging/zcache/Kconfig
@@ -2,7 +2,7 @@
bool "Dynamic compression of swap pages and clean pagecache pages"
# X86 dependency is because zsmalloc uses non-portable pte/tlb
# functions
- depends on (CLEANCACHE || FRONTSWAP) && CRYPTO && X86
+ depends on (CLEANCACHE || FRONTSWAP) && CRYPTO=y && X86
select ZSMALLOC
select CRYPTO_LZO
default n
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index 09caa4f..917461c 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -267,33 +267,39 @@
return off + obj_idx * class_size;
}
+static void reset_page(struct page *page)
+{
+ clear_bit(PG_private, &page->flags);
+ clear_bit(PG_private_2, &page->flags);
+ set_page_private(page, 0);
+ page->mapping = NULL;
+ page->freelist = NULL;
+ reset_page_mapcount(page);
+}
+
static void free_zspage(struct page *first_page)
{
- struct page *nextp, *tmp;
+ struct page *nextp, *tmp, *head_extra;
BUG_ON(!is_first_page(first_page));
BUG_ON(first_page->inuse);
- nextp = (struct page *)page_private(first_page);
+ head_extra = (struct page *)page_private(first_page);
- clear_bit(PG_private, &first_page->flags);
- clear_bit(PG_private_2, &first_page->flags);
- set_page_private(first_page, 0);
- first_page->mapping = NULL;
- first_page->freelist = NULL;
- reset_page_mapcount(first_page);
+ reset_page(first_page);
__free_page(first_page);
/* zspage with only 1 system page */
- if (!nextp)
+ if (!head_extra)
return;
- list_for_each_entry_safe(nextp, tmp, &nextp->lru, lru) {
+ list_for_each_entry_safe(nextp, tmp, &head_extra->lru, lru) {
list_del(&nextp->lru);
- clear_bit(PG_private_2, &nextp->flags);
- nextp->index = 0;
+ reset_page(nextp);
__free_page(nextp);
}
+ reset_page(head_extra);
+ __free_page(head_extra);
}
/* Initialize a newly allocated zspage */
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index 8306579..c5eb3c3 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -122,6 +122,7 @@
/* Local sense buffer */
unsigned char ft_sense_buffer[TRANSPORT_SENSE_BUFFER];
u32 was_ddp_setup:1; /* Set only if ddp is setup */
+ u32 aborted:1; /* Set if aborted by reset or timeout */
struct scatterlist *sg; /* Set only if DDP is setup */
u32 sg_cnt; /* No. of item in scatterlist */
};
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index 62dec97..a375f25 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -121,6 +121,8 @@
struct fc_exch *ep;
size_t len;
+ if (cmd->aborted)
+ return 0;
ft_dump_cmd(cmd, __func__);
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
@@ -187,6 +189,8 @@
ft_dump_cmd(cmd, __func__);
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
fp = fc_frame_alloc(lport, sizeof(*txrdy));
@@ -252,10 +256,10 @@
struct ft_cmd *cmd = arg;
struct fc_frame_header *fh;
- if (IS_ERR(fp)) {
+ if (unlikely(IS_ERR(fp))) {
/* XXX need to find cmd if queued */
cmd->seq = NULL;
- transport_generic_free_cmd(&cmd->se_cmd, 0);
+ cmd->aborted = true;
return;
}
@@ -399,6 +403,8 @@
struct se_tmr_req *tmr = se_cmd->se_tmr_req;
enum fcp_resp_rsp_codes code;
+ if (cmd->aborted)
+ return 0;
switch (tmr->response) {
case TMR_FUNCTION_COMPLETE:
code = FCP_TMF_CMPL;
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index f357039..2948dc9 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -300,6 +300,7 @@
{
struct ft_lport_acl *lacl;
struct ft_tpg *tpg;
+ struct workqueue_struct *wq;
unsigned long index;
int ret;
@@ -321,18 +322,20 @@
tpg->lport_acl = lacl;
INIT_LIST_HEAD(&tpg->lun_list);
- ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
- tpg, TRANSPORT_TPG_TYPE_NORMAL);
- if (ret < 0) {
+ wq = alloc_workqueue("tcm_fc", 0, 1);
+ if (!wq) {
kfree(tpg);
return NULL;
}
- tpg->workqueue = alloc_workqueue("tcm_fc", 0, 1);
- if (!tpg->workqueue) {
+ ret = core_tpg_register(&ft_configfs->tf_ops, wwn, &tpg->se_tpg,
+ tpg, TRANSPORT_TPG_TYPE_NORMAL);
+ if (ret < 0) {
+ destroy_workqueue(wq);
kfree(tpg);
return NULL;
}
+ tpg->workqueue = wq;
mutex_lock(&ft_lport_lock);
list_add_tail(&tpg->list, &lacl->tpg_list);
diff --git a/drivers/target/tcm_fc/tfc_io.c b/drivers/target/tcm_fc/tfc_io.c
index 2b693ee..dc7c0db 100644
--- a/drivers/target/tcm_fc/tfc_io.c
+++ b/drivers/target/tcm_fc/tfc_io.c
@@ -81,6 +81,8 @@
void *from;
void *to = NULL;
+ if (cmd->aborted)
+ return 0;
ep = fc_seq_exch(cmd->seq);
lport = ep->lp;
cmd->seq = lport->tt.seq_start_next(cmd->seq);
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 24145c3..6cc4358 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1073,8 +1073,10 @@
(new_serial.close_delay != port->close_delay) ||
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
- (port->flags & ~ASYNC_USR_MASK)))
+ (port->flags & ~ASYNC_USR_MASK))) {
+ tty_unlock();
return -EPERM;
+ }
port->flags = ((port->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
state->custom_divisor = new_serial.custom_divisor;
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 5b149b4..5c27f7e 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -1572,13 +1572,11 @@
do {
struct uart_8250_port *up;
struct uart_port *port;
- bool skip;
up = list_entry(l, struct uart_8250_port, list);
port = &up->port;
- skip = pass_counter && up->port.flags & UPF_IIR_ONCE;
- if (!skip && port->handle_irq(port)) {
+ if (port->handle_irq(port)) {
handled = 1;
end = NULL;
} else if (end == NULL)
@@ -2037,10 +2035,12 @@
spin_unlock_irqrestore(&port->lock, flags);
/*
- * If the interrupt is not reasserted, setup a timer to
- * kick the UART on a regular basis.
+ * If the interrupt is not reasserted, or we otherwise
+ * don't trust the iir, setup a timer to kick the UART
+ * on a regular basis.
*/
- if (!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) {
+ if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
+ up->port.flags & UPF_BUG_THRE) {
up->bugs |= UART_BUG_THRE;
pr_debug("ttyS%d - using backup timer\n",
serial_index(port));
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index da2b0b0..858dca8 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1096,7 +1096,7 @@
const struct pciserial_board *board,
struct uart_port *port, int idx)
{
- port->flags |= UPF_IIR_ONCE;
+ port->flags |= UPF_BUG_THRE;
return skip_tx_en_setup(priv, board, port, idx);
}
@@ -1118,18 +1118,6 @@
return pci_default_setup(priv, board, port, idx);
}
-static int try_enable_msi(struct pci_dev *dev)
-{
- /* use msi if available, but fallback to legacy otherwise */
- pci_enable_msi(dev);
- return 0;
-}
-
-static void disable_msi(struct pci_dev *dev)
-{
- pci_disable_msi(dev);
-}
-
#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
#define PCI_DEVICE_ID_OCTPRO 0x0001
@@ -1249,9 +1237,7 @@
.device = PCI_DEVICE_ID_INTEL_PATSBURG_KT,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
- .init = try_enable_msi,
.setup = kt_serial_setup,
- .exit = disable_msi,
},
/*
* ITE
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 665beb6..070b442 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1041,7 +1041,7 @@
config SERIAL_OMAP_CONSOLE
bool "Console on OMAP serial port"
- depends on SERIAL_OMAP
+ depends on SERIAL_OMAP=y
select SERIAL_CORE_CONSOLE
help
Select this option if you would like to use omap serial port as
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index e790375..1f03309 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -556,7 +556,7 @@
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem)
port->mapbase = res_mem->start;
- else if (platp->mapbase)
+ else if (platp)
port->mapbase = platp->mapbase;
else
return -EINVAL;
@@ -564,7 +564,7 @@
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res_irq)
port->irq = res_irq->start;
- else if (platp->irq)
+ else if (platp)
port->irq = platp->irq;
/* Check platform data first so we can override device node data */
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 0c65c9e..3d569cd 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1946,10 +1946,6 @@
goto unmap;
}
- /* Ensure interrupts from this UART are masked and cleared */
- writew(0, uap->port.membase + UART011_IMSC);
- writew(0xffff, uap->port.membase + UART011_ICR);
-
uap->vendor = vendor;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
@@ -1967,6 +1963,10 @@
uap->port.line = i;
pl011_dma_probe(uap);
+ /* Ensure interrupts from this UART are masked and cleared */
+ writew(0, uap->port.membase + UART011_IMSC);
+ writew(0xffff, uap->port.membase + UART011_ICR);
+
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
amba_ports[i] = uap;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index f9a6be7..3d7e1ee 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -389,6 +389,8 @@
{
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */
+ UART_PUT_CR(port, ATMEL_US_RXEN);
+
if (atmel_use_dma_rx(port)) {
/* enable PDC controller */
UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
@@ -404,6 +406,8 @@
*/
static void atmel_stop_rx(struct uart_port *port)
{
+ UART_PUT_CR(port, ATMEL_US_RXDIS);
+
if (atmel_use_dma_rx(port)) {
/* disable PDC receive */
UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index e6c3dbd..836fe273 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -154,10 +154,9 @@
port->x_char = 0;
return IRQ_HANDLED;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port);
- return IRQ_HANDLED;
- }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ goto disable_tx_irq;
count = port->fifosize >> 1;
do {
@@ -171,8 +170,11 @@
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port);
+ if (uart_circ_empty(xmit)) {
+ disable_tx_irq:
+ disable_irq_nosync(TX_IRQ(port));
+ tx_enabled(port) = 0;
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/mfd.c b/drivers/tty/serial/mfd.c
index a9234ba8..c4b50af 100644
--- a/drivers/tty/serial/mfd.c
+++ b/drivers/tty/serial/mfd.c
@@ -127,11 +127,6 @@
#define HSU_REGS_BUFSIZE 1024
-static int hsu_show_regs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
static ssize_t port_show_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -231,14 +226,14 @@
static const struct file_operations port_regs_ops = {
.owner = THIS_MODULE,
- .open = hsu_show_regs_open,
+ .open = simple_open,
.read = port_show_regs,
.llseek = default_llseek,
};
static const struct file_operations dma_regs_ops = {
.owner = THIS_MODULE,
- .open = hsu_show_regs_open,
+ .open = simple_open,
.read = dma_show_regs,
.llseek = default_llseek,
};
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 0121486..d00b38e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1381,29 +1381,24 @@
return -ENODEV;
}
- if (!request_mem_region(mem->start, resource_size(mem),
+ if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
pdev->dev.driver->name)) {
dev_err(&pdev->dev, "memory region already claimed\n");
return -EBUSY;
}
dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
- if (!dma_rx) {
- ret = -EINVAL;
- goto err;
- }
+ if (!dma_rx)
+ return -ENXIO;
dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
- if (!dma_tx) {
- ret = -EINVAL;
- goto err;
- }
+ if (!dma_tx)
+ return -ENXIO;
- up = kzalloc(sizeof(*up), GFP_KERNEL);
- if (up == NULL) {
- ret = -ENOMEM;
- goto do_release_region;
- }
+ up = devm_kzalloc(&pdev->dev, sizeof(*up), GFP_KERNEL);
+ if (!up)
+ return -ENOMEM;
+
up->pdev = pdev;
up->port.dev = &pdev->dev;
up->port.type = PORT_OMAP;
@@ -1423,16 +1418,17 @@
dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n",
up->port.line);
ret = -ENODEV;
- goto err;
+ goto err_port_line;
}
sprintf(up->name, "OMAP UART%d", up->port.line);
up->port.mapbase = mem->start;
- up->port.membase = ioremap(mem->start, resource_size(mem));
+ up->port.membase = devm_ioremap(&pdev->dev, mem->start,
+ resource_size(mem));
if (!up->port.membase) {
dev_err(&pdev->dev, "can't ioremap UART\n");
ret = -ENOMEM;
- goto err;
+ goto err_ioremap;
}
up->port.flags = omap_up_info->flags;
@@ -1478,16 +1474,19 @@
ret = uart_add_one_port(&serial_omap_reg, &up->port);
if (ret != 0)
- goto do_release_region;
+ goto err_add_port;
pm_runtime_put(&pdev->dev);
platform_set_drvdata(pdev, up);
return 0;
-err:
+
+err_add_port:
+ pm_runtime_put(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+err_ioremap:
+err_port_line:
dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
pdev->id, __func__, ret);
-do_release_region:
- release_mem_region(mem->start, resource_size(mem));
return ret;
}
@@ -1499,8 +1498,6 @@
pm_runtime_disable(&up->pdev->dev);
uart_remove_one_port(&serial_omap_reg, &up->port);
pm_qos_remove_request(&up->pm_qos_request);
-
- kfree(up);
}
platform_set_drvdata(dev, NULL);
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index e825460..c2816f4 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -210,6 +210,7 @@
#define CMITC_UARTCLK 192000000 /* 192.0000 MHz */
#define FRI2_64_UARTCLK 64000000 /* 64.0000 MHz */
#define FRI2_48_UARTCLK 48000000 /* 48.0000 MHz */
+#define NTC1_UARTCLK 64000000 /* 64.0000 MHz */
struct pch_uart_buffer {
unsigned char *buf;
@@ -304,11 +305,7 @@
#ifdef CONFIG_DEBUG_FS
#define PCH_REGS_BUFSIZE 1024
-static int pch_show_regs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
+
static ssize_t port_show_regs(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -362,7 +359,7 @@
static const struct file_operations port_regs_ops = {
.owner = THIS_MODULE,
- .open = pch_show_regs_open,
+ .open = simple_open,
.read = port_show_regs,
.llseek = default_llseek,
};
@@ -388,6 +385,12 @@
if (cmp && strstr(cmp, "Fish River Island II"))
return FRI2_48_UARTCLK;
+ /* Kontron COMe-mTT10 (nanoETXexpress-TT) */
+ cmp = dmi_get_system_info(DMI_BOARD_NAME);
+ if (cmp && (strstr(cmp, "COMe-mTT") ||
+ strstr(cmp, "nanoETXexpress-TT")))
+ return NTC1_UARTCLK;
+
return DEFAULT_UARTCLK;
}
@@ -1444,9 +1447,11 @@
__func__);
return -EOPNOTSUPP;
#endif
- priv->use_dma = 1;
priv->use_dma_flag = 1;
dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
+ if (!priv->use_dma)
+ pch_request_dma(port);
+ priv->use_dma = 1;
}
return 0;
@@ -1655,6 +1660,7 @@
}
pci_enable_msi(pdev);
+ pci_set_master(pdev);
iobase = pci_resource_start(pdev, 0);
mapbase = pci_resource_start(pdev, 1);
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 08ebe90..654755a 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -469,7 +469,7 @@
tty = NULL;
if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
if (!ZS_IS_OPEN(uap_a)) {
- pmz_debug("ChanA interrupt while open !\n");
+ pmz_debug("ChanA interrupt while not open !\n");
goto skip_a;
}
write_zsreg(uap_a, R0, RES_H_IUS);
@@ -493,8 +493,8 @@
spin_lock(&uap_b->port.lock);
tty = NULL;
if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
- if (!ZS_IS_OPEN(uap_a)) {
- pmz_debug("ChanB interrupt while open !\n");
+ if (!ZS_IS_OPEN(uap_b)) {
+ pmz_debug("ChanB interrupt while not open !\n");
goto skip_b;
}
write_zsreg(uap_b, R0, RES_H_IUS);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index de249d2..d8b0aee 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -982,6 +982,7 @@
ucon &= ucon_mask;
wr_regl(port, S3C2410_UCON, ucon | cfg->ucon);
+ wr_regl(port, S3C2410_ULCON, cfg->ulcon);
/* reset both fifos */
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index bf461cf..3158e17 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -355,9 +355,6 @@
WARN(1, "Invalid register access\n");
}
-#define sci_in(up, offset) (up->serial_in(up, offset))
-#define sci_out(up, offset, value) (up->serial_out(up, offset, value))
-
static int sci_probe_regmap(struct plat_sci_port *cfg)
{
switch (cfg->type) {
@@ -422,9 +419,9 @@
int c;
do {
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
if (status & SCxSR_ERRORS(port)) {
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
continue;
}
break;
@@ -433,11 +430,11 @@
if (!(status & SCxSR_RDxF(port)))
return NO_POLL_CHAR;
- c = sci_in(port, SCxRDR);
+ c = serial_port_in(port, SCxRDR);
/* Dummy read */
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ serial_port_in(port, SCxSR);
+ serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
return c;
}
@@ -448,11 +445,11 @@
unsigned short status;
do {
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
} while (!(status & SCxSR_TDxE(port)));
- sci_out(port, SCxTDR, c);
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
+ serial_port_out(port, SCxTDR, c);
+ serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port));
}
#endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */
@@ -480,10 +477,10 @@
((!(cflag & CRTSCTS)))) {
unsigned short status;
- status = sci_in(port, SCSPTR);
+ status = serial_port_in(port, SCSPTR);
status &= ~SCSPTR_CTSIO;
status |= SCSPTR_RTSIO;
- sci_out(port, SCSPTR, status); /* Set RTS = 1 */
+ serial_port_out(port, SCSPTR, status); /* Set RTS = 1 */
}
}
@@ -493,13 +490,13 @@
reg = sci_getreg(port, SCTFDR);
if (reg->size)
- return sci_in(port, SCTFDR) & 0xff;
+ return serial_port_in(port, SCTFDR) & 0xff;
reg = sci_getreg(port, SCFDR);
if (reg->size)
- return sci_in(port, SCFDR) >> 8;
+ return serial_port_in(port, SCFDR) >> 8;
- return !(sci_in(port, SCxSR) & SCI_TDRE);
+ return !(serial_port_in(port, SCxSR) & SCI_TDRE);
}
static int sci_txroom(struct uart_port *port)
@@ -513,13 +510,13 @@
reg = sci_getreg(port, SCRFDR);
if (reg->size)
- return sci_in(port, SCRFDR) & 0xff;
+ return serial_port_in(port, SCRFDR) & 0xff;
reg = sci_getreg(port, SCFDR);
if (reg->size)
- return sci_in(port, SCFDR) & ((port->fifosize << 1) - 1);
+ return serial_port_in(port, SCFDR) & ((port->fifosize << 1) - 1);
- return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
+ return (serial_port_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
}
/*
@@ -547,14 +544,14 @@
unsigned short ctrl;
int count;
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
if (!(status & SCxSR_TDxE(port))) {
- ctrl = sci_in(port, SCSCR);
+ ctrl = serial_port_in(port, SCSCR);
if (uart_circ_empty(xmit))
ctrl &= ~SCSCR_TIE;
else
ctrl |= SCSCR_TIE;
- sci_out(port, SCSCR, ctrl);
+ serial_port_out(port, SCSCR, ctrl);
return;
}
@@ -573,27 +570,27 @@
break;
}
- sci_out(port, SCxTDR, c);
+ serial_port_out(port, SCxTDR, c);
port->icount.tx++;
} while (--count > 0);
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (uart_circ_empty(xmit)) {
sci_stop_tx(port);
} else {
- ctrl = sci_in(port, SCSCR);
+ ctrl = serial_port_in(port, SCSCR);
if (port->type != PORT_SCI) {
- sci_in(port, SCxSR); /* Dummy read */
- sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
+ serial_port_in(port, SCxSR); /* Dummy read */
+ serial_port_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
}
ctrl |= SCSCR_TIE;
- sci_out(port, SCSCR, ctrl);
+ serial_port_out(port, SCSCR, ctrl);
}
}
@@ -608,7 +605,7 @@
unsigned short status;
unsigned char flag;
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
if (!(status & SCxSR_RDxF(port)))
return;
@@ -621,7 +618,7 @@
break;
if (port->type == PORT_SCI) {
- char c = sci_in(port, SCxRDR);
+ char c = serial_port_in(port, SCxRDR);
if (uart_handle_sysrq_char(port, c) ||
sci_port->break_flag)
count = 0;
@@ -629,9 +626,9 @@
tty_insert_flip_char(tty, c, TTY_NORMAL);
} else {
for (i = 0; i < count; i++) {
- char c = sci_in(port, SCxRDR);
+ char c = serial_port_in(port, SCxRDR);
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
#if defined(CONFIG_CPU_SH3)
/* Skip "chars" during break */
if (sci_port->break_flag) {
@@ -672,8 +669,8 @@
}
}
- sci_in(port, SCxSR); /* dummy read */
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ serial_port_in(port, SCxSR); /* dummy read */
+ serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
copied += count;
port->icount.rx += count;
@@ -683,8 +680,8 @@
/* Tell the rest of the system the news. New characters! */
tty_flip_buffer_push(tty);
} else {
- sci_in(port, SCxSR); /* dummy read */
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ serial_port_in(port, SCxSR); /* dummy read */
+ serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
}
}
@@ -726,7 +723,7 @@
static int sci_handle_errors(struct uart_port *port)
{
int copied = 0;
- unsigned short status = sci_in(port, SCxSR);
+ unsigned short status = serial_port_in(port, SCxSR);
struct tty_struct *tty = port->state->port.tty;
struct sci_port *s = to_sci_port(port);
@@ -804,8 +801,8 @@
if (!reg->size)
return 0;
- if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
- sci_out(port, SCLSR, 0);
+ if ((serial_port_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
+ serial_port_out(port, SCLSR, 0);
port->icount.overrun++;
@@ -822,7 +819,7 @@
static int sci_handle_breaks(struct uart_port *port)
{
int copied = 0;
- unsigned short status = sci_in(port, SCxSR);
+ unsigned short status = serial_port_in(port, SCxSR);
struct tty_struct *tty = port->state->port.tty;
struct sci_port *s = to_sci_port(port);
@@ -859,8 +856,8 @@
struct sci_port *s = to_sci_port(port);
if (s->chan_rx) {
- u16 scr = sci_in(port, SCSCR);
- u16 ssr = sci_in(port, SCxSR);
+ u16 scr = serial_port_in(port, SCSCR);
+ u16 ssr = serial_port_in(port, SCxSR);
/* Disable future Rx interrupts */
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
@@ -869,9 +866,9 @@
} else {
scr &= ~SCSCR_RIE;
}
- sci_out(port, SCSCR, scr);
+ serial_port_out(port, SCSCR, scr);
/* Clear current interrupt */
- sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+ serial_port_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n",
jiffies, s->rx_timeout);
mod_timer(&s->rx_timer, jiffies + s->rx_timeout);
@@ -909,15 +906,15 @@
if (port->type == PORT_SCI) {
if (sci_handle_errors(port)) {
/* discard character in rx buffer */
- sci_in(port, SCxSR);
- sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
+ serial_port_in(port, SCxSR);
+ serial_port_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
}
} else {
sci_handle_fifo_overrun(port);
sci_rx_interrupt(irq, ptr);
}
- sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
+ serial_port_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
/* Kick the transmission */
sci_tx_interrupt(irq, ptr);
@@ -931,7 +928,7 @@
/* Handle BREAKs */
sci_handle_breaks(port);
- sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
+ serial_port_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
return IRQ_HANDLED;
}
@@ -955,8 +952,8 @@
struct sci_port *s = to_sci_port(port);
irqreturn_t ret = IRQ_NONE;
- ssr_status = sci_in(port, SCxSR);
- scr_status = sci_in(port, SCSCR);
+ ssr_status = serial_port_in(port, SCxSR);
+ scr_status = serial_port_in(port, SCSCR);
err_enabled = scr_status & port_rx_irq_mask(port);
/* Tx Interrupt */
@@ -1170,7 +1167,7 @@
static unsigned int sci_tx_empty(struct uart_port *port)
{
- unsigned short status = sci_in(port, SCxSR);
+ unsigned short status = serial_port_in(port, SCxSR);
unsigned short in_tx_fifo = sci_txfill(port);
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
@@ -1198,7 +1195,7 @@
*/
reg = sci_getreg(port, SCFCR);
if (reg->size)
- sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
+ serial_port_out(port, SCFCR, serial_port_in(port, SCFCR) | 1);
}
}
@@ -1240,8 +1237,8 @@
} else {
s->cookie_tx = -EINVAL;
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ u16 ctrl = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, ctrl & ~SCSCR_TIE);
}
}
@@ -1494,13 +1491,13 @@
#ifdef CONFIG_SERIAL_SH_SCI_DMA
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 new, scr = sci_in(port, SCSCR);
+ u16 new, scr = serial_port_in(port, SCSCR);
if (s->chan_tx)
new = scr | 0x8000;
else
new = scr & ~0x8000;
if (new != scr)
- sci_out(port, SCSCR, new);
+ serial_port_out(port, SCSCR, new);
}
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
@@ -1512,8 +1509,8 @@
if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl | SCSCR_TIE);
+ ctrl = serial_port_in(port, SCSCR);
+ serial_port_out(port, SCSCR, ctrl | SCSCR_TIE);
}
}
@@ -1522,40 +1519,40 @@
unsigned short ctrl;
/* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
+ ctrl = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x8000;
ctrl &= ~SCSCR_TIE;
- sci_out(port, SCSCR, ctrl);
+ serial_port_out(port, SCSCR, ctrl);
}
static void sci_start_rx(struct uart_port *port)
{
unsigned short ctrl;
- ctrl = sci_in(port, SCSCR) | port_rx_irq_mask(port);
+ ctrl = serial_port_in(port, SCSCR) | port_rx_irq_mask(port);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000;
- sci_out(port, SCSCR, ctrl);
+ serial_port_out(port, SCSCR, ctrl);
}
static void sci_stop_rx(struct uart_port *port)
{
unsigned short ctrl;
- ctrl = sci_in(port, SCSCR);
+ ctrl = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)
ctrl &= ~0x4000;
ctrl &= ~port_rx_irq_mask(port);
- sci_out(port, SCSCR, ctrl);
+ serial_port_out(port, SCSCR, ctrl);
}
static void sci_enable_ms(struct uart_port *port)
@@ -1589,13 +1586,13 @@
{
struct sci_port *s = (struct sci_port *)arg;
struct uart_port *port = &s->port;
- u16 scr = sci_in(port, SCSCR);
+ u16 scr = serial_port_in(port, SCSCR);
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
scr &= ~0x4000;
enable_irq(s->cfg->irqs[1]);
}
- sci_out(port, SCSCR, scr | SCSCR_RIE);
+ serial_port_out(port, SCSCR, scr | SCSCR_RIE);
dev_dbg(port->dev, "DMA Rx timed out\n");
schedule_work(&s->work_rx);
}
@@ -1776,14 +1773,14 @@
unsigned int status;
do {
- status = sci_in(port, SCxSR);
+ status = serial_port_in(port, SCxSR);
} while (!(status & SCxSR_TEND(port)));
- sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
+ serial_port_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
reg = sci_getreg(port, SCFCR);
if (reg->size)
- sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
+ serial_port_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
}
static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
@@ -1812,7 +1809,7 @@
sci_reset(port);
- smr_val = sci_in(port, SCSMR) & 3;
+ smr_val = serial_port_in(port, SCSMR) & 3;
if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= 0x40;
@@ -1825,19 +1822,19 @@
uart_update_timeout(port, termios->c_cflag, baud);
- sci_out(port, SCSMR, smr_val);
+ serial_port_out(port, SCSMR, smr_val);
dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
s->cfg->scscr);
if (t > 0) {
if (t >= 256) {
- sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
+ serial_port_out(port, SCSMR, (serial_port_in(port, SCSMR) & ~3) | 1);
t >>= 2;
} else
- sci_out(port, SCSMR, sci_in(port, SCSMR) & ~3);
+ serial_port_out(port, SCSMR, serial_port_in(port, SCSMR) & ~3);
- sci_out(port, SCBRR, t);
+ serial_port_out(port, SCBRR, t);
udelay((1000000+(baud-1)) / baud); /* Wait one bit interval */
}
@@ -1845,7 +1842,7 @@
reg = sci_getreg(port, SCFCR);
if (reg->size) {
- unsigned short ctrl = sci_in(port, SCFCR);
+ unsigned short ctrl = serial_port_in(port, SCFCR);
if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
if (termios->c_cflag & CRTSCTS)
@@ -1861,10 +1858,10 @@
*/
ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
- sci_out(port, SCFCR, ctrl);
+ serial_port_out(port, SCFCR, ctrl);
}
- sci_out(port, SCSCR, s->cfg->scscr);
+ serial_port_out(port, SCSCR, s->cfg->scscr);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
/*
@@ -2166,7 +2163,7 @@
/* wait until fifo is empty and last bit has been transmitted */
bits = SCxSR_TDxE(port) | SCxSR_TEND(port);
- while ((sci_in(port, SCxSR) & bits) != bits)
+ while ((serial_port_in(port, SCxSR) & bits) != bits)
cpu_relax();
sci_port_disable(sci_port);
@@ -2260,12 +2257,12 @@
if (uart_console(port)) {
struct plat_sci_reg *reg;
- sci_port->saved_smr = sci_in(port, SCSMR);
- sci_port->saved_brr = sci_in(port, SCBRR);
+ sci_port->saved_smr = serial_port_in(port, SCSMR);
+ sci_port->saved_brr = serial_port_in(port, SCBRR);
reg = sci_getreg(port, SCFCR);
if (reg->size)
- sci_port->saved_fcr = sci_in(port, SCFCR);
+ sci_port->saved_fcr = serial_port_in(port, SCFCR);
else
sci_port->saved_fcr = 0;
}
@@ -2279,13 +2276,13 @@
if (uart_console(port)) {
sci_reset(port);
- sci_out(port, SCSMR, sci_port->saved_smr);
- sci_out(port, SCBRR, sci_port->saved_brr);
+ serial_port_out(port, SCSMR, sci_port->saved_smr);
+ serial_port_out(port, SCBRR, sci_port->saved_brr);
if (sci_port->saved_fcr)
- sci_out(port, SCFCR, sci_port->saved_fcr);
+ serial_port_out(port, SCFCR, sci_port->saved_fcr);
- sci_out(port, SCSCR, sci_port->cfg->scscr);
+ serial_port_out(port, SCSCR, sci_port->cfg->scscr);
}
return 0;
}
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index a1a2d36..4c22a15 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -20,10 +20,10 @@
defined(CONFIG_ARCH_SH7372) || \
defined(CONFIG_ARCH_R8A7740)
-# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
-# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
-# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
-# define SCxSR_BREAK_CLEAR(port) (sci_in(port, SCxSR) & 0xffe3)
+# define SCxSR_RDxF_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfffc)
+# define SCxSR_ERROR_CLEAR(port) (serial_port_in(port, SCxSR) & 0xfd73)
+# define SCxSR_TDxE_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffdf)
+# define SCxSR_BREAK_CLEAR(port) (serial_port_in(port, SCxSR) & 0xffe3)
#else
# define SCxSR_RDxF_CLEAR(port) (((port)->type == PORT_SCI) ? 0xbc : 0x00fc)
# define SCxSR_ERROR_CLEAR(port) (((port)->type == PORT_SCI) ? 0xc4 : 0x0073)
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index b3b70b0..babd947 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1581,7 +1581,7 @@
if (err)
goto out_unregister_uart;
- if (!zilog_irq) {
+ if (zilog_irq) {
struct uart_sunzilog_port *up = sunzilog_irq_chain;
err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
"zs", sunzilog_irq_chain);
@@ -1622,7 +1622,7 @@
{
platform_driver_unregister(&zs_driver);
- if (!zilog_irq) {
+ if (zilog_irq) {
struct uart_sunzilog_port *up = sunzilog_irq_chain;
/* Disable Interrupts */
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 136e86f..05728894 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -327,7 +327,7 @@
if (is_global_init(p))
continue;
- force_sig(sig, p);
+ do_send_sig_info(sig, SEND_SIG_FORCED, p, true);
}
read_unlock(&tasklist_lock);
}
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 86dd1e3..29ca20d 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1085,15 +1085,21 @@
*
* Handle console start. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
+ *
+ * FIXME: We eventually need to hold the kbd lock here to protect
+ * the LED updating. We can't do it yet because fn_hold calls stop_tty
+ * and start_tty under the kbd_event_lock, while normal tty paths
+ * don't hold the lock. We probably need to split out an LED lock
+ * but not during an -rc release!
*/
void vt_kbd_con_start(int console)
{
struct kbd_struct * kbd = kbd_table + console;
- unsigned long flags;
- spin_lock_irqsave(&kbd_event_lock, flags);
+/* unsigned long flags; */
+/* spin_lock_irqsave(&kbd_event_lock, flags); */
clr_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
}
/**
@@ -1102,22 +1108,28 @@
*
* Handle console stop. This is a wrapper for the VT layer
* so that we can keep kbd knowledge internal
+ *
+ * FIXME: We eventually need to hold the kbd lock here to protect
+ * the LED updating. We can't do it yet because fn_hold calls stop_tty
+ * and start_tty under the kbd_event_lock, while normal tty paths
+ * don't hold the lock. We probably need to split out an LED lock
+ * but not during an -rc release!
*/
void vt_kbd_con_stop(int console)
{
struct kbd_struct * kbd = kbd_table + console;
- unsigned long flags;
- spin_lock_irqsave(&kbd_event_lock, flags);
+/* unsigned long flags; */
+/* spin_lock_irqsave(&kbd_event_lock, flags); */
set_vc_kbd_led(kbd, VC_SCROLLOCK);
set_leds();
- spin_unlock_irqrestore(&kbd_event_lock, flags);
+/* spin_unlock_irqrestore(&kbd_event_lock, flags); */
}
/*
* This is the tasklet that updates LED state on all keyboards
* attached to the box. The reason we use tasklet is that we
* need to handle the scenario when keyboard handler is not
- * registered yet but we already getting updates form VT to
+ * registered yet but we already getting updates from the VT to
* update led state.
*/
static void kbd_bh(unsigned long dummy)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 3bdd4b1..2156188 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -2932,11 +2932,10 @@
gotoxy(vc, vc->vc_x, vc->vc_y);
csi_J(vc, 0);
update_screen(vc);
- pr_info("Console: %s %s %dx%d",
+ pr_info("Console: %s %s %dx%d\n",
vc->vc_can_do_color ? "colour" : "mono",
display_desc, vc->vc_cols, vc->vc_rows);
printable = 1;
- printk("\n");
console_unlock();
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index cbd8f5f..76316a3 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -2,14 +2,6 @@
# USB device configuration
#
-menuconfig USB_SUPPORT
- bool "USB support"
- depends on HAS_IOMEM
- default y
- ---help---
- This option adds core support for Universal Serial Bus (USB).
- You will also need drivers from the following menu to make use of it.
-
# many non-PCI SOC chips embed OHCI
config USB_ARCH_HAS_OHCI
boolean
@@ -63,6 +55,14 @@
boolean
default PCI
+menuconfig USB_SUPPORT
+ bool "USB support"
+ depends on HAS_IOMEM
+ default y
+ ---help---
+ This option adds core support for Universal Serial Bus (USB).
+ You will also need drivers from the following menu to make use of it.
+
if USB_SUPPORT
config USB_COMMON
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index c6f6560..0bb2b32 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -157,8 +157,9 @@
spin_lock(&desc->iuspin);
desc->werr = urb->status;
spin_unlock(&desc->iuspin);
- clear_bit(WDM_IN_USE, &desc->flags);
kfree(desc->outbuf);
+ desc->outbuf = NULL;
+ clear_bit(WDM_IN_USE, &desc->flags);
wake_up(&desc->wait);
}
@@ -338,7 +339,7 @@
if (we < 0)
return -EIO;
- desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+ buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
rv = -ENOMEM;
goto outnl;
@@ -406,10 +407,12 @@
req->wIndex = desc->inum;
req->wLength = cpu_to_le16(count);
set_bit(WDM_IN_USE, &desc->flags);
+ desc->outbuf = buf;
rv = usb_submit_urb(desc->command, GFP_KERNEL);
if (rv < 0) {
kfree(buf);
+ desc->outbuf = NULL;
clear_bit(WDM_IN_USE, &desc->flags);
dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
} else {
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index f8e2d6d..9a56635 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1189,8 +1189,13 @@
if (status == 0) {
status = usb_suspend_device(udev, msg);
- /* Again, ignore errors during system sleep transitions */
- if (!PMSG_IS_AUTO(msg))
+ /*
+ * Ignore errors from non-root-hub devices during
+ * system sleep transitions. For the most part,
+ * these devices should go to low power anyway when
+ * the entire bus is suspended.
+ */
+ if (udev->parent && !PMSG_IS_AUTO(msg))
status = 0;
}
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 622b4a4..57ed9e4 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -493,6 +493,15 @@
pci_save_state(pci_dev);
+ /*
+ * Some systems crash if an EHCI controller is in D3 during
+ * a sleep transition. We have to leave such controllers in D0.
+ */
+ if (hcd->broken_pci_sleep) {
+ dev_dbg(dev, "Staying in PCI D0\n");
+ return retval;
+ }
+
/* If the root hub is dead rather than suspended, disallow remote
* wakeup. usb_hc_died() should ensure that both hosts are marked as
* dying, so we only need to check the primary roothub.
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 9d7fc9a..140d3e1 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1978,6 +1978,18 @@
if (status == 0) {
usb_set_device_state(rhdev, USB_STATE_SUSPENDED);
hcd->state = HC_STATE_SUSPENDED;
+
+ /* Did we race with a root-hub wakeup event? */
+ if (rhdev->do_remote_wakeup) {
+ char buffer[6];
+
+ status = hcd->driver->hub_status_data(hcd, buffer);
+ if (status != 0) {
+ dev_dbg(&rhdev->dev, "suspend raced with wakeup event\n");
+ hcd_bus_resume(rhdev, PMSG_AUTO_RESUME);
+ status = -EBUSY;
+ }
+ }
} else {
spin_lock_irq(&hcd_root_hub_lock);
if (!HCD_DEAD(hcd)) {
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 28664eb..ec6c97d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1667,7 +1667,6 @@
{
struct usb_device *udev = *pdev;
int i;
- struct usb_hcd *hcd = bus_to_hcd(udev->bus);
/* mark the device as inactive, so any further urb submissions for
* this device (and any of its children) will fail immediately.
@@ -1690,9 +1689,7 @@
* so that the hardware is now fully quiesced.
*/
dev_dbg (&udev->dev, "unregistering device\n");
- mutex_lock(hcd->bandwidth_mutex);
usb_disable_device(udev, 0);
- mutex_unlock(hcd->bandwidth_mutex);
usb_hcd_synchronize_unlinks(udev);
usb_remove_ep_devs(&udev->ep0);
@@ -3163,6 +3160,22 @@
if (retval)
goto fail;
+ /*
+ * Some superspeed devices have finished the link training process
+ * and attached to a superspeed hub port, but the device descriptor
+ * got from those devices show they aren't superspeed devices. Warm
+ * reset the port attached by the devices can fix them.
+ */
+ if ((udev->speed == USB_SPEED_SUPER) &&
+ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
+ dev_err(&udev->dev, "got a wrong device descriptor, "
+ "warm reset device\n");
+ hub_port_reset(hub, port1, udev,
+ HUB_BH_RESET_TIME, true);
+ retval = -EINVAL;
+ goto fail;
+ }
+
if (udev->descriptor.bMaxPacketSize0 == 0xff ||
udev->speed == USB_SPEED_SUPER)
i = 512;
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index cefa0c8..d2b9af5 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -428,18 +428,10 @@
return retval;
}
-static int default_open (struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static const struct file_operations default_file_operations = {
.read = default_read_file,
.write = default_write_file,
- .open = default_open,
+ .open = simple_open,
.llseek = default_file_lseek,
};
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index b3bdfed..ca717da 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -308,7 +308,8 @@
retval = usb_unlink_urb(io->urbs [i]);
if (retval != -EINPROGRESS &&
retval != -ENODEV &&
- retval != -EBUSY)
+ retval != -EBUSY &&
+ retval != -EIDRM)
dev_err(&io->dev->dev,
"%s, unlink --> %d\n",
__func__, retval);
@@ -317,7 +318,6 @@
}
spin_lock(&io->lock);
}
- urb->dev = NULL;
/* on the last completion, signal usb_sg_wait() */
io->bytes += urb->actual_length;
@@ -524,7 +524,6 @@
case -ENXIO: /* hc didn't queue this one */
case -EAGAIN:
case -ENOMEM:
- io->urbs[i]->dev = NULL;
retval = 0;
yield();
break;
@@ -542,7 +541,6 @@
/* fail any uncompleted urbs */
default:
- io->urbs[i]->dev = NULL;
io->urbs[i]->status = retval;
dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
__func__, retval);
@@ -593,7 +591,10 @@
if (!io->urbs [i]->dev)
continue;
retval = usb_unlink_urb(io->urbs [i]);
- if (retval != -EINPROGRESS && retval != -EBUSY)
+ if (retval != -EINPROGRESS
+ && retval != -ENODEV
+ && retval != -EBUSY
+ && retval != -EIDRM)
dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
__func__, retval);
}
@@ -1135,8 +1136,6 @@
* Deallocates hcd/hardware state for the endpoints (nuking all or most
* pending urbs) and usbcore state for the interfaces, so that usbcore
* must usb_set_configuration() before any interfaces could be used.
- *
- * Must be called with hcd->bandwidth_mutex held.
*/
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
@@ -1189,7 +1188,9 @@
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
}
/* Remove endpoints from the host controller internal state */
+ mutex_lock(hcd->bandwidth_mutex);
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+ mutex_unlock(hcd->bandwidth_mutex);
/* Second pass: remove endpoint pointers */
}
for (i = skip_ep0; i < 16; ++i) {
@@ -1749,7 +1750,6 @@
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
- mutex_lock(hcd->bandwidth_mutex);
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device(dev, 1); /* Skip ep0 */
@@ -1762,6 +1762,7 @@
* host controller will not allow submissions to dropped endpoints. If
* this call fails, the device state is unchanged.
*/
+ mutex_lock(hcd->bandwidth_mutex);
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) {
mutex_unlock(hcd->bandwidth_mutex);
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 7239a73c..cd9b3a2 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -539,6 +539,10 @@
* never submitted, or it was unlinked before, or the hardware is already
* finished with it), even if the completion handler has not yet run.
*
+ * The URB must not be deallocated while this routine is running. In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
* Unlinking and Endpoint Queues:
*
* [The behaviors and guarantees described below do not apply to virtual
@@ -603,6 +607,10 @@
* with error -EPERM. Thus even if the URB's completion handler always
* tries to resubmit, it will not succeed and the URB will become idle.
*
+ * The URB must not be deallocated while this routine is running. In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
* This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule().
@@ -640,6 +648,10 @@
* with error -EPERM. Thus even if the URB's completion handler always
* tries to resubmit, it will not succeed and the URB will become idle.
*
+ * The URB must not be deallocated while this routine is running. In
+ * particular, when a driver calls this routine, it must insure that the
+ * completion handler cannot deallocate the URB.
+ *
* This routine may not be used in an interrupt context (such as a bottom
* half or a completion handler), or when holding a spinlock, or in other
* situations where the caller can't schedule().
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 7bd815a..99b58d84 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -206,11 +206,11 @@
for (i = 0; i < dwc->num_event_buffers; i++) {
evt = dwc->ev_buffs[i];
- if (evt) {
+ if (evt)
dwc3_free_one_event_buffer(dwc, evt);
- dwc->ev_buffs[i] = NULL;
- }
}
+
+ kfree(dwc->ev_buffs);
}
/**
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 25910e2..3584a16 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -353,6 +353,9 @@
dwc->test_mode_nr = wIndex >> 8;
dwc->test_mode = true;
+ break;
+ default:
+ return -EINVAL;
}
break;
@@ -559,15 +562,20 @@
length = trb->size & DWC3_TRB_SIZE_MASK;
if (dwc->ep0_bounced) {
+ unsigned transfer_size = ur->length;
+ unsigned maxp = ep0->endpoint.maxpacket;
+
+ transfer_size += (maxp - (transfer_size % maxp));
transferred = min_t(u32, ur->length,
- ep0->endpoint.maxpacket - length);
+ transfer_size - length);
memcpy(ur->buf, dwc->ep0_bounce, transferred);
dwc->ep0_bounced = false;
} else {
transferred = ur->length - length;
- ur->actual += transferred;
}
+ ur->actual += transferred;
+
if ((epnum & 1) && ur->actual < ur->length) {
/* for some reason we did not get everything out */
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
index 0c935d7..9d7bcd9 100644
--- a/drivers/usb/gadget/at91_udc.c
+++ b/drivers/usb/gadget/at91_udc.c
@@ -1863,8 +1863,8 @@
mod_timer(&udc->vbus_timer,
jiffies + VBUS_POLL_TIMEOUT);
} else {
- if (request_irq(udc->board.vbus_pin, at91_vbus_irq,
- 0, driver_name, udc)) {
+ if (request_irq(gpio_to_irq(udc->board.vbus_pin),
+ at91_vbus_irq, 0, driver_name, udc)) {
DBG("request vbus irq %d failed\n",
udc->board.vbus_pin);
retval = -EBUSY;
@@ -1886,7 +1886,7 @@
return 0;
fail4:
if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled)
- free_irq(udc->board.vbus_pin, udc);
+ free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
fail3:
if (gpio_is_valid(udc->board.vbus_pin))
gpio_free(udc->board.vbus_pin);
@@ -1924,7 +1924,7 @@
device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc);
if (gpio_is_valid(udc->board.vbus_pin)) {
- free_irq(udc->board.vbus_pin, udc);
+ free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
gpio_free(udc->board.vbus_pin);
}
free_irq(udc->udp_irq, udc);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index a6dfd21..170cbe8 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -927,7 +927,6 @@
dum->driver = NULL;
- dummy_pullup(&dum->gadget, 0);
return 0;
}
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 1cbba70..f52cb1a 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -712,7 +712,7 @@
if (code == FUNCTIONFS_INTERFACE_REVMAP) {
struct ffs_function *func = ffs->func;
ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
- } else if (gadget->ops->ioctl) {
+ } else if (gadget && gadget->ops->ioctl) {
ret = gadget->ops->ioctl(gadget, code, value);
} else {
ret = -ENOTTY;
@@ -1382,6 +1382,7 @@
ffs->ep0req = NULL;
ffs->gadget = NULL;
ffs_data_put(ffs);
+ clear_bit(FFS_FL_BOUND, &ffs->flags);
}
}
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index a371e96..cb8c162 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2189,7 +2189,7 @@
common->data_size_from_cmnd = 0;
sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
reply = check_command(common, common->cmnd_size,
- DATA_DIR_UNKNOWN, 0xff, 0, unknown);
+ DATA_DIR_UNKNOWN, ~0, 0, unknown);
if (reply == 0) {
common->curlun->sense_data = SS_INVALID_COMMAND;
reply = -EINVAL;
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 85a5ceb..965a629 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -345,7 +345,7 @@
}
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
- skb->len <= 1, req->actual, req->actual);
+ skb->len <= 1, req->actual, PAGE_SIZE);
page = NULL;
if (req->actual < req->length) { /* Last fragment */
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 7b1cf18..5234365 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -500,6 +500,7 @@
if (buf) {
memcpy(req->buf, buf, n);
req->complete = rndis_response_complete;
+ req->context = rndis;
rndis_free_response(rndis->config, buf);
value = n;
}
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 4fac569..a896d73 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -2579,7 +2579,7 @@
fsg->data_size_from_cmnd = 0;
sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
if ((reply = check_command(fsg, fsg->cmnd_size,
- DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
+ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
fsg->curlun->sense_data = SS_INVALID_COMMAND;
reply = -EINVAL;
}
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 5f94e79..55abfb6 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -730,7 +730,7 @@
: (1 << (ep_index(ep)));
/* check if the pipe is empty */
- if (!(list_empty(&ep->queue))) {
+ if (!(list_empty(&ep->queue)) && !(ep_index(ep) == 0)) {
/* Add td to the end */
struct fsl_req *lastreq;
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
@@ -918,10 +918,6 @@
return -ENOMEM;
}
- /* Update ep0 state */
- if ((ep_index(ep) == 0))
- udc->ep0_state = DATA_STATE_XMIT;
-
/* irq handler advances the queue */
if (req != NULL)
list_add_tail(&req->queue, &ep->queue);
@@ -1279,7 +1275,8 @@
udc->ep0_dir = USB_DIR_OUT;
ep = &udc->eps[0];
- udc->ep0_state = WAIT_FOR_OUT_STATUS;
+ if (udc->ep0_state != DATA_STATE_XMIT)
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
req->ep = ep;
req->req.length = 0;
@@ -1384,6 +1381,9 @@
list_add_tail(&req->queue, &ep->queue);
udc->ep0_state = DATA_STATE_XMIT;
+ if (ep0_prime_status(udc, EP_DIR_OUT))
+ ep0stall(udc);
+
return;
stall:
ep0stall(udc);
@@ -1492,6 +1492,14 @@
spin_lock(&udc->lock);
udc->ep0_state = (setup->bRequestType & USB_DIR_IN)
? DATA_STATE_XMIT : DATA_STATE_RECV;
+ /*
+ * If the data stage is IN, send status prime immediately.
+ * See 2.0 Spec chapter 8.5.3.3 for detail.
+ */
+ if (udc->ep0_state == DATA_STATE_XMIT)
+ if (ep0_prime_status(udc, EP_DIR_OUT))
+ ep0stall(udc);
+
} else {
/* No data phase, IN status from gadget */
udc->ep0_dir = USB_DIR_IN;
@@ -1520,9 +1528,8 @@
switch (udc->ep0_state) {
case DATA_STATE_XMIT:
- /* receive status phase */
- if (ep0_prime_status(udc, EP_DIR_OUT))
- ep0stall(udc);
+ /* already primed at setup_received_irq */
+ udc->ep0_state = WAIT_FOR_OUT_STATUS;
break;
case DATA_STATE_RECV:
/* send status phase */
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index 331cd67..a85eaf4 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -161,7 +161,7 @@
static struct ffs_data *gfs_ffs_data;
static unsigned long gfs_registered;
-static int gfs_init(void)
+static int __init gfs_init(void)
{
ENTER();
@@ -169,7 +169,7 @@
}
module_init(gfs_init);
-static void gfs_exit(void)
+static void __exit gfs_exit(void)
{
ENTER();
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 8793f32..e58b164 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1574,7 +1574,6 @@
DBG (dev, "%s %d\n", __func__, dev->state);
/* dev->state must prevent interference */
-restart:
spin_lock_irq (&dev->lock);
while (!list_empty(&dev->epfiles)) {
struct ep_data *ep;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 69295ba..105b206 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -340,7 +340,7 @@
/* currently we allocate TX FIFOs for all possible endpoints,
* and assume that they are all the same size. */
- for (ep = 0; ep <= 15; ep++) {
+ for (ep = 1; ep <= 15; ep++) {
val = addr;
val |= size << S3C_DPTXFSIZn_DPTxFSize_SHIFT;
addr += size;
@@ -741,7 +741,7 @@
/* write size / packets */
writel(epsize, hsotg->regs + epsize_reg);
- if (using_dma(hsotg)) {
+ if (using_dma(hsotg) && !continuing) {
unsigned int dma_reg;
/* write DMA address to control register, buffer already
@@ -1696,10 +1696,12 @@
reg |= mpsval;
writel(reg, regs + S3C_DIEPCTL(ep));
- reg = readl(regs + S3C_DOEPCTL(ep));
- reg &= ~S3C_DxEPCTL_MPS_MASK;
- reg |= mpsval;
- writel(reg, regs + S3C_DOEPCTL(ep));
+ if (ep) {
+ reg = readl(regs + S3C_DOEPCTL(ep));
+ reg &= ~S3C_DxEPCTL_MPS_MASK;
+ reg |= mpsval;
+ writel(reg, regs + S3C_DOEPCTL(ep));
+ }
return;
@@ -1919,7 +1921,8 @@
ints & S3C_DIEPMSK_TxFIFOEmpty) {
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
- s3c_hsotg_trytx(hsotg, hs_ep);
+ if (!using_dma(hsotg))
+ s3c_hsotg_trytx(hsotg, hs_ep);
}
}
}
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 56da49f..e5e44f8 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -263,9 +263,9 @@
if (udc_is_newstyle(udc)) {
udc->driver->disconnect(udc->gadget);
+ usb_gadget_disconnect(udc->gadget);
udc->driver->unbind(udc->gadget);
usb_gadget_udc_stop(udc->gadget, udc->driver);
- usb_gadget_disconnect(udc->gadget);
} else {
usb_gadget_stop(udc->gadget, udc->driver);
}
@@ -411,9 +411,13 @@
struct usb_udc *udc = container_of(dev, struct usb_udc, dev);
if (sysfs_streq(buf, "connect")) {
+ if (udc_is_newstyle(udc))
+ usb_gadget_udc_start(udc->gadget, udc->driver);
usb_gadget_connect(udc->gadget);
} else if (sysfs_streq(buf, "disconnect")) {
usb_gadget_disconnect(udc->gadget);
+ if (udc_is_newstyle(udc))
+ usb_gadget_udc_stop(udc->gadget, udc->driver);
} else {
dev_err(dev, "unsupported command '%s'\n", buf);
return -EINVAL;
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
index bc78c60..ca4e03a 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/uvc.h
@@ -28,7 +28,7 @@
struct uvc_request_data
{
- unsigned int length;
+ __s32 length;
__u8 data[60];
};
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index d776adb..0cdf89d 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -543,11 +543,11 @@
return ret;
}
+/* called with queue->irqlock held.. */
static struct uvc_buffer *
uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
{
struct uvc_buffer *nextbuf;
- unsigned long flags;
if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
buf->buf.length != buf->buf.bytesused) {
@@ -556,14 +556,12 @@
return buf;
}
- spin_lock_irqsave(&queue->irqlock, flags);
list_del(&buf->queue);
if (!list_empty(&queue->irqqueue))
nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
else
nextbuf = NULL;
- spin_unlock_irqrestore(&queue->irqlock, flags);
buf->buf.sequence = queue->sequence++;
do_gettimeofday(&buf->buf.timestamp);
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index f6e083b..54d7ca5 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -39,7 +39,7 @@
if (data->length < 0)
return usb_ep_set_halt(cdev->gadget->ep0);
- req->length = min(uvc->event_length, data->length);
+ req->length = min_t(unsigned int, uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
req->dma = DMA_ADDR_INVALID;
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 19f318a..cf14c95 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
/* interface and function clocks */
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index fd9109d..680e1a3 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -352,7 +352,6 @@
static int debug_periodic_open(struct inode *, struct file *);
static int debug_registers_open(struct inode *, struct file *);
static int debug_async_open(struct inode *, struct file *);
-static int debug_lpm_open(struct inode *, struct file *);
static ssize_t debug_lpm_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
static ssize_t debug_lpm_write(struct file *file, const char __user *buffer,
@@ -385,7 +384,7 @@
};
static const struct file_operations debug_lpm_fops = {
.owner = THIS_MODULE,
- .open = debug_lpm_open,
+ .open = simple_open,
.read = debug_lpm_read,
.write = debug_lpm_write,
.release = debug_lpm_close,
@@ -970,12 +969,6 @@
return file->private_data ? 0 : -ENOMEM;
}
-static int debug_lpm_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static int debug_lpm_close(struct inode *inode, struct file *file)
{
return 0;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 3e73451..d0a84bd 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -218,6 +218,9 @@
u32 portsc;
struct usb_hcd *hcd = ehci_to_hcd(ehci);
void __iomem *non_ehci = hcd->regs;
+ struct fsl_usb2_platform_data *pdata;
+
+ pdata = hcd->self.controller->platform_data;
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -234,7 +237,9 @@
/* fall through */
case FSL_USB2_PHY_UTMI:
/* enable UTMI PHY */
- setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
+ if (pdata->have_sysif_regs)
+ setbits32(non_ehci + FSL_SOC_USB_CTRL,
+ CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 057cdda..4a3bc5b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -347,6 +347,8 @@
if (ehci->debug)
dbgp_external_startup();
+ ehci->port_c_suspend = ehci->suspended_ports =
+ ehci->resuming_ports = 0;
return retval;
}
@@ -856,8 +858,13 @@
goto dead;
}
+ /*
+ * We don't use STS_FLR, but some controllers don't like it to
+ * remain on, so mask it out along with the other status bits.
+ */
+ masked_status = status & (INTR_MASK | STS_FLR);
+
/* Shared IRQ? */
- masked_status = status & INTR_MASK;
if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) {
spin_unlock(&ehci->lock);
return IRQ_NONE;
@@ -908,7 +915,7 @@
pcd_status = status;
/* resume root hub? */
- if (!(cmd & CMD_RUN))
+ if (ehci->rh_state == EHCI_RH_SUSPENDED)
usb_hcd_resume_root_hub(hcd);
/* get per-port change detect bits */
@@ -939,6 +946,7 @@
* like usb_port_resume() does.
*/
ehci->reset_done[i] = jiffies + msecs_to_jiffies(25);
+ set_bit(i, &ehci->resuming_ports);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
mod_timer(&hcd->rh_timer, ehci->reset_done[i]);
}
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 256fbd4..38fe076 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -223,15 +223,10 @@
* remote wakeup, we must fail the suspend.
*/
if (hcd->self.root_hub->do_remote_wakeup) {
- port = HCS_N_PORTS(ehci->hcs_params);
- while (port--) {
- if (ehci->reset_done[port] != 0) {
- spin_unlock_irq(&ehci->lock);
- ehci_dbg(ehci, "suspend failed because "
- "port %d is resuming\n",
- port + 1);
- return -EBUSY;
- }
+ if (ehci->resuming_ports) {
+ spin_unlock_irq(&ehci->lock);
+ ehci_dbg(ehci, "suspend failed because a port is resuming\n");
+ return -EBUSY;
}
}
@@ -554,16 +549,12 @@
ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- u32 temp, status = 0;
+ u32 temp, status;
u32 mask;
int ports, i, retval = 1;
unsigned long flags;
u32 ppcd = 0;
- /* if !USB_SUSPEND, root hub timers won't get shut down ... */
- if (ehci->rh_state != EHCI_RH_RUNNING)
- return 0;
-
/* init status to no-changes */
buf [0] = 0;
ports = HCS_N_PORTS (ehci->hcs_params);
@@ -572,6 +563,11 @@
retval++;
}
+ /* Inform the core about resumes-in-progress by returning
+ * a non-zero value even if there are no status changes.
+ */
+ status = ehci->resuming_ports;
+
/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
* may be relevant that VIA VT8235 controllers, where PORT_POWER is
@@ -846,6 +842,7 @@
ehci_writel(ehci,
temp & ~(PORT_RWC_BITS | PORT_RESUME),
status_reg);
+ clear_bit(wIndex, &ehci->resuming_ports);
retval = handshake(ehci, status_reg,
PORT_RESUME, 0, 2000 /* 2msec */);
if (retval != 0) {
@@ -864,6 +861,7 @@
ehci->reset_done[wIndex])) {
status |= USB_PORT_STAT_C_RESET << 16;
ehci->reset_done [wIndex] = 0;
+ clear_bit(wIndex, &ehci->resuming_ports);
/* force reset to complete */
ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET),
@@ -884,8 +882,10 @@
ehci_readl(ehci, status_reg));
}
- if (!(temp & (PORT_RESUME|PORT_RESET)))
+ if (!(temp & (PORT_RESUME|PORT_RESET))) {
ehci->reset_done[wIndex] = 0;
+ clear_bit(wIndex, &ehci->resuming_ports);
+ }
/* transfer dedicated ports to the companion hc */
if ((temp & PORT_CONNECT) &&
@@ -920,6 +920,7 @@
status |= USB_PORT_STAT_SUSPEND;
} else if (test_bit(wIndex, &ehci->suspended_ports)) {
clear_bit(wIndex, &ehci->suspended_ports);
+ clear_bit(wIndex, &ehci->resuming_ports);
ehci->reset_done[wIndex] = 0;
if (temp & PORT_PE)
set_bit(wIndex, &ehci->port_c_suspend);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index bba9850..5c78f9e 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -42,6 +42,7 @@
#include <plat/usb.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
+#include <linux/gpio.h>
/* EHCI Register Set */
#define EHCI_INSNREG04 (0xA0)
@@ -191,6 +192,19 @@
}
}
+ if (pdata->phy_reset) {
+ if (gpio_is_valid(pdata->reset_gpio_port[0]))
+ gpio_request_one(pdata->reset_gpio_port[0],
+ GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
+
+ if (gpio_is_valid(pdata->reset_gpio_port[1]))
+ gpio_request_one(pdata->reset_gpio_port[1],
+ GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
+
+ /* Hold the PHY in RESET for enough time till DIR is high */
+ udelay(10);
+ }
+
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
@@ -237,6 +251,19 @@
/* root ports should always stay powered */
ehci_port_power(omap_ehci, 1);
+ if (pdata->phy_reset) {
+ /* Hold the PHY in RESET for enough time till
+ * PHY is settled and ready
+ */
+ udelay(10);
+
+ if (gpio_is_valid(pdata->reset_gpio_port[0]))
+ gpio_set_value(pdata->reset_gpio_port[0], 1);
+
+ if (gpio_is_valid(pdata->reset_gpio_port[1]))
+ gpio_set_value(pdata->reset_gpio_port[1], 1);
+ }
+
return 0;
err_add_hcd:
@@ -259,8 +286,9 @@
*/
static int ehci_hcd_omap_remove(struct platform_device *pdev)
{
- struct device *dev = &pdev->dev;
- struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct device *dev = &pdev->dev;
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct ehci_hcd_omap_platform_data *pdata = dev->platform_data;
usb_remove_hcd(hcd);
disable_put_regulator(dev->platform_data);
@@ -269,6 +297,13 @@
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
+ if (pdata->phy_reset) {
+ if (gpio_is_valid(pdata->reset_gpio_port[0]))
+ gpio_free(pdata->reset_gpio_port[0]);
+
+ if (gpio_is_valid(pdata->reset_gpio_port[1]))
+ gpio_free(pdata->reset_gpio_port[1]);
+ }
return 0;
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 01bb7241d..fe8dc06 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -144,6 +144,14 @@
hcd->has_tt = 1;
tdi_reset(ehci);
}
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
+ /* EHCI #1 or #2 on 6 Series/C200 Series chipset */
+ if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
+ ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
+ hcd->broken_pci_sleep = 1;
+ device_set_wakeup_capable(&pdev->dev, false);
+ }
+ }
break;
case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 3de48a2..f214a80 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -24,6 +24,7 @@
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/pm_runtime.h>
#include <mach/usb_phy.h>
#include <mach/iomap.h>
@@ -37,9 +38,7 @@
struct clk *emc_clk;
struct usb_phy *transceiver;
int host_resumed;
- int bus_suspended;
int port_resuming;
- int power_down_on_bus_suspend;
enum tegra_usb_phy_port_speed port_speed;
};
@@ -224,6 +223,7 @@
temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
/* start resume signalling */
ehci_writel(ehci, temp | PORT_RESUME, status_reg);
+ set_bit(wIndex-1, &ehci->resuming_ports);
spin_unlock_irqrestore(&ehci->lock, flags);
msleep(20);
@@ -236,6 +236,7 @@
pr_err("%s: timeout waiting for SUSPEND\n", __func__);
ehci->reset_done[wIndex-1] = 0;
+ clear_bit(wIndex-1, &ehci->resuming_ports);
tegra->port_resuming = 1;
goto done;
@@ -271,120 +272,6 @@
up_write(&ehci_cf_port_reset_rwsem);
}
-static int tegra_usb_suspend(struct usb_hcd *hcd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- struct ehci_regs __iomem *hw = tegra->ehci->regs;
- unsigned long flags;
-
- spin_lock_irqsave(&tegra->ehci->lock, flags);
-
- tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
- ehci_halt(tegra->ehci);
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
- spin_unlock_irqrestore(&tegra->ehci->lock, flags);
-
- tegra_ehci_power_down(hcd);
- return 0;
-}
-
-static int tegra_usb_resume(struct usb_hcd *hcd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- struct ehci_regs __iomem *hw = ehci->regs;
- unsigned long val;
-
- set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- tegra_ehci_power_up(hcd);
-
- if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
- /* Wait for the phy to detect new devices
- * before we restart the controller */
- msleep(10);
- goto restart;
- }
-
- /* Force the phy to keep data lines in suspend state */
- tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
-
- /* Enable host mode */
- tdi_reset(ehci);
-
- /* Enable Port Power */
- val = readl(&hw->port_status[0]);
- val |= PORT_POWER;
- writel(val, &hw->port_status[0]);
- udelay(10);
-
- /* Check if the phy resume from LP0. When the phy resume from LP0
- * USB register will be reset. */
- if (!readl(&hw->async_next)) {
- /* Program the field PTC based on the saved speed mode */
- val = readl(&hw->port_status[0]);
- val &= ~PORT_TEST(~0);
- if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
- val |= PORT_TEST_FORCE;
- else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
- val |= PORT_TEST(6);
- else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
- val |= PORT_TEST(7);
- writel(val, &hw->port_status[0]);
- udelay(10);
-
- /* Disable test mode by setting PTC field to NORMAL_OP */
- val = readl(&hw->port_status[0]);
- val &= ~PORT_TEST(~0);
- writel(val, &hw->port_status[0]);
- udelay(10);
- }
-
- /* Poll until CCS is enabled */
- if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
- PORT_CONNECT, 2000)) {
- pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
- goto restart;
- }
-
- /* Poll until PE is enabled */
- if (handshake(ehci, &hw->port_status[0], PORT_PE,
- PORT_PE, 2000)) {
- pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
- goto restart;
- }
-
- /* Clear the PCI status, to avoid an interrupt taken upon resume */
- val = readl(&hw->status);
- val |= STS_PCD;
- writel(val, &hw->status);
-
- /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
- val = readl(&hw->port_status[0]);
- if ((val & PORT_POWER) && (val & PORT_PE)) {
- val |= PORT_SUSPEND;
- writel(val, &hw->port_status[0]);
-
- /* Wait until port suspend completes */
- if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
- PORT_SUSPEND, 1000)) {
- pr_err("%s: timeout waiting for PORT_SUSPEND\n",
- __func__);
- goto restart;
- }
- }
-
- tegra_ehci_phy_restore_end(tegra->phy);
- return 0;
-
-restart:
- if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
- tegra_ehci_phy_restore_end(tegra->phy);
-
- tegra_ehci_restart(hcd);
- return 0;
-}
-
static void tegra_ehci_shutdown(struct usb_hcd *hcd)
{
struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
@@ -432,36 +319,6 @@
return retval;
}
-#ifdef CONFIG_PM
-static int tegra_ehci_bus_suspend(struct usb_hcd *hcd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
- int error_status = 0;
-
- error_status = ehci_bus_suspend(hcd);
- if (!error_status && tegra->power_down_on_bus_suspend) {
- tegra_usb_suspend(hcd);
- tegra->bus_suspended = 1;
- }
-
- return error_status;
-}
-
-static int tegra_ehci_bus_resume(struct usb_hcd *hcd)
-{
- struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-
- if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) {
- tegra_usb_resume(hcd);
- tegra->bus_suspended = 0;
- }
-
- tegra_usb_phy_preresume(tegra->phy);
- tegra->port_resuming = 1;
- return ehci_bus_resume(hcd);
-}
-#endif
-
struct temp_buffer {
void *kmalloc_ptr;
void *old_xfer_buffer;
@@ -572,8 +429,8 @@
.hub_control = tegra_ehci_hub_control,
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
#ifdef CONFIG_PM
- .bus_suspend = tegra_ehci_bus_suspend,
- .bus_resume = tegra_ehci_bus_resume,
+ .bus_suspend = ehci_bus_suspend,
+ .bus_resume = ehci_bus_resume,
#endif
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
@@ -601,11 +458,187 @@
dev_err(&pdev->dev, "can't enable vbus\n");
return err;
}
- gpio_set_value(gpio, 1);
return err;
}
+#ifdef CONFIG_PM
+
+static int controller_suspend(struct device *dev)
+{
+ struct tegra_ehci_hcd *tegra =
+ platform_get_drvdata(to_platform_device(dev));
+ struct ehci_hcd *ehci = tegra->ehci;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ struct ehci_regs __iomem *hw = ehci->regs;
+ unsigned long flags;
+
+ if (time_before(jiffies, ehci->next_statechange))
+ msleep(10);
+
+ spin_lock_irqsave(&ehci->lock, flags);
+
+ tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
+ ehci_halt(ehci);
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+ spin_unlock_irqrestore(&ehci->lock, flags);
+
+ tegra_ehci_power_down(hcd);
+ return 0;
+}
+
+static int controller_resume(struct device *dev)
+{
+ struct tegra_ehci_hcd *tegra =
+ platform_get_drvdata(to_platform_device(dev));
+ struct ehci_hcd *ehci = tegra->ehci;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ struct ehci_regs __iomem *hw = ehci->regs;
+ unsigned long val;
+
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+ tegra_ehci_power_up(hcd);
+
+ if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) {
+ /* Wait for the phy to detect new devices
+ * before we restart the controller */
+ msleep(10);
+ goto restart;
+ }
+
+ /* Force the phy to keep data lines in suspend state */
+ tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+
+ /* Enable host mode */
+ tdi_reset(ehci);
+
+ /* Enable Port Power */
+ val = readl(&hw->port_status[0]);
+ val |= PORT_POWER;
+ writel(val, &hw->port_status[0]);
+ udelay(10);
+
+ /* Check if the phy resume from LP0. When the phy resume from LP0
+ * USB register will be reset. */
+ if (!readl(&hw->async_next)) {
+ /* Program the field PTC based on the saved speed mode */
+ val = readl(&hw->port_status[0]);
+ val &= ~PORT_TEST(~0);
+ if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH)
+ val |= PORT_TEST_FORCE;
+ else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL)
+ val |= PORT_TEST(6);
+ else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+ val |= PORT_TEST(7);
+ writel(val, &hw->port_status[0]);
+ udelay(10);
+
+ /* Disable test mode by setting PTC field to NORMAL_OP */
+ val = readl(&hw->port_status[0]);
+ val &= ~PORT_TEST(~0);
+ writel(val, &hw->port_status[0]);
+ udelay(10);
+ }
+
+ /* Poll until CCS is enabled */
+ if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+ PORT_CONNECT, 2000)) {
+ pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
+ goto restart;
+ }
+
+ /* Poll until PE is enabled */
+ if (handshake(ehci, &hw->port_status[0], PORT_PE,
+ PORT_PE, 2000)) {
+ pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
+ goto restart;
+ }
+
+ /* Clear the PCI status, to avoid an interrupt taken upon resume */
+ val = readl(&hw->status);
+ val |= STS_PCD;
+ writel(val, &hw->status);
+
+ /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
+ val = readl(&hw->port_status[0]);
+ if ((val & PORT_POWER) && (val & PORT_PE)) {
+ val |= PORT_SUSPEND;
+ writel(val, &hw->port_status[0]);
+
+ /* Wait until port suspend completes */
+ if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+ PORT_SUSPEND, 1000)) {
+ pr_err("%s: timeout waiting for PORT_SUSPEND\n",
+ __func__);
+ goto restart;
+ }
+ }
+
+ tegra_ehci_phy_restore_end(tegra->phy);
+ goto done;
+
+ restart:
+ if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
+ tegra_ehci_phy_restore_end(tegra->phy);
+
+ tegra_ehci_restart(hcd);
+
+ done:
+ tegra_usb_phy_preresume(tegra->phy);
+ tegra->port_resuming = 1;
+ return 0;
+}
+
+static int tegra_ehci_suspend(struct device *dev)
+{
+ struct tegra_ehci_hcd *tegra =
+ platform_get_drvdata(to_platform_device(dev));
+ struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
+ int rc = 0;
+
+ /*
+ * When system sleep is supported and USB controller wakeup is
+ * implemented: If the controller is runtime-suspended and the
+ * wakeup setting needs to be changed, call pm_runtime_resume().
+ */
+ if (HCD_HW_ACCESSIBLE(hcd))
+ rc = controller_suspend(dev);
+ return rc;
+}
+
+static int tegra_ehci_resume(struct device *dev)
+{
+ int rc;
+
+ rc = controller_resume(dev);
+ if (rc == 0) {
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ }
+ return rc;
+}
+
+static int tegra_ehci_runtime_suspend(struct device *dev)
+{
+ return controller_suspend(dev);
+}
+
+static int tegra_ehci_runtime_resume(struct device *dev)
+{
+ return controller_resume(dev);
+}
+
+static const struct dev_pm_ops tegra_ehci_pm_ops = {
+ .suspend = tegra_ehci_suspend,
+ .resume = tegra_ehci_resume,
+ .runtime_suspend = tegra_ehci_runtime_suspend,
+ .runtime_resume = tegra_ehci_runtime_resume,
+};
+
+#endif
+
static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
static int tegra_ehci_probe(struct platform_device *pdev)
@@ -720,7 +753,6 @@
}
tegra->host_resumed = 1;
- tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend;
tegra->ehci = hcd_to_ehci(hcd);
irq = platform_get_irq(pdev, 0);
@@ -729,7 +761,6 @@
err = -ENODEV;
goto fail;
}
- set_irq_flags(irq, IRQF_VALID);
#ifdef CONFIG_USB_OTG_UTILS
if (pdata->operating_mode == TEGRA_USB_OTG) {
@@ -745,6 +776,14 @@
goto fail;
}
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+
+ /* Don't skip the pm_runtime_forbid call if wakeup isn't working */
+ /* if (!pdata->power_down_on_bus_suspend) */
+ pm_runtime_forbid(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_put_sync(&pdev->dev);
return err;
fail:
@@ -771,33 +810,6 @@
return err;
}
-#ifdef CONFIG_PM
-static int tegra_ehci_resume(struct platform_device *pdev)
-{
- struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
-
- if (tegra->bus_suspended)
- return 0;
-
- return tegra_usb_resume(hcd);
-}
-
-static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
- struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
-
- if (tegra->bus_suspended)
- return 0;
-
- if (time_before(jiffies, tegra->ehci->next_statechange))
- msleep(10);
-
- return tegra_usb_suspend(hcd);
-}
-#endif
-
static int tegra_ehci_remove(struct platform_device *pdev)
{
struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
@@ -806,6 +818,10 @@
if (tegra == NULL || hcd == NULL)
return -EINVAL;
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
#ifdef CONFIG_USB_OTG_UTILS
if (tegra->transceiver) {
otg_set_host(tegra->transceiver->otg, NULL);
@@ -846,13 +862,12 @@
static struct platform_driver tegra_ehci_driver = {
.probe = tegra_ehci_probe,
.remove = tegra_ehci_remove,
-#ifdef CONFIG_PM
- .suspend = tegra_ehci_suspend,
- .resume = tegra_ehci_resume,
-#endif
.shutdown = tegra_ehci_hcd_shutdown,
.driver = {
.name = "tegra-ehci",
.of_match_table = tegra_ehci_of_match,
+#ifdef CONFIG_PM
+ .pm = &tegra_ehci_pm_ops,
+#endif
}
};
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 8f9acbc..2694ed6 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -117,6 +117,8 @@
the change-suspend feature turned on */
unsigned long suspended_ports; /* which ports are
suspended */
+ unsigned long resuming_ports; /* which ports have
+ started to resume */
/* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index db8963f..13ebeca 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -27,6 +27,10 @@
#error "CONFIG_ARCH_AT91 must be defined."
#endif
+#define valid_port(index) ((index) >= 0 && (index) < AT91_MAX_USBH_PORTS)
+#define at91_for_each_port(index) \
+ for ((index) = 0; (index) < AT91_MAX_USBH_PORTS; (index)++)
+
/* interface and function clocks; sometimes also an AHB clock */
static struct clk *iclk, *fclk, *hclk;
static int clocked;
@@ -90,7 +94,7 @@
/*-------------------------------------------------------------------------*/
-static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
+static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *);
/* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */
@@ -104,7 +108,7 @@
* then invokes the start() method for the HCD associated with it
* through the hotplug entry's driver_data.
*/
-static int usb_hcd_at91_probe(const struct hc_driver *driver,
+static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver,
struct platform_device *pdev)
{
int retval;
@@ -199,7 +203,7 @@
* context, "rmmod" or something similar.
*
*/
-static void usb_hcd_at91_remove(struct usb_hcd *hcd,
+static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
usb_remove_hcd(hcd);
@@ -240,26 +244,26 @@
static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int enable)
{
- if (port < 0 || port >= 2)
+ if (!valid_port(port))
return;
if (!gpio_is_valid(pdata->vbus_pin[port]))
return;
gpio_set_value(pdata->vbus_pin[port],
- !pdata->vbus_pin_active_low[port] ^ enable);
+ pdata->vbus_pin_active_low[port] ^ enable);
}
static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
{
- if (port < 0 || port >= 2)
+ if (!valid_port(port))
return -EINVAL;
if (!gpio_is_valid(pdata->vbus_pin[port]))
return -EINVAL;
return gpio_get_value(pdata->vbus_pin[port]) ^
- !pdata->vbus_pin_active_low[port];
+ pdata->vbus_pin_active_low[port];
}
/*
@@ -271,9 +275,9 @@
int length = ohci_hub_status_data(hcd, buf);
int port;
- for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+ at91_for_each_port(port) {
if (pdata->overcurrent_changed[port]) {
- if (! length)
+ if (!length)
length = 1;
buf[0] |= 1 << (port + 1);
}
@@ -297,11 +301,17 @@
"ohci_at91_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n",
hcd, typeReq, wValue, wIndex, buf, wLength);
+ wIndex--;
+
switch (typeReq) {
case SetPortFeature:
if (wValue == USB_PORT_FEAT_POWER) {
dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n");
- ohci_at91_usb_set_power(pdata, wIndex - 1, 1);
+ if (valid_port(wIndex)) {
+ ohci_at91_usb_set_power(pdata, wIndex, 1);
+ ret = 0;
+ }
+
goto out;
}
break;
@@ -312,9 +322,9 @@
dev_dbg(hcd->self.controller,
"ClearPortFeature: C_OVER_CURRENT\n");
- if (wIndex == 1 || wIndex == 2) {
- pdata->overcurrent_changed[wIndex-1] = 0;
- pdata->overcurrent_status[wIndex-1] = 0;
+ if (valid_port(wIndex)) {
+ pdata->overcurrent_changed[wIndex] = 0;
+ pdata->overcurrent_status[wIndex] = 0;
}
goto out;
@@ -323,9 +333,8 @@
dev_dbg(hcd->self.controller,
"ClearPortFeature: OVER_CURRENT\n");
- if (wIndex == 1 || wIndex == 2) {
- pdata->overcurrent_status[wIndex-1] = 0;
- }
+ if (valid_port(wIndex))
+ pdata->overcurrent_status[wIndex] = 0;
goto out;
@@ -333,15 +342,15 @@
dev_dbg(hcd->self.controller,
"ClearPortFeature: POWER\n");
- if (wIndex == 1 || wIndex == 2) {
- ohci_at91_usb_set_power(pdata, wIndex - 1, 0);
+ if (valid_port(wIndex)) {
+ ohci_at91_usb_set_power(pdata, wIndex, 0);
return 0;
}
}
break;
}
- ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
+ ret = ohci_hub_control(hcd, typeReq, wValue, wIndex + 1, buf, wLength);
if (ret)
goto out;
@@ -377,18 +386,15 @@
dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
- if (wIndex == 1 || wIndex == 2) {
- if (! ohci_at91_usb_get_power(pdata, wIndex-1)) {
+ if (valid_port(wIndex)) {
+ if (!ohci_at91_usb_get_power(pdata, wIndex))
*data &= ~cpu_to_le32(RH_PS_PPS);
- }
- if (pdata->overcurrent_changed[wIndex-1]) {
+ if (pdata->overcurrent_changed[wIndex])
*data |= cpu_to_le32(RH_PS_OCIC);
- }
- if (pdata->overcurrent_status[wIndex-1]) {
+ if (pdata->overcurrent_status[wIndex])
*data |= cpu_to_le32(RH_PS_POCI);
- }
}
}
@@ -450,14 +456,14 @@
/* From the GPIO notifying the over-current situation, find
* out the corresponding port */
- for (port = 0; port < ARRAY_SIZE(pdata->overcurrent_pin); port++) {
+ at91_for_each_port(port) {
if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
gpio = pdata->overcurrent_pin[port];
break;
}
}
- if (port == ARRAY_SIZE(pdata->overcurrent_pin)) {
+ if (port == AT91_MAX_USBH_PORTS) {
dev_err(& pdev->dev, "overcurrent interrupt from unknown GPIO\n");
return IRQ_HANDLED;
}
@@ -467,7 +473,7 @@
/* When notified of an over-current situation, disable power
on the corresponding port, and mark this port in
over-current. */
- if (! val) {
+ if (!val) {
ohci_at91_usb_set_power(pdata, port, 0);
pdata->overcurrent_status[port] = 1;
pdata->overcurrent_changed[port] = 1;
@@ -492,7 +498,7 @@
static int __devinit ohci_at91_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- int i, ret, gpio;
+ int i, gpio;
enum of_gpio_flags flags;
struct at91_usbh_data *pdata;
u32 ports;
@@ -514,48 +520,17 @@
if (!of_property_read_u32(np, "num-ports", &ports))
pdata->ports = ports;
- for (i = 0; i < 2; i++) {
+ at91_for_each_port(i) {
gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
pdata->vbus_pin[i] = gpio;
if (!gpio_is_valid(gpio))
continue;
pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
- ret = gpio_request(gpio, "ohci_vbus");
- if (ret) {
- dev_warn(&pdev->dev, "can't request vbus gpio %d", gpio);
- continue;
- }
- ret = gpio_direction_output(gpio, !(flags & OF_GPIO_ACTIVE_LOW) ^ 1);
- if (ret)
- dev_warn(&pdev->dev, "can't put vbus gpio %d as output %d",
- !(flags & OF_GPIO_ACTIVE_LOW) ^ 1, gpio);
}
- for (i = 0; i < 2; i++) {
- gpio = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
- pdata->overcurrent_pin[i] = gpio;
- if (!gpio_is_valid(gpio))
- continue;
- ret = gpio_request(gpio, "ohci_overcurrent");
- if (ret) {
- dev_err(&pdev->dev, "can't request overcurrent gpio %d", gpio);
- continue;
- }
-
- ret = gpio_direction_input(gpio);
- if (ret) {
- dev_err(&pdev->dev, "can't configure overcurrent gpio %d as input", gpio);
- continue;
- }
-
- ret = request_irq(gpio_to_irq(gpio),
- ohci_hcd_at91_overcurrent_irq,
- IRQF_SHARED, "ohci_overcurrent", pdev);
- if (ret) {
- gpio_free(gpio);
- dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
- }
- }
+ at91_for_each_port(i)
+ pdata->overcurrent_pin[i] =
+ of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
pdev->dev.platform_data = pdata;
@@ -570,39 +545,73 @@
/*-------------------------------------------------------------------------*/
-static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
+static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
{
struct at91_usbh_data *pdata;
int i;
+ int gpio;
+ int ret;
- i = ohci_at91_of_init(pdev);
-
- if (i)
- return i;
+ ret = ohci_at91_of_init(pdev);
+ if (ret)
+ return ret;
pdata = pdev->dev.platform_data;
if (pdata) {
- for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
+ at91_for_each_port(i) {
if (!gpio_is_valid(pdata->vbus_pin[i]))
continue;
- gpio_request(pdata->vbus_pin[i], "ohci_vbus");
+ gpio = pdata->vbus_pin[i];
+
+ ret = gpio_request(gpio, "ohci_vbus");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't request vbus gpio %d\n", gpio);
+ continue;
+ }
+ ret = gpio_direction_output(gpio,
+ !pdata->vbus_pin_active_low[i]);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't put vbus gpio %d as output %d\n",
+ gpio, !pdata->vbus_pin_active_low[i]);
+ gpio_free(gpio);
+ continue;
+ }
+
ohci_at91_usb_set_power(pdata, i, 1);
}
- for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
- int ret;
-
+ at91_for_each_port(i) {
if (!gpio_is_valid(pdata->overcurrent_pin[i]))
continue;
- gpio_request(pdata->overcurrent_pin[i], "ohci_overcurrent");
+ gpio = pdata->overcurrent_pin[i];
- ret = request_irq(gpio_to_irq(pdata->overcurrent_pin[i]),
+ ret = gpio_request(gpio, "ohci_overcurrent");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't request overcurrent gpio %d\n",
+ gpio);
+ continue;
+ }
+
+ ret = gpio_direction_input(gpio);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't configure overcurrent gpio %d as input\n",
+ gpio);
+ gpio_free(gpio);
+ continue;
+ }
+
+ ret = request_irq(gpio_to_irq(gpio),
ohci_hcd_at91_overcurrent_irq,
IRQF_SHARED, "ohci_overcurrent", pdev);
if (ret) {
- gpio_free(pdata->overcurrent_pin[i]);
- dev_warn(& pdev->dev, "cannot get GPIO IRQ for overcurrent\n");
+ gpio_free(gpio);
+ dev_err(&pdev->dev,
+ "can't get gpio IRQ for overcurrent\n");
}
}
}
@@ -611,20 +620,20 @@
return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
}
-static int ohci_hcd_at91_drv_remove(struct platform_device *pdev)
+static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev)
{
struct at91_usbh_data *pdata = pdev->dev.platform_data;
int i;
if (pdata) {
- for (i = 0; i < ARRAY_SIZE(pdata->vbus_pin); i++) {
+ at91_for_each_port(i) {
if (!gpio_is_valid(pdata->vbus_pin[i]))
continue;
ohci_at91_usb_set_power(pdata, i, 0);
gpio_free(pdata->vbus_pin[i]);
}
- for (i = 0; i < ARRAY_SIZE(pdata->overcurrent_pin); i++) {
+ at91_for_each_port(i) {
if (!gpio_is_valid(pdata->overcurrent_pin[i]))
continue;
free_irq(gpio_to_irq(pdata->overcurrent_pin[i]), pdev);
@@ -687,7 +696,7 @@
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
- .remove = ohci_hcd_at91_drv_remove,
+ .remove = __devexit_p(ohci_hcd_at91_drv_remove),
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_hcd_at91_drv_suspend,
.resume = ohci_hcd_at91_drv_resume,
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 11de5f1..32dada8 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -825,9 +825,13 @@
}
}
- /* Disable any BIOS SMIs */
- writel(XHCI_LEGACY_DISABLE_SMI,
- base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+ val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+ /* Mask off (turn off) any enabled SMIs */
+ val &= XHCI_LEGACY_DISABLE_SMI;
+ /* Mask all SMI events bits, RW1C */
+ val |= XHCI_LEGACY_SMI_EVENTS;
+ /* Disable any BIOS SMIs and clear all SMI events*/
+ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
if (usb_is_intel_switchable_xhci(pdev))
usb_enable_xhci_ports(pdev);
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c
index 045cde4..768d542 100644
--- a/drivers/usb/host/uhci-hub.c
+++ b/drivers/usb/host/uhci-hub.c
@@ -196,11 +196,12 @@
status = get_hub_status_data(uhci, buf);
switch (uhci->rh_state) {
- case UHCI_RH_SUSPENDING:
case UHCI_RH_SUSPENDED:
/* if port change, ask to be resumed */
- if (status || uhci->resuming_ports)
+ if (status || uhci->resuming_ports) {
+ status = 1;
usb_hcd_resume_root_hub(hcd);
+ }
break;
case UHCI_RH_AUTO_STOPPED:
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index e9b0f04..4b436f5 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -119,7 +119,7 @@
xhci_dbg(xhci, " Event Interrupts %s\n",
(temp & CMD_EIE) ? "enabled " : "disabled");
xhci_dbg(xhci, " Host System Error Interrupts %s\n",
- (temp & CMD_EIE) ? "enabled " : "disabled");
+ (temp & CMD_HSEIE) ? "enabled " : "disabled");
xhci_dbg(xhci, " HC has %sfinished light reset\n",
(temp & CMD_LRESET) ? "not " : "");
}
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index c7f3312..377f424 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -62,8 +62,9 @@
/* USB Legacy Support Control and Status Register - section 7.1.2 */
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
#define XHCI_LEGACY_CONTROL_OFFSET (0x04)
-/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
-#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
+/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
+#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
+#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29)
/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */
#define XHCI_L1C (1 << 16)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index cae4c6f..68eaa90 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1796,11 +1796,6 @@
int i;
/* Free the Event Ring Segment Table and the actual Event Ring */
- if (xhci->ir_set) {
- xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
- }
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries)
dma_free_coherent(&pdev->dev, size,
@@ -1812,7 +1807,6 @@
xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n");
- xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
@@ -1841,7 +1835,6 @@
xhci->medium_streams_pool = NULL;
xhci_dbg(xhci, "Freed medium stream array pool\n");
- xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
if (xhci->dcbaa)
dma_free_coherent(&pdev->dev, sizeof(*xhci->dcbaa),
xhci->dcbaa, xhci->dcbaa->dma);
@@ -2459,6 +2452,8 @@
fail:
xhci_warn(xhci, "Couldn't initialize memory\n");
+ xhci_halt(xhci);
+ xhci_reset(xhci);
xhci_mem_cleanup(xhci);
return -ENOMEM;
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index ef98b38..7a856a7 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -95,6 +95,8 @@
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
}
+ if (pdev->vendor == PCI_VENDOR_ID_VIA)
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
}
/* called during probe() after chip reset completes */
@@ -326,7 +328,7 @@
return pci_register_driver(&xhci_pci_driver);
}
-void __exit xhci_unregister_pci(void)
+void xhci_unregister_pci(void)
{
pci_unregister_driver(&xhci_pci_driver);
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6bd9d53..3d9422f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2417,7 +2417,7 @@
u32 irq_pending;
/* Acknowledge the PCI interrupt */
irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
- irq_pending |= 0x3;
+ irq_pending |= IMAN_IP;
xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
}
@@ -2734,7 +2734,7 @@
urb->dev->speed == USB_SPEED_FULL)
urb->interval /= 8;
}
- return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+ return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
}
/*
@@ -3514,7 +3514,7 @@
}
ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
- return xhci_queue_isoc_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index);
+ return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
}
/**** Command Ring Operations ****/
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e1963d4..36641a7 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -106,6 +106,9 @@
STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
if (!ret)
xhci->xhc_state |= XHCI_STATE_HALTED;
+ else
+ xhci_warn(xhci, "Host not halted after %u microseconds.\n",
+ XHCI_MAX_HALT_USEC);
return ret;
}
@@ -664,11 +667,11 @@
xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
- xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
- xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+ xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+ xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
}
static void xhci_restore_registers(struct xhci_hcd *xhci)
@@ -677,10 +680,11 @@
xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
- xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
- xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+ xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
+ xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+ xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
}
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 91074fd..3d69c4b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -205,6 +205,10 @@
#define CMD_PM_INDEX (1 << 11)
/* bits 12:31 are reserved (and should be preserved on writes). */
+/* IMAN - Interrupt Management Register */
+#define IMAN_IP (1 << 1)
+#define IMAN_IE (1 << 0)
+
/* USBSTS - USB status - status bitmasks */
/* HC not running - set to 1 when run/stop bit is cleared. */
#define STS_HALT XHCI_STS_HALT
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 959145b..9dcb68f 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -423,7 +423,7 @@
unsigned i;
unsigned size = max;
- sg = kmalloc(nents * sizeof *sg, GFP_KERNEL);
+ sg = kmalloc_array(nents, sizeof *sg, GFP_KERNEL);
if (!sg)
return NULL;
sg_init_table(sg, nents);
@@ -904,6 +904,9 @@
struct ctrl_ctx context;
int i;
+ if (param->sglen == 0 || param->iterations > UINT_MAX / param->sglen)
+ return -EOPNOTSUPP;
+
spin_lock_init(&context.lock);
context.dev = dev;
init_completion(&context.complete);
@@ -1981,8 +1984,6 @@
/* queued control messaging */
case 10:
- if (param->sglen == 0)
- break;
retval = 0;
dev_info(&intf->dev,
"TEST 10: queue %d control calls, %d times\n",
@@ -2276,6 +2277,8 @@
if (status < 0) {
WARNING(dev, "couldn't get endpoints, %d\n",
status);
+ kfree(dev->buf);
+ kfree(dev);
return status;
}
/* may find bulk or ISO pipes */
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 897edda..7020146 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -99,9 +99,7 @@
usb_put_dev(dev->udev);
if (dev->cntl_urb) {
usb_kill_urb(dev->cntl_urb);
- if (dev->cntl_req)
- usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
- dev->cntl_req, dev->cntl_urb->setup_dma);
+ kfree(dev->cntl_req);
if (dev->cntl_buffer)
usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
dev->cntl_buffer, dev->cntl_urb->transfer_dma);
@@ -234,9 +232,7 @@
}
/* allocate buffer for control req */
- dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
- GFP_KERNEL,
- &dev->cntl_urb->setup_dma);
+ dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL);
if (!dev->cntl_req) {
err("Could not allocate cntl_req");
goto error;
@@ -286,7 +282,7 @@
usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
dev, 1);
- dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
retval = -EIO;
err("Could not submitting URB");
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c
index 97ab975..768b4b5 100644
--- a/drivers/usb/musb/davinci.c
+++ b/drivers/usb/musb/davinci.c
@@ -386,7 +386,7 @@
usb_nop_xceiv_register();
musb->xceiv = usb_get_transceiver();
if (!musb->xceiv)
- return -ENODEV;
+ goto unregister;
musb->mregs += DAVINCI_BASE_OFFSET;
@@ -444,6 +444,7 @@
fail:
usb_put_transceiver(musb->xceiv);
+unregister:
usb_nop_xceiv_unregister();
return -ENODEV;
}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 0f8b829..66aaccf 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -137,6 +137,9 @@
int i = 0;
u8 r;
u8 power;
+ int ret;
+
+ pm_runtime_get_sync(phy->io_dev);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
@@ -154,15 +157,22 @@
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
- if (i == 10000)
- return -ETIMEDOUT;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
- return musb_readb(addr, MUSB_ULPI_REG_DATA);
+ ret = musb_readb(addr, MUSB_ULPI_REG_DATA);
+
+out:
+ pm_runtime_put(phy->io_dev);
+
+ return ret;
}
static int musb_ulpi_write(struct usb_phy *phy, u32 offset, u32 data)
@@ -171,6 +181,9 @@
int i = 0;
u8 r = 0;
u8 power;
+ int ret = 0;
+
+ pm_runtime_get_sync(phy->io_dev);
/* Make sure the transceiver is not in low power mode */
power = musb_readb(addr, MUSB_POWER);
@@ -184,15 +197,20 @@
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
& MUSB_ULPI_REG_CMPLT)) {
i++;
- if (i == 10000)
- return -ETIMEDOUT;
+ if (i == 10000) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
}
r = musb_readb(addr, MUSB_ULPI_REG_CONTROL);
r &= ~MUSB_ULPI_REG_CMPLT;
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, r);
- return 0;
+out:
+ pm_runtime_put(phy->io_dev);
+
+ return ret;
}
#else
#define musb_ulpi_read NULL
@@ -1904,14 +1922,17 @@
if (!musb->isr) {
status = -ENODEV;
- goto fail3;
+ goto fail2;
}
if (!musb->xceiv->io_ops) {
+ musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs;
musb->xceiv->io_ops = &musb_ulpi_access;
}
+ pm_runtime_get_sync(musb->controller);
+
#ifndef CONFIG_MUSB_PIO_ONLY
if (use_dma && dev->dma_mask) {
struct dma_controller *c;
@@ -2023,6 +2044,8 @@
goto fail5;
#endif
+ pm_runtime_put(musb->controller);
+
dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n",
({char *s;
switch (musb->board_mode) {
@@ -2047,6 +2070,9 @@
musb_gadget_cleanup(musb);
fail3:
+ pm_runtime_put_sync(musb->controller);
+
+fail2:
if (musb->irq_wake)
device_init_wakeup(dev, 0);
musb_platform_exit(musb);
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 93de517..f4a40f0 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -449,7 +449,7 @@
* We added this flag to forcefully disable double
* buffering until we get it working.
*/
- unsigned double_buffer_not_ok:1 __deprecated;
+ unsigned double_buffer_not_ok:1;
struct musb_hdrc_config *config;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 79cb0af..ef8d744 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2098,7 +2098,7 @@
}
/* turn off DMA requests, discard state, stop polling ... */
- if (is_in) {
+ if (ep->epnum && is_in) {
/* giveback saves bulk toggle */
csr = musb_h_flush_rxfifo(ep, 0);
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 2ae0bb3..c7785e8 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -282,7 +282,8 @@
static int omap2430_musb_init(struct musb *musb)
{
- u32 l, status = 0;
+ u32 l;
+ int status = 0;
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data;
@@ -301,7 +302,7 @@
status = pm_runtime_get_sync(dev);
if (status < 0) {
- dev_err(dev, "pm_runtime_get_sync FAILED");
+ dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
goto err1;
}
@@ -333,6 +334,7 @@
setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
+ pm_runtime_put_noidle(musb->controller);
return 0;
err1:
@@ -452,14 +454,14 @@
goto err2;
}
+ pm_runtime_enable(&pdev->dev);
+
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err2;
}
- pm_runtime_enable(&pdev->dev);
-
return 0;
err2:
@@ -478,7 +480,6 @@
platform_device_del(glue->musb);
platform_device_put(glue->musb);
- pm_runtime_put(&pdev->dev);
kfree(glue);
return 0;
@@ -491,11 +492,13 @@
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- musb->context.otg_interfsel = musb_readl(musb->mregs,
- OTG_INTERFSEL);
+ if (musb) {
+ musb->context.otg_interfsel = musb_readl(musb->mregs,
+ OTG_INTERFSEL);
- omap2430_low_level_exit(musb);
- usb_phy_set_suspend(musb->xceiv, 1);
+ omap2430_low_level_exit(musb);
+ usb_phy_set_suspend(musb->xceiv, 1);
+ }
return 0;
}
@@ -505,11 +508,13 @@
struct omap2430_glue *glue = dev_get_drvdata(dev);
struct musb *musb = glue_to_musb(glue);
- omap2430_low_level_init(musb);
- musb_writel(musb->mregs, OTG_INTERFSEL,
- musb->context.otg_interfsel);
+ if (musb) {
+ omap2430_low_level_init(musb);
+ musb_writel(musb->mregs, OTG_INTERFSEL,
+ musb->context.otg_interfsel);
- usb_phy_set_suspend(musb->xceiv, 0);
+ usb_phy_set_suspend(musb->xceiv, 0);
+ }
return 0;
}
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 3ece43a..a0a2178 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -96,7 +96,7 @@
struct gpio_vbus_data *gpio_vbus =
container_of(work, struct gpio_vbus_data, work);
struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
- int gpio;
+ int gpio, status;
if (!gpio_vbus->phy.otg->gadget)
return;
@@ -108,7 +108,9 @@
*/
gpio = pdata->gpio_pullup;
if (is_vbus_powered(pdata)) {
+ status = USB_EVENT_VBUS;
gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
+ gpio_vbus->phy.last_event = status;
usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
/* drawing a "unit load" is *always* OK, except for OTG */
@@ -117,6 +119,9 @@
/* optionally enable D+ pullup */
if (gpio_is_valid(gpio))
gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
+
+ atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+ status, gpio_vbus->phy.otg->gadget);
} else {
/* optionally disable D+ pullup */
if (gpio_is_valid(gpio))
@@ -125,7 +130,12 @@
set_vbus_draw(gpio_vbus, 0);
usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
+ status = USB_EVENT_NONE;
gpio_vbus->phy.state = OTG_STATE_B_IDLE;
+ gpio_vbus->phy.last_event = status;
+
+ atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
+ status, gpio_vbus->phy.otg->gadget);
}
}
@@ -287,6 +297,9 @@
irq, err);
goto err_irq;
}
+
+ ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
+
INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 7f547dc..ed8adb0 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -60,8 +60,6 @@
retval = -ENODEV;
goto exit;
}
- if (port->dev_state != PORT_REGISTERING)
- goto exit;
driver = port->serial->type;
if (driver->port_probe) {
@@ -98,9 +96,6 @@
if (!port)
return -ENODEV;
- if (port->dev_state != PORT_UNREGISTERING)
- return retval;
-
device_remove_file(&port->dev, &dev_attr_port_number);
driver = port->serial->type;
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 0310e2d..ec30f95 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -287,7 +287,8 @@
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- port_priv->bInterfaceNumber, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size,
+ USB_CTRL_GET_TIMEOUT);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
@@ -340,12 +341,14 @@
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
- port_priv->bInterfaceNumber, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size,
+ USB_CTRL_SET_TIMEOUT);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
- port_priv->bInterfaceNumber, NULL, 0, 300);
+ port_priv->bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
}
kfree(buf);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index ff8605b..02e7f2d 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -75,7 +75,8 @@
unsigned long last_dtr_rts; /* saved modem control outputs */
struct async_icount icount;
wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
- char prev_status, diff_status; /* Used for TIOCMIWAIT */
+ char prev_status; /* Used for TIOCMIWAIT */
+ bool dev_gone; /* Used to abort TIOCMIWAIT */
char transmit_empty; /* If transmitter is empty or not */
struct usb_serial_port *port;
__u16 interface; /* FT2232C, FT2232H or FT4232H port interface
@@ -1681,6 +1682,7 @@
init_waitqueue_head(&priv->delta_msr_wait);
priv->flags = ASYNC_LOW_LATENCY;
+ priv->dev_gone = false;
if (quirk && quirk->port_probe)
quirk->port_probe(priv);
@@ -1839,6 +1841,9 @@
dbg("%s", __func__);
+ priv->dev_gone = true;
+ wake_up_interruptible_all(&priv->delta_msr_wait);
+
remove_sysfs_attrs(port);
kref_put(&priv->kref, ftdi_sio_priv_release);
@@ -1982,17 +1987,19 @@
N.B. packet may be processed more than once, but differences
are only processed once. */
status = packet[0] & FTDI_STATUS_B0_MASK;
- if (status & FTDI_RS0_CTS)
- priv->icount.cts++;
- if (status & FTDI_RS0_DSR)
- priv->icount.dsr++;
- if (status & FTDI_RS0_RI)
- priv->icount.rng++;
- if (status & FTDI_RS0_RLSD)
- priv->icount.dcd++;
if (status != priv->prev_status) {
- priv->diff_status |= status ^ priv->prev_status;
- wake_up_interruptible(&priv->delta_msr_wait);
+ char diff_status = status ^ priv->prev_status;
+
+ if (diff_status & FTDI_RS0_CTS)
+ priv->icount.cts++;
+ if (diff_status & FTDI_RS0_DSR)
+ priv->icount.dsr++;
+ if (diff_status & FTDI_RS0_RI)
+ priv->icount.rng++;
+ if (diff_status & FTDI_RS0_RLSD)
+ priv->icount.dcd++;
+
+ wake_up_interruptible_all(&priv->delta_msr_wait);
priv->prev_status = status;
}
@@ -2395,15 +2402,12 @@
*/
case TIOCMIWAIT:
cprev = priv->icount;
- while (1) {
+ while (!priv->dev_gone) {
interruptible_sleep_on(&priv->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
cnow = priv->icount;
- if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
- cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
- return -EIO; /* no change => error */
if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
@@ -2412,7 +2416,7 @@
}
cprev = cnow;
}
- /* not reached */
+ return -EIO;
break;
case TIOCSERGETLSR:
return get_lsr_info(port, (struct serial_struct __user *)arg);
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c
index 6e1622f..08d16e8 100644
--- a/drivers/usb/serial/metro-usb.c
+++ b/drivers/usb/serial/metro-usb.c
@@ -27,8 +27,8 @@
/* Product information. */
#define FOCUS_VENDOR_ID 0x0C2E
-#define FOCUS_PRODUCT_ID 0x0720
-#define FOCUS_PRODUCT_ID_UNI 0x0710
+#define FOCUS_PRODUCT_ID_BI 0x0720
+#define FOCUS_PRODUCT_ID_UNI 0x0700
#define METROUSB_SET_REQUEST_TYPE 0x40
#define METROUSB_SET_MODEM_CTRL_REQUEST 10
@@ -47,7 +47,7 @@
/* Device table list. */
static struct usb_device_id id_table[] = {
- { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID) },
+ { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) },
{ USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) },
{ }, /* Terminating entry. */
};
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 836cfa9..f4465cc 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -708,6 +708,7 @@
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) },
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ff4a174..a1a9062 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -420,7 +420,7 @@
control = priv->line_control;
if ((cflag & CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
- else
+ else if ((old_termios->c_cflag & CBAUD) == B0)
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
if (control != priv->line_control) {
control = priv->line_control;
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index f14465a..8c8bf80 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -221,7 +221,7 @@
};
/* 'blacklist' of interfaces not served by this driver */
-static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
static const struct sierra_iface_info direct_ip_interface_blacklist = {
.infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
.ifaceinfo = direct_ip_non_serial_ifaces,
@@ -298,6 +298,9 @@
/* Sierra Wireless HSPA Non-Composite Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
+ { USB_DEVICE(0x1199, 0x68A2), /* Sierra Wireless MC77xx in QMI mode */
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 69230f0..97355a1 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1059,6 +1059,12 @@
serial->attached = 1;
}
+ /* Avoid race with tty_open and serial_install by setting the
+ * disconnected flag and not clearing it until all ports have been
+ * registered.
+ */
+ serial->disconnected = 1;
+
if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error;
@@ -1070,19 +1076,16 @@
port = serial->port[i];
dev_set_name(&port->dev, "ttyUSB%d", port->number);
dbg ("%s - registering %s", __func__, dev_name(&port->dev));
- port->dev_state = PORT_REGISTERING;
device_enable_async_suspend(&port->dev);
retval = device_add(&port->dev);
- if (retval) {
+ if (retval)
dev_err(&port->dev, "Error registering port device, "
"continuing\n");
- port->dev_state = PORT_UNREGISTERED;
- } else {
- port->dev_state = PORT_REGISTERED;
- }
}
+ serial->disconnected = 0;
+
usb_serial_console_init(debug, minor);
exit:
@@ -1124,22 +1127,8 @@
}
kill_traffic(port);
cancel_work_sync(&port->work);
- if (port->dev_state == PORT_REGISTERED) {
-
- /* Make sure the port is bound so that the
- * driver's port_remove method is called.
- */
- if (!port->dev.driver) {
- int rc;
-
- port->dev.driver =
- &serial->type->driver;
- rc = device_bind_driver(&port->dev);
- }
- port->dev_state = PORT_UNREGISTERING;
+ if (device_is_registered(&port->dev))
device_del(&port->dev);
- port->dev_state = PORT_UNREGISTERED;
- }
}
}
serial->type->disconnect(serial);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index c18538e..2653e73 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -132,6 +132,35 @@
#undef COMPLIANT_DEV
#undef USUAL_DEV
+#ifdef CONFIG_LOCKDEP
+
+static struct lock_class_key us_interface_key[USB_MAXINTERFACES];
+
+static void us_set_lock_class(struct mutex *mutex,
+ struct usb_interface *intf)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_host_config *config = udev->actconfig;
+ int i;
+
+ for (i = 0; i < config->desc.bNumInterfaces; i++) {
+ if (config->interface[i] == intf)
+ break;
+ }
+
+ BUG_ON(i == config->desc.bNumInterfaces);
+
+ lockdep_set_class(mutex, &us_interface_key[i]);
+}
+
+#else
+
+static void us_set_lock_class(struct mutex *mutex,
+ struct usb_interface *intf)
+{
+}
+
+#endif
#ifdef CONFIG_PM /* Minimal support for suspend and resume */
@@ -895,6 +924,7 @@
*pus = us = host_to_us(host);
memset(us, 0, sizeof(struct us_data));
mutex_init(&(us->dev_mutex));
+ us_set_lock_class(&us->dev_mutex, intf);
init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 66797e9..810c90a 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -645,7 +645,8 @@
dev_err(dev, "NEEP: URB error %d\n", urb->status);
}
result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result < 0) {
+ if (result < 0 && result != -ENODEV && result != -EPERM) {
+ /* ignoring unrecoverable errors */
dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
result);
goto error;
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c
index a269937..8cb71bb 100644
--- a/drivers/uwb/neh.c
+++ b/drivers/uwb/neh.c
@@ -107,6 +107,7 @@
u8 evt_type;
__le16 evt;
u8 context;
+ u8 completed;
uwb_rc_cmd_cb_f cb;
void *arg;
@@ -409,6 +410,7 @@
struct device *dev = &rc->uwb_dev.dev;
struct uwb_rc_neh *neh;
struct uwb_rceb *notif;
+ unsigned long flags;
if (rceb->bEventContext == 0) {
notif = kmalloc(size, GFP_ATOMIC);
@@ -422,7 +424,11 @@
} else {
neh = uwb_rc_neh_lookup(rc, rceb);
if (neh) {
- del_timer_sync(&neh->timer);
+ spin_lock_irqsave(&rc->neh_lock, flags);
+ /* to guard against a timeout */
+ neh->completed = 1;
+ del_timer(&neh->timer);
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
uwb_rc_neh_cb(neh, rceb, size);
} else
dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n",
@@ -568,6 +574,10 @@
unsigned long flags;
spin_lock_irqsave(&rc->neh_lock, flags);
+ if (neh->completed) {
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
+ return;
+ }
if (neh->context)
__uwb_rc_neh_rm(rc, neh);
else
diff --git a/drivers/uwb/uwb-debug.c b/drivers/uwb/uwb-debug.c
index 2eecec0..6ec45be 100644
--- a/drivers/uwb/uwb-debug.c
+++ b/drivers/uwb/uwb-debug.c
@@ -159,13 +159,6 @@
return uwb_rc_ie_rm(rc, ie_to_rm->data[0]);
}
-static int command_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t command_write(struct file *file, const char __user *buf,
size_t len, loff_t *off)
{
@@ -206,7 +199,7 @@
}
static const struct file_operations command_fops = {
- .open = command_open,
+ .open = simple_open,
.write = command_write,
.read = NULL,
.llseek = no_llseek,
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index f0da2c3..1f21d2a 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -238,7 +238,7 @@
vq->heads[vq->upend_idx].len = len;
ubuf->callback = vhost_zerocopy_callback;
- ubuf->arg = vq->ubufs;
+ ubuf->ctx = vq->ubufs;
ubuf->desc = vq->upend_idx;
msg.msg_control = ubuf;
msg.msg_controllen = sizeof(ubuf);
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index fc9a1d7..3de00d9 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -155,7 +155,7 @@
vhost_test_stop(n, &private);
vhost_test_flush(n);
- vhost_dev_cleanup(&n->dev);
+ vhost_dev_cleanup(&n->dev, false);
/* We do an extra flush before freeing memory,
* since jobs can re-queue themselves. */
vhost_test_flush(n);
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 947f00d..51e4c1e 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1598,10 +1598,9 @@
kfree(ubufs);
}
-void vhost_zerocopy_callback(void *arg)
+void vhost_zerocopy_callback(struct ubuf_info *ubuf)
{
- struct ubuf_info *ubuf = arg;
- struct vhost_ubuf_ref *ubufs = ubuf->arg;
+ struct vhost_ubuf_ref *ubufs = ubuf->ctx;
struct vhost_virtqueue *vq = ubufs->vq;
/* set len = 1 to mark this desc buffers done DMA */
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
index 8dcf4cc..8de1fd5 100644
--- a/drivers/vhost/vhost.h
+++ b/drivers/vhost/vhost.h
@@ -188,7 +188,7 @@
int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
unsigned int log_num, u64 len);
-void vhost_zerocopy_callback(void *arg);
+void vhost_zerocopy_callback(struct ubuf_info *);
int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
#define vq_err(vq, fmt, ...) do { \
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index befcbd8..ffbce45 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -499,7 +499,8 @@
au1100fb_fix.mmio_start = regs_res->start;
au1100fb_fix.mmio_len = resource_size(regs_res);
- if (!devm_request_mem_region(au1100fb_fix.mmio_start,
+ if (!devm_request_mem_region(&dev->dev,
+ au1100fb_fix.mmio_start,
au1100fb_fix.mmio_len,
DRIVER_NAME)) {
print_err("fail to lock memory region at 0x%08lx",
@@ -516,7 +517,7 @@
fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
- fbdev->fb_mem = dmam_alloc_coherent(&dev->dev, &dev->dev,
+ fbdev->fb_mem = dmam_alloc_coherent(&dev->dev,
PAGE_ALIGN(fbdev->fb_len),
&fbdev->fb_phys, GFP_KERNEL);
if (!fbdev->fb_mem) {
diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c
index 3e9a773..7ca79f0 100644
--- a/drivers/video/au1200fb.c
+++ b/drivers/video/au1200fb.c
@@ -1724,7 +1724,7 @@
/* Allocate the framebuffer to the maximum screen size */
fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8;
- fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev, &dev->dev,
+ fbdev->fb_mem = dmam_alloc_noncoherent(&dev->dev,
PAGE_ALIGN(fbdev->fb_len),
&fbdev->fb_phys, GFP_KERNEL);
if (!fbdev->fb_mem) {
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 7ed9991..af16884 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -245,6 +245,12 @@
If you have a LCD backlight connected to the WLED output of DA9030
or DA9034 WLED output, say Y here to enable this driver.
+config BACKLIGHT_DA9052
+ tristate "Dialog DA9052/DA9053 WLED"
+ depends on PMIC_DA9052
+ help
+ Enable the Backlight Driver for DA9052-BC and DA9053-AA/Bx PMICs.
+
config BACKLIGHT_MAX8925
tristate "Backlight driver for MAX8925"
depends on MFD_MAX8925
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 8071eb6..36855ae 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -29,6 +29,7 @@
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
+obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o
obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
new file mode 100644
index 0000000..b628d68
--- /dev/null
+++ b/drivers/video/backlight/da9052_bl.c
@@ -0,0 +1,187 @@
+/*
+ * Backlight Driver for Dialog DA9052 PMICs
+ *
+ * Copyright(c) 2012 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/reg.h>
+
+#define DA9052_MAX_BRIGHTNESS 0xFF
+
+enum {
+ DA9052_WLEDS_OFF,
+ DA9052_WLEDS_ON,
+};
+
+enum {
+ DA9052_TYPE_WLED1,
+ DA9052_TYPE_WLED2,
+ DA9052_TYPE_WLED3,
+};
+
+static unsigned char wled_bank[] = {
+ DA9052_LED1_CONF_REG,
+ DA9052_LED2_CONF_REG,
+ DA9052_LED3_CONF_REG,
+};
+
+struct da9052_bl {
+ struct da9052 *da9052;
+ uint brightness;
+ uint state;
+ uint led_reg;
+};
+
+static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
+{
+ unsigned char boost_en;
+ unsigned char i_sink;
+ int ret;
+
+ boost_en = 0x3F;
+ i_sink = 0xFF;
+ if (wleds->state == DA9052_WLEDS_OFF) {
+ boost_en = 0x00;
+ i_sink = 0x00;
+ }
+
+ ret = da9052_reg_write(wleds->da9052, DA9052_BOOST_REG, boost_en);
+ if (ret < 0)
+ return ret;
+
+ ret = da9052_reg_write(wleds->da9052, DA9052_LED_CONT_REG, i_sink);
+ if (ret < 0)
+ return ret;
+
+ ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], 0x0);
+ if (ret < 0)
+ return ret;
+
+ msleep(10);
+
+ if (wleds->brightness) {
+ ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg],
+ wleds->brightness);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int da9052_backlight_update_status(struct backlight_device *bl)
+{
+ int brightness = bl->props.brightness;
+ struct da9052_bl *wleds = bl_get_data(bl);
+
+ wleds->brightness = brightness;
+ wleds->state = DA9052_WLEDS_ON;
+
+ return da9052_adjust_wled_brightness(wleds);
+}
+
+static int da9052_backlight_get_brightness(struct backlight_device *bl)
+{
+ struct da9052_bl *wleds = bl_get_data(bl);
+
+ return wleds->brightness;
+}
+
+static const struct backlight_ops da9052_backlight_ops = {
+ .update_status = da9052_backlight_update_status,
+ .get_brightness = da9052_backlight_get_brightness,
+};
+
+static int da9052_backlight_probe(struct platform_device *pdev)
+{
+ struct backlight_device *bl;
+ struct backlight_properties props;
+ struct da9052_bl *wleds;
+
+ wleds = devm_kzalloc(&pdev->dev, sizeof(struct da9052_bl), GFP_KERNEL);
+ if (!wleds)
+ return -ENOMEM;
+
+ wleds->da9052 = dev_get_drvdata(pdev->dev.parent);
+ wleds->brightness = 0;
+ wleds->led_reg = platform_get_device_id(pdev)->driver_data;
+ wleds->state = DA9052_WLEDS_OFF;
+
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = DA9052_MAX_BRIGHTNESS;
+
+ bl = backlight_device_register(pdev->name, wleds->da9052->dev, wleds,
+ &da9052_backlight_ops, &props);
+ if (IS_ERR(bl)) {
+ dev_err(&pdev->dev, "Failed to register backlight\n");
+ devm_kfree(&pdev->dev, wleds);
+ return PTR_ERR(bl);
+ }
+
+ bl->props.max_brightness = DA9052_MAX_BRIGHTNESS;
+ bl->props.brightness = 0;
+ platform_set_drvdata(pdev, bl);
+
+ return da9052_adjust_wled_brightness(wleds);
+}
+
+static int da9052_backlight_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct da9052_bl *wleds = bl_get_data(bl);
+
+ wleds->brightness = 0;
+ wleds->state = DA9052_WLEDS_OFF;
+ da9052_adjust_wled_brightness(wleds);
+ backlight_device_unregister(bl);
+ devm_kfree(&pdev->dev, wleds);
+
+ return 0;
+}
+
+static struct platform_device_id da9052_wled_ids[] = {
+ {
+ .name = "da9052-wled1",
+ .driver_data = DA9052_TYPE_WLED1,
+ },
+ {
+ .name = "da9052-wled2",
+ .driver_data = DA9052_TYPE_WLED2,
+ },
+ {
+ .name = "da9052-wled3",
+ .driver_data = DA9052_TYPE_WLED3,
+ },
+};
+
+static struct platform_driver da9052_wled_driver = {
+ .probe = da9052_backlight_probe,
+ .remove = da9052_backlight_remove,
+ .id_table = da9052_wled_ids,
+ .driver = {
+ .name = "da9052-wled",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(da9052_wled_driver);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Backlight driver for DA9052 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-backlight");
diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c
index be20b5c..3a6d541 100644
--- a/drivers/video/backlight/locomolcd.c
+++ b/drivers/video/backlight/locomolcd.c
@@ -229,14 +229,7 @@
static int __init locomolcd_init(void)
{
- int ret = locomo_driver_register(&poodle_lcd_driver);
- if (ret)
- return ret;
-
-#ifdef CONFIG_SA1100_COLLIE
- sa1100fb_lcd_power = locomolcd_power;
-#endif
- return 0;
+ return locomo_driver_register(&poodle_lcd_driver);
}
static void __exit locomolcd_exit(void)
diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/bfin-lq035q1-fb.c
index 86922ac..353c02f 100644
--- a/drivers/video/bfin-lq035q1-fb.c
+++ b/drivers/video/bfin-lq035q1-fb.c
@@ -13,6 +13,7 @@
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/fb.h>
+#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/types.h>
diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/kyro/STG4000Reg.h
index 5d62698..50f4670 100644
--- a/drivers/video/kyro/STG4000Reg.h
+++ b/drivers/video/kyro/STG4000Reg.h
@@ -73,210 +73,210 @@
/* Register Table */
typedef struct {
/* 0h */
- volatile unsigned long Thread0Enable; /* 0x0000 */
- volatile unsigned long Thread1Enable; /* 0x0004 */
- volatile unsigned long Thread0Recover; /* 0x0008 */
- volatile unsigned long Thread1Recover; /* 0x000C */
- volatile unsigned long Thread0Step; /* 0x0010 */
- volatile unsigned long Thread1Step; /* 0x0014 */
- volatile unsigned long VideoInStatus; /* 0x0018 */
- volatile unsigned long Core2InSignStart; /* 0x001C */
- volatile unsigned long Core1ResetVector; /* 0x0020 */
- volatile unsigned long Core1ROMOffset; /* 0x0024 */
- volatile unsigned long Core1ArbiterPriority; /* 0x0028 */
- volatile unsigned long VideoInControl; /* 0x002C */
- volatile unsigned long VideoInReg0CtrlA; /* 0x0030 */
- volatile unsigned long VideoInReg0CtrlB; /* 0x0034 */
- volatile unsigned long VideoInReg1CtrlA; /* 0x0038 */
- volatile unsigned long VideoInReg1CtrlB; /* 0x003C */
- volatile unsigned long Thread0Kicker; /* 0x0040 */
- volatile unsigned long Core2InputSign; /* 0x0044 */
- volatile unsigned long Thread0ProgCtr; /* 0x0048 */
- volatile unsigned long Thread1ProgCtr; /* 0x004C */
- volatile unsigned long Thread1Kicker; /* 0x0050 */
- volatile unsigned long GPRegister1; /* 0x0054 */
- volatile unsigned long GPRegister2; /* 0x0058 */
- volatile unsigned long GPRegister3; /* 0x005C */
- volatile unsigned long GPRegister4; /* 0x0060 */
- volatile unsigned long SerialIntA; /* 0x0064 */
+ volatile u32 Thread0Enable; /* 0x0000 */
+ volatile u32 Thread1Enable; /* 0x0004 */
+ volatile u32 Thread0Recover; /* 0x0008 */
+ volatile u32 Thread1Recover; /* 0x000C */
+ volatile u32 Thread0Step; /* 0x0010 */
+ volatile u32 Thread1Step; /* 0x0014 */
+ volatile u32 VideoInStatus; /* 0x0018 */
+ volatile u32 Core2InSignStart; /* 0x001C */
+ volatile u32 Core1ResetVector; /* 0x0020 */
+ volatile u32 Core1ROMOffset; /* 0x0024 */
+ volatile u32 Core1ArbiterPriority; /* 0x0028 */
+ volatile u32 VideoInControl; /* 0x002C */
+ volatile u32 VideoInReg0CtrlA; /* 0x0030 */
+ volatile u32 VideoInReg0CtrlB; /* 0x0034 */
+ volatile u32 VideoInReg1CtrlA; /* 0x0038 */
+ volatile u32 VideoInReg1CtrlB; /* 0x003C */
+ volatile u32 Thread0Kicker; /* 0x0040 */
+ volatile u32 Core2InputSign; /* 0x0044 */
+ volatile u32 Thread0ProgCtr; /* 0x0048 */
+ volatile u32 Thread1ProgCtr; /* 0x004C */
+ volatile u32 Thread1Kicker; /* 0x0050 */
+ volatile u32 GPRegister1; /* 0x0054 */
+ volatile u32 GPRegister2; /* 0x0058 */
+ volatile u32 GPRegister3; /* 0x005C */
+ volatile u32 GPRegister4; /* 0x0060 */
+ volatile u32 SerialIntA; /* 0x0064 */
- volatile unsigned long Fill0[6]; /* GAP 0x0068 - 0x007C */
+ volatile u32 Fill0[6]; /* GAP 0x0068 - 0x007C */
- volatile unsigned long SoftwareReset; /* 0x0080 */
- volatile unsigned long SerialIntB; /* 0x0084 */
+ volatile u32 SoftwareReset; /* 0x0080 */
+ volatile u32 SerialIntB; /* 0x0084 */
- volatile unsigned long Fill1[37]; /* GAP 0x0088 - 0x011C */
+ volatile u32 Fill1[37]; /* GAP 0x0088 - 0x011C */
- volatile unsigned long ROMELQV; /* 0x011C */
- volatile unsigned long WLWH; /* 0x0120 */
- volatile unsigned long ROMELWL; /* 0x0124 */
+ volatile u32 ROMELQV; /* 0x011C */
+ volatile u32 WLWH; /* 0x0120 */
+ volatile u32 ROMELWL; /* 0x0124 */
- volatile unsigned long dwFill_1; /* GAP 0x0128 */
+ volatile u32 dwFill_1; /* GAP 0x0128 */
- volatile unsigned long IntStatus; /* 0x012C */
- volatile unsigned long IntMask; /* 0x0130 */
- volatile unsigned long IntClear; /* 0x0134 */
+ volatile u32 IntStatus; /* 0x012C */
+ volatile u32 IntMask; /* 0x0130 */
+ volatile u32 IntClear; /* 0x0134 */
- volatile unsigned long Fill2[6]; /* GAP 0x0138 - 0x014C */
+ volatile u32 Fill2[6]; /* GAP 0x0138 - 0x014C */
- volatile unsigned long ROMGPIOA; /* 0x0150 */
- volatile unsigned long ROMGPIOB; /* 0x0154 */
- volatile unsigned long ROMGPIOC; /* 0x0158 */
- volatile unsigned long ROMGPIOD; /* 0x015C */
+ volatile u32 ROMGPIOA; /* 0x0150 */
+ volatile u32 ROMGPIOB; /* 0x0154 */
+ volatile u32 ROMGPIOC; /* 0x0158 */
+ volatile u32 ROMGPIOD; /* 0x015C */
- volatile unsigned long Fill3[2]; /* GAP 0x0160 - 0x0168 */
+ volatile u32 Fill3[2]; /* GAP 0x0160 - 0x0168 */
- volatile unsigned long AGPIntID; /* 0x0168 */
- volatile unsigned long AGPIntClassCode; /* 0x016C */
- volatile unsigned long AGPIntBIST; /* 0x0170 */
- volatile unsigned long AGPIntSSID; /* 0x0174 */
- volatile unsigned long AGPIntPMCSR; /* 0x0178 */
- volatile unsigned long VGAFrameBufBase; /* 0x017C */
- volatile unsigned long VGANotify; /* 0x0180 */
- volatile unsigned long DACPLLMode; /* 0x0184 */
- volatile unsigned long Core1VideoClockDiv; /* 0x0188 */
- volatile unsigned long AGPIntStat; /* 0x018C */
+ volatile u32 AGPIntID; /* 0x0168 */
+ volatile u32 AGPIntClassCode; /* 0x016C */
+ volatile u32 AGPIntBIST; /* 0x0170 */
+ volatile u32 AGPIntSSID; /* 0x0174 */
+ volatile u32 AGPIntPMCSR; /* 0x0178 */
+ volatile u32 VGAFrameBufBase; /* 0x017C */
+ volatile u32 VGANotify; /* 0x0180 */
+ volatile u32 DACPLLMode; /* 0x0184 */
+ volatile u32 Core1VideoClockDiv; /* 0x0188 */
+ volatile u32 AGPIntStat; /* 0x018C */
/*
- volatile unsigned long Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
- volatile unsigned long Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
- volatile unsigned long Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
- volatile unsigned long Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
- volatile unsigned long Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
+ volatile u32 Fill4[0x0400/4 - 0x0190/4]; //GAP 0x0190 - 0x0400
+ volatile u32 Fill5[0x05FC/4 - 0x0400/4]; //GAP 0x0400 - 0x05FC Fog Table
+ volatile u32 Fill6[0x0604/4 - 0x0600/4]; //GAP 0x0600 - 0x0604
+ volatile u32 Fill7[0x0680/4 - 0x0608/4]; //GAP 0x0608 - 0x0680
+ volatile u32 Fill8[0x07FC/4 - 0x0684/4]; //GAP 0x0684 - 0x07FC
*/
- volatile unsigned long Fill4[412]; /* 0x0190 - 0x07FC */
+ volatile u32 Fill4[412]; /* 0x0190 - 0x07FC */
- volatile unsigned long TACtrlStreamBase; /* 0x0800 */
- volatile unsigned long TAObjDataBase; /* 0x0804 */
- volatile unsigned long TAPtrDataBase; /* 0x0808 */
- volatile unsigned long TARegionDataBase; /* 0x080C */
- volatile unsigned long TATailPtrBase; /* 0x0810 */
- volatile unsigned long TAPtrRegionSize; /* 0x0814 */
- volatile unsigned long TAConfiguration; /* 0x0818 */
- volatile unsigned long TAObjDataStartAddr; /* 0x081C */
- volatile unsigned long TAObjDataEndAddr; /* 0x0820 */
- volatile unsigned long TAXScreenClip; /* 0x0824 */
- volatile unsigned long TAYScreenClip; /* 0x0828 */
- volatile unsigned long TARHWClamp; /* 0x082C */
- volatile unsigned long TARHWCompare; /* 0x0830 */
- volatile unsigned long TAStart; /* 0x0834 */
- volatile unsigned long TAObjReStart; /* 0x0838 */
- volatile unsigned long TAPtrReStart; /* 0x083C */
- volatile unsigned long TAStatus1; /* 0x0840 */
- volatile unsigned long TAStatus2; /* 0x0844 */
- volatile unsigned long TAIntStatus; /* 0x0848 */
- volatile unsigned long TAIntMask; /* 0x084C */
+ volatile u32 TACtrlStreamBase; /* 0x0800 */
+ volatile u32 TAObjDataBase; /* 0x0804 */
+ volatile u32 TAPtrDataBase; /* 0x0808 */
+ volatile u32 TARegionDataBase; /* 0x080C */
+ volatile u32 TATailPtrBase; /* 0x0810 */
+ volatile u32 TAPtrRegionSize; /* 0x0814 */
+ volatile u32 TAConfiguration; /* 0x0818 */
+ volatile u32 TAObjDataStartAddr; /* 0x081C */
+ volatile u32 TAObjDataEndAddr; /* 0x0820 */
+ volatile u32 TAXScreenClip; /* 0x0824 */
+ volatile u32 TAYScreenClip; /* 0x0828 */
+ volatile u32 TARHWClamp; /* 0x082C */
+ volatile u32 TARHWCompare; /* 0x0830 */
+ volatile u32 TAStart; /* 0x0834 */
+ volatile u32 TAObjReStart; /* 0x0838 */
+ volatile u32 TAPtrReStart; /* 0x083C */
+ volatile u32 TAStatus1; /* 0x0840 */
+ volatile u32 TAStatus2; /* 0x0844 */
+ volatile u32 TAIntStatus; /* 0x0848 */
+ volatile u32 TAIntMask; /* 0x084C */
- volatile unsigned long Fill5[235]; /* GAP 0x0850 - 0x0BF8 */
+ volatile u32 Fill5[235]; /* GAP 0x0850 - 0x0BF8 */
- volatile unsigned long TextureAddrThresh; /* 0x0BFC */
- volatile unsigned long Core1Translation; /* 0x0C00 */
- volatile unsigned long TextureAddrReMap; /* 0x0C04 */
- volatile unsigned long RenderOutAGPRemap; /* 0x0C08 */
- volatile unsigned long _3DRegionReadTrans; /* 0x0C0C */
- volatile unsigned long _3DPtrReadTrans; /* 0x0C10 */
- volatile unsigned long _3DParamReadTrans; /* 0x0C14 */
- volatile unsigned long _3DRegionReadThresh; /* 0x0C18 */
- volatile unsigned long _3DPtrReadThresh; /* 0x0C1C */
- volatile unsigned long _3DParamReadThresh; /* 0x0C20 */
- volatile unsigned long _3DRegionReadAGPRemap; /* 0x0C24 */
- volatile unsigned long _3DPtrReadAGPRemap; /* 0x0C28 */
- volatile unsigned long _3DParamReadAGPRemap; /* 0x0C2C */
- volatile unsigned long ZBufferAGPRemap; /* 0x0C30 */
- volatile unsigned long TAIndexAGPRemap; /* 0x0C34 */
- volatile unsigned long TAVertexAGPRemap; /* 0x0C38 */
- volatile unsigned long TAUVAddrTrans; /* 0x0C3C */
- volatile unsigned long TATailPtrCacheTrans; /* 0x0C40 */
- volatile unsigned long TAParamWriteTrans; /* 0x0C44 */
- volatile unsigned long TAPtrWriteTrans; /* 0x0C48 */
- volatile unsigned long TAParamWriteThresh; /* 0x0C4C */
- volatile unsigned long TAPtrWriteThresh; /* 0x0C50 */
- volatile unsigned long TATailPtrCacheAGPRe; /* 0x0C54 */
- volatile unsigned long TAParamWriteAGPRe; /* 0x0C58 */
- volatile unsigned long TAPtrWriteAGPRe; /* 0x0C5C */
- volatile unsigned long SDRAMArbiterConf; /* 0x0C60 */
- volatile unsigned long SDRAMConf0; /* 0x0C64 */
- volatile unsigned long SDRAMConf1; /* 0x0C68 */
- volatile unsigned long SDRAMConf2; /* 0x0C6C */
- volatile unsigned long SDRAMRefresh; /* 0x0C70 */
- volatile unsigned long SDRAMPowerStat; /* 0x0C74 */
+ volatile u32 TextureAddrThresh; /* 0x0BFC */
+ volatile u32 Core1Translation; /* 0x0C00 */
+ volatile u32 TextureAddrReMap; /* 0x0C04 */
+ volatile u32 RenderOutAGPRemap; /* 0x0C08 */
+ volatile u32 _3DRegionReadTrans; /* 0x0C0C */
+ volatile u32 _3DPtrReadTrans; /* 0x0C10 */
+ volatile u32 _3DParamReadTrans; /* 0x0C14 */
+ volatile u32 _3DRegionReadThresh; /* 0x0C18 */
+ volatile u32 _3DPtrReadThresh; /* 0x0C1C */
+ volatile u32 _3DParamReadThresh; /* 0x0C20 */
+ volatile u32 _3DRegionReadAGPRemap; /* 0x0C24 */
+ volatile u32 _3DPtrReadAGPRemap; /* 0x0C28 */
+ volatile u32 _3DParamReadAGPRemap; /* 0x0C2C */
+ volatile u32 ZBufferAGPRemap; /* 0x0C30 */
+ volatile u32 TAIndexAGPRemap; /* 0x0C34 */
+ volatile u32 TAVertexAGPRemap; /* 0x0C38 */
+ volatile u32 TAUVAddrTrans; /* 0x0C3C */
+ volatile u32 TATailPtrCacheTrans; /* 0x0C40 */
+ volatile u32 TAParamWriteTrans; /* 0x0C44 */
+ volatile u32 TAPtrWriteTrans; /* 0x0C48 */
+ volatile u32 TAParamWriteThresh; /* 0x0C4C */
+ volatile u32 TAPtrWriteThresh; /* 0x0C50 */
+ volatile u32 TATailPtrCacheAGPRe; /* 0x0C54 */
+ volatile u32 TAParamWriteAGPRe; /* 0x0C58 */
+ volatile u32 TAPtrWriteAGPRe; /* 0x0C5C */
+ volatile u32 SDRAMArbiterConf; /* 0x0C60 */
+ volatile u32 SDRAMConf0; /* 0x0C64 */
+ volatile u32 SDRAMConf1; /* 0x0C68 */
+ volatile u32 SDRAMConf2; /* 0x0C6C */
+ volatile u32 SDRAMRefresh; /* 0x0C70 */
+ volatile u32 SDRAMPowerStat; /* 0x0C74 */
- volatile unsigned long Fill6[2]; /* GAP 0x0C78 - 0x0C7C */
+ volatile u32 Fill6[2]; /* GAP 0x0C78 - 0x0C7C */
- volatile unsigned long RAMBistData; /* 0x0C80 */
- volatile unsigned long RAMBistCtrl; /* 0x0C84 */
- volatile unsigned long FIFOBistKey; /* 0x0C88 */
- volatile unsigned long RAMBistResult; /* 0x0C8C */
- volatile unsigned long FIFOBistResult; /* 0x0C90 */
+ volatile u32 RAMBistData; /* 0x0C80 */
+ volatile u32 RAMBistCtrl; /* 0x0C84 */
+ volatile u32 FIFOBistKey; /* 0x0C88 */
+ volatile u32 RAMBistResult; /* 0x0C8C */
+ volatile u32 FIFOBistResult; /* 0x0C90 */
/*
- volatile unsigned long Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
- volatile unsigned long Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
+ volatile u32 Fill11[0x0CBC/4 - 0x0C94/4]; //GAP 0x0C94 - 0x0CBC
+ volatile u32 Fill12[0x0CD0/4 - 0x0CC0/4]; //GAP 0x0CC0 - 0x0CD0 3DRegisters
*/
- volatile unsigned long Fill7[16]; /* 0x0c94 - 0x0cd0 */
+ volatile u32 Fill7[16]; /* 0x0c94 - 0x0cd0 */
- volatile unsigned long SDRAMAddrSign; /* 0x0CD4 */
- volatile unsigned long SDRAMDataSign; /* 0x0CD8 */
- volatile unsigned long SDRAMSignConf; /* 0x0CDC */
+ volatile u32 SDRAMAddrSign; /* 0x0CD4 */
+ volatile u32 SDRAMDataSign; /* 0x0CD8 */
+ volatile u32 SDRAMSignConf; /* 0x0CDC */
/* DWFILL; //GAP 0x0CE0 */
- volatile unsigned long dwFill_2;
+ volatile u32 dwFill_2;
- volatile unsigned long ISPSignature; /* 0x0CE4 */
+ volatile u32 ISPSignature; /* 0x0CE4 */
- volatile unsigned long Fill8[454]; /*GAP 0x0CE8 - 0x13FC */
+ volatile u32 Fill8[454]; /*GAP 0x0CE8 - 0x13FC */
- volatile unsigned long DACPrimAddress; /* 0x1400 */
- volatile unsigned long DACPrimSize; /* 0x1404 */
- volatile unsigned long DACCursorAddr; /* 0x1408 */
- volatile unsigned long DACCursorCtrl; /* 0x140C */
- volatile unsigned long DACOverlayAddr; /* 0x1410 */
- volatile unsigned long DACOverlayUAddr; /* 0x1414 */
- volatile unsigned long DACOverlayVAddr; /* 0x1418 */
- volatile unsigned long DACOverlaySize; /* 0x141C */
- volatile unsigned long DACOverlayVtDec; /* 0x1420 */
+ volatile u32 DACPrimAddress; /* 0x1400 */
+ volatile u32 DACPrimSize; /* 0x1404 */
+ volatile u32 DACCursorAddr; /* 0x1408 */
+ volatile u32 DACCursorCtrl; /* 0x140C */
+ volatile u32 DACOverlayAddr; /* 0x1410 */
+ volatile u32 DACOverlayUAddr; /* 0x1414 */
+ volatile u32 DACOverlayVAddr; /* 0x1418 */
+ volatile u32 DACOverlaySize; /* 0x141C */
+ volatile u32 DACOverlayVtDec; /* 0x1420 */
- volatile unsigned long Fill9[9]; /* GAP 0x1424 - 0x1444 */
+ volatile u32 Fill9[9]; /* GAP 0x1424 - 0x1444 */
- volatile unsigned long DACVerticalScal; /* 0x1448 */
- volatile unsigned long DACPixelFormat; /* 0x144C */
- volatile unsigned long DACHorizontalScal; /* 0x1450 */
- volatile unsigned long DACVidWinStart; /* 0x1454 */
- volatile unsigned long DACVidWinEnd; /* 0x1458 */
- volatile unsigned long DACBlendCtrl; /* 0x145C */
- volatile unsigned long DACHorTim1; /* 0x1460 */
- volatile unsigned long DACHorTim2; /* 0x1464 */
- volatile unsigned long DACHorTim3; /* 0x1468 */
- volatile unsigned long DACVerTim1; /* 0x146C */
- volatile unsigned long DACVerTim2; /* 0x1470 */
- volatile unsigned long DACVerTim3; /* 0x1474 */
- volatile unsigned long DACBorderColor; /* 0x1478 */
- volatile unsigned long DACSyncCtrl; /* 0x147C */
- volatile unsigned long DACStreamCtrl; /* 0x1480 */
- volatile unsigned long DACLUTAddress; /* 0x1484 */
- volatile unsigned long DACLUTData; /* 0x1488 */
- volatile unsigned long DACBurstCtrl; /* 0x148C */
- volatile unsigned long DACCrcTrigger; /* 0x1490 */
- volatile unsigned long DACCrcDone; /* 0x1494 */
- volatile unsigned long DACCrcResult1; /* 0x1498 */
- volatile unsigned long DACCrcResult2; /* 0x149C */
- volatile unsigned long DACLinecount; /* 0x14A0 */
+ volatile u32 DACVerticalScal; /* 0x1448 */
+ volatile u32 DACPixelFormat; /* 0x144C */
+ volatile u32 DACHorizontalScal; /* 0x1450 */
+ volatile u32 DACVidWinStart; /* 0x1454 */
+ volatile u32 DACVidWinEnd; /* 0x1458 */
+ volatile u32 DACBlendCtrl; /* 0x145C */
+ volatile u32 DACHorTim1; /* 0x1460 */
+ volatile u32 DACHorTim2; /* 0x1464 */
+ volatile u32 DACHorTim3; /* 0x1468 */
+ volatile u32 DACVerTim1; /* 0x146C */
+ volatile u32 DACVerTim2; /* 0x1470 */
+ volatile u32 DACVerTim3; /* 0x1474 */
+ volatile u32 DACBorderColor; /* 0x1478 */
+ volatile u32 DACSyncCtrl; /* 0x147C */
+ volatile u32 DACStreamCtrl; /* 0x1480 */
+ volatile u32 DACLUTAddress; /* 0x1484 */
+ volatile u32 DACLUTData; /* 0x1488 */
+ volatile u32 DACBurstCtrl; /* 0x148C */
+ volatile u32 DACCrcTrigger; /* 0x1490 */
+ volatile u32 DACCrcDone; /* 0x1494 */
+ volatile u32 DACCrcResult1; /* 0x1498 */
+ volatile u32 DACCrcResult2; /* 0x149C */
+ volatile u32 DACLinecount; /* 0x14A0 */
- volatile unsigned long Fill10[151]; /*GAP 0x14A4 - 0x16FC */
+ volatile u32 Fill10[151]; /*GAP 0x14A4 - 0x16FC */
- volatile unsigned long DigVidPortCtrl; /* 0x1700 */
- volatile unsigned long DigVidPortStat; /* 0x1704 */
+ volatile u32 DigVidPortCtrl; /* 0x1700 */
+ volatile u32 DigVidPortStat; /* 0x1704 */
/*
- volatile unsigned long Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
- volatile unsigned long Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
+ volatile u32 Fill11[0x1FFC/4 - 0x1708/4]; //GAP 0x1708 - 0x1FFC
+ volatile u32 Fill17[0x3000/4 - 0x2FFC/4]; //GAP 0x2000 - 0x2FFC ALUT
*/
- volatile unsigned long Fill11[1598];
+ volatile u32 Fill11[1598];
/* DWFILL; //GAP 0x3000 ALUT 256MB offset */
- volatile unsigned long Fill_3;
+ volatile u32 Fill_3;
} STG4000REG;
diff --git a/drivers/video/msm/mddi.c b/drivers/video/msm/mddi.c
index 4527cbf..b061d70 100644
--- a/drivers/video/msm/mddi.c
+++ b/drivers/video/msm/mddi.c
@@ -420,7 +420,7 @@
mddi_set_auto_hibernate(&mddi->client_data, 1);
}
-static int __init mddi_get_client_caps(struct mddi_info *mddi)
+static int __devinit mddi_get_client_caps(struct mddi_info *mddi)
{
int i, j;
@@ -622,9 +622,9 @@
static struct mddi_info mddi_info[2];
-static int __init mddi_clk_setup(struct platform_device *pdev,
- struct mddi_info *mddi,
- unsigned long clk_rate)
+static int __devinit mddi_clk_setup(struct platform_device *pdev,
+ struct mddi_info *mddi,
+ unsigned long clk_rate)
{
int ret;
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 260cca7..26e83d7 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -815,8 +815,15 @@
par->pmi_setpal = pmi_setpal;
par->ypan = ypan;
- if (par->pmi_setpal || par->ypan)
- uvesafb_vbe_getpmi(task, par);
+ if (par->pmi_setpal || par->ypan) {
+ if (__supported_pte_mask & _PAGE_NX) {
+ par->pmi_setpal = par->ypan = 0;
+ printk(KERN_WARNING "uvesafb: NX protection is actively."
+ "We have better not to use the PMI.\n");
+ } else {
+ uvesafb_vbe_getpmi(task, par);
+ }
+ }
#else
/* The protected mode interface is not available on non-x86. */
par->pmi_setpal = par->ypan = 0;
diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c
index cb4529c..b7f5173 100644
--- a/drivers/video/xen-fbfront.c
+++ b/drivers/video/xen-fbfront.c
@@ -365,7 +365,7 @@
struct fb_info *fb_info;
int fb_size;
int val;
- int ret;
+ int ret = 0;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
@@ -458,26 +458,31 @@
xenfb_init_shared_page(info, fb_info);
ret = xenfb_connect_backend(dev, info);
- if (ret < 0)
- goto error;
+ if (ret < 0) {
+ xenbus_dev_fatal(dev, ret, "xenfb_connect_backend");
+ goto error_fb;
+ }
ret = register_framebuffer(fb_info);
if (ret) {
- fb_deferred_io_cleanup(fb_info);
- fb_dealloc_cmap(&fb_info->cmap);
- framebuffer_release(fb_info);
xenbus_dev_fatal(dev, ret, "register_framebuffer");
- goto error;
+ goto error_fb;
}
info->fb_info = fb_info;
xenfb_make_preferred_console();
return 0;
- error_nomem:
- ret = -ENOMEM;
- xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
+error_fb:
+ fb_deferred_io_cleanup(fb_info);
+ fb_dealloc_cmap(&fb_info->cmap);
+ framebuffer_release(fb_info);
+error_nomem:
+ if (!ret) {
+ ret = -ENOMEM;
+ xenbus_dev_fatal(dev, ret, "allocating device memory");
+ }
+error:
xenfb_remove(dev);
return ret;
}
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 05f0a808..c2d05a8 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -28,6 +28,13 @@
#include <linux/slab.h>
#include <linux/module.h>
+/*
+ * Balloon device works in 4K page units. So each page is pointed to by
+ * multiple balloon pages. All memory counters in this driver are in balloon
+ * page units.
+ */
+#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
+
struct virtio_balloon
{
struct virtio_device *vdev;
@@ -42,8 +49,13 @@
/* Waiting for host to ack the pages we released. */
struct completion acked;
- /* The pages we've told the Host we're not using. */
+ /* Number of balloon pages we've told the Host we're not using. */
unsigned int num_pages;
+ /*
+ * The pages we've told the Host we're not using.
+ * Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
+ * to num_pages above.
+ */
struct list_head pages;
/* The array of pfns we tell the Host about. */
@@ -66,7 +78,13 @@
BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT);
/* Convert pfn from Linux page size to balloon page size. */
- return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT);
+ return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
+}
+
+static struct page *balloon_pfn_to_page(u32 pfn)
+{
+ BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE);
+ return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE);
}
static void balloon_ack(struct virtqueue *vq)
@@ -96,12 +114,23 @@
wait_for_completion(&vb->acked);
}
+static void set_page_pfns(u32 pfns[], struct page *page)
+{
+ unsigned int i;
+
+ /* Set balloon pfns pointing at this page.
+ * Note that the first pfn points at start of the page. */
+ for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
+ pfns[i] = page_to_balloon_pfn(page) + i;
+}
+
static void fill_balloon(struct virtio_balloon *vb, size_t num)
{
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
- for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
+ for (vb->num_pfns = 0; vb->num_pfns < num;
+ vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
__GFP_NOMEMALLOC | __GFP_NOWARN);
if (!page) {
@@ -113,9 +142,9 @@
msleep(200);
break;
}
- vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
+ set_page_pfns(vb->pfns + vb->num_pfns, page);
+ vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
totalram_pages--;
- vb->num_pages++;
list_add(&page->lru, &vb->pages);
}
@@ -130,8 +159,9 @@
{
unsigned int i;
- for (i = 0; i < num; i++) {
- __free_page(pfn_to_page(pfns[i]));
+ /* Find pfns pointing at start of each page, get pages and free them. */
+ for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+ __free_page(balloon_pfn_to_page(pfns[i]));
totalram_pages++;
}
}
@@ -143,11 +173,12 @@
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
- for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
+ for (vb->num_pfns = 0; vb->num_pfns < num;
+ vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
page = list_first_entry(&vb->pages, struct page, lru);
list_del(&page->lru);
- vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
- vb->num_pages--;
+ set_page_pfns(vb->pfns + vb->num_pfns, page);
+ vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}
/*
@@ -234,11 +265,14 @@
static inline s64 towards_target(struct virtio_balloon *vb)
{
- u32 v;
+ __le32 v;
+ s64 target;
+
vb->vdev->config->get(vb->vdev,
offsetof(struct virtio_balloon_config, num_pages),
&v, sizeof(v));
- return (s64)v - vb->num_pages;
+ target = le32_to_cpu(v);
+ return target - vb->num_pages;
}
static void update_balloon_size(struct virtio_balloon *vb)
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index cbc7cee..9f13b89 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -435,16 +435,16 @@
{
reload = SECS_TO_TICKS(soft_margin);
iowrite16(reload, hpwdt_timer_reg);
- iowrite16(0x85, hpwdt_timer_con);
+ iowrite8(0x85, hpwdt_timer_con);
}
static void hpwdt_stop(void)
{
unsigned long data;
- data = ioread16(hpwdt_timer_con);
+ data = ioread8(hpwdt_timer_con);
data &= 0xFE;
- iowrite16(data, hpwdt_timer_con);
+ iowrite8(data, hpwdt_timer_con);
}
static void hpwdt_ping(void)
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index 9424313..ea20c51 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -183,15 +183,17 @@
depends on XEN && X86 && ACPI_PROCESSOR && CPU_FREQ
default m
help
- This ACPI processor uploads Power Management information to the Xen hypervisor.
+ This ACPI processor uploads Power Management information to the Xen
+ hypervisor.
- To do that the driver parses the Power Management data and uploads said
- information to the Xen hypervisor. Then the Xen hypervisor can select the
- proper Cx and Pxx states. It also registers itslef as the SMM so that
- other drivers (such as ACPI cpufreq scaling driver) will not load.
+ To do that the driver parses the Power Management data and uploads
+ said information to the Xen hypervisor. Then the Xen hypervisor can
+ select the proper Cx and Pxx states. It also registers itslef as the
+ SMM so that other drivers (such as ACPI cpufreq scaling driver) will
+ not load.
- To compile this driver as a module, choose M here: the
- module will be called xen_acpi_processor If you do not know what to choose,
- select M here. If the CPUFREQ drivers are built in, select Y here.
+ To compile this driver as a module, choose M here: the module will be
+ called xen_acpi_processor If you do not know what to choose, select
+ M here. If the CPUFREQ drivers are built in, select Y here.
endmenu
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index 4b33acd..0a8a17c 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -274,7 +274,7 @@
static bool pirq_check_eoi_map(unsigned irq)
{
- return test_bit(irq, pirq_eoi_map);
+ return test_bit(pirq_from_irq(irq), pirq_eoi_map);
}
static bool pirq_needs_eoi_flag(unsigned irq)
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 99d8151..1ffd03b 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -722,7 +722,7 @@
vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
if (use_ptemod)
- vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP;
+ vma->vm_flags |= VM_DONTCOPY;
vma->vm_private_data = map;
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index b4d4eac..f100ce2 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -1029,6 +1029,7 @@
int i;
unsigned int max_nr_glist_frames, nr_glist_frames;
unsigned int nr_init_grefs;
+ int ret;
nr_grant_frames = 1;
boot_max_nr_grant_frames = __max_nr_grant_frames();
@@ -1047,12 +1048,16 @@
nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
for (i = 0; i < nr_glist_frames; i++) {
gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
- if (gnttab_list[i] == NULL)
+ if (gnttab_list[i] == NULL) {
+ ret = -ENOMEM;
goto ini_nomem;
+ }
}
- if (gnttab_resume() < 0)
- return -ENODEV;
+ if (gnttab_resume() < 0) {
+ ret = -ENODEV;
+ goto ini_nomem;
+ }
nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
@@ -1070,7 +1075,7 @@
for (i--; i >= 0; i--)
free_page((unsigned long)gnttab_list[i]);
kfree(gnttab_list);
- return -ENOMEM;
+ return ret;
}
EXPORT_SYMBOL_GPL(gnttab_init);
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 9e14ae6..412b96c 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -132,6 +132,7 @@
err = dpm_suspend_end(PMSG_FREEZE);
if (err) {
printk(KERN_ERR "dpm_suspend_end failed: %d\n", err);
+ si.cancelled = 0;
goto out_resume;
}
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 19e6a20..1afb4fb 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -204,7 +204,8 @@
void *
xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags)
+ dma_addr_t *dma_handle, gfp_t flags,
+ struct dma_attrs *attrs)
{
void *ret;
int order = get_order(size);
@@ -253,7 +254,7 @@
void
xen_swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dev_addr)
+ dma_addr_t dev_addr, struct dma_attrs *attrs)
{
int order = get_order(size);
phys_addr_t phys;
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 174b565..0b48579 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -128,7 +128,10 @@
pr_debug(" C%d: %s %d uS\n",
cx->type, cx->desc, (u32)cx->latency);
}
- } else
+ } else if (ret != -EINVAL)
+ /* EINVAL means the ACPI ID is incorrect - meaning the ACPI
+ * table is referencing a non-existing CPU - which can happen
+ * with broken ACPI tables. */
pr_err(DRV_NAME "(CX): Hypervisor error (%d) for ACPI CPU%u\n",
ret, _pr->acpi_id);
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index 63616d7..97f5d26 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -234,7 +234,7 @@
if (dev_data)
dev_data->ack_intr = 0;
- return result;
+ return result > 0 ? 0 : result;
}
static
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index f20c5f1..a31b54d 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -135,7 +135,7 @@
return xenbus_read_otherend_details(xendev, "backend-id", "backend");
}
-static int is_device_connecting(struct device *dev, void *data)
+static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
struct device_driver *drv = data;
@@ -152,16 +152,41 @@
if (drv && (dev->driver != drv))
return 0;
+ if (ignore_nonessential) {
+ /* With older QEMU, for PVonHVM guests the guest config files
+ * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
+ * which is nonsensical as there is no PV FB (there can be
+ * a PVKB) running as HVM guest. */
+
+ if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
+ return 0;
+
+ if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
+ return 0;
+ }
xendrv = to_xenbus_driver(dev->driver);
return (xendev->state < XenbusStateConnected ||
(xendev->state == XenbusStateConnected &&
xendrv->is_ready && !xendrv->is_ready(xendev)));
}
+static int essential_device_connecting(struct device *dev, void *data)
+{
+ return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
+}
+static int non_essential_device_connecting(struct device *dev, void *data)
+{
+ return is_device_connecting(dev, data, false);
+}
-static int exists_connecting_device(struct device_driver *drv)
+static int exists_essential_connecting_device(struct device_driver *drv)
{
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
- is_device_connecting);
+ essential_device_connecting);
+}
+static int exists_non_essential_connecting_device(struct device_driver *drv)
+{
+ return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
+ non_essential_device_connecting);
}
static int print_device_status(struct device *dev, void *data)
@@ -192,6 +217,23 @@
/* We only wait for device setup after most initcalls have run. */
static int ready_to_wait_for_devices;
+static bool wait_loop(unsigned long start, unsigned int max_delay,
+ unsigned int *seconds_waited)
+{
+ if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
+ if (!*seconds_waited)
+ printk(KERN_WARNING "XENBUS: Waiting for "
+ "devices to initialise: ");
+ *seconds_waited += 5;
+ printk("%us...", max_delay - *seconds_waited);
+ if (*seconds_waited == max_delay)
+ return true;
+ }
+
+ schedule_timeout_interruptible(HZ/10);
+
+ return false;
+}
/*
* On a 5-minute timeout, wait for all devices currently configured. We need
* to do this to guarantee that the filesystems and / or network devices
@@ -215,19 +257,14 @@
if (!ready_to_wait_for_devices || !xen_domain())
return;
- while (exists_connecting_device(drv)) {
- if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
- if (!seconds_waited)
- printk(KERN_WARNING "XENBUS: Waiting for "
- "devices to initialise: ");
- seconds_waited += 5;
- printk("%us...", 300 - seconds_waited);
- if (seconds_waited == 300)
- break;
- }
+ while (exists_non_essential_connecting_device(drv))
+ if (wait_loop(start, 30, &seconds_waited))
+ break;
- schedule_timeout_interruptible(HZ/10);
- }
+ /* Skips PVKB and PVFB check.*/
+ while (exists_essential_connecting_device(drv))
+ if (wait_loop(start, 270, &seconds_waited))
+ break;
if (seconds_waited)
printk("\n");
diff --git a/fs/aio.c b/fs/aio.c
index da88760..67a6db3 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -93,9 +93,8 @@
put_page(info->ring_pages[i]);
if (info->mmap_size) {
- down_write(&ctx->mm->mmap_sem);
- do_munmap(ctx->mm, info->mmap_base, info->mmap_size);
- up_write(&ctx->mm->mmap_sem);
+ BUG_ON(ctx->mm != current->mm);
+ vm_munmap(info->mmap_base, info->mmap_size);
}
if (info->ring_pages && info->ring_pages != info->internal_pages)
@@ -389,6 +388,17 @@
"exit_aio:ioctx still alive: %d %d %d\n",
atomic_read(&ctx->users), ctx->dead,
ctx->reqs_active);
+ /*
+ * We don't need to bother with munmap() here -
+ * exit_mmap(mm) is coming and it'll unmap everything.
+ * Since aio_free_ring() uses non-zero ->mmap_size
+ * as indicator that it needs to unmap the area,
+ * just set it to 0; aio_free_ring() is the only
+ * place that uses ->mmap_size, so it's safe.
+ * That way we get all munmap done to current->mm -
+ * all other callers have ctx->mm == current->mm.
+ */
+ ctx->ring_info.mmap_size = 0;
put_ioctx(ctx);
}
}
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index eb1cc92..908e184 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -110,7 +110,6 @@
int sub_version;
int min_proto;
int max_proto;
- int compat_daemon;
unsigned long exp_timeout;
unsigned int type;
int reghost_enabled;
@@ -270,6 +269,17 @@
struct autofs_info *autofs4_new_ino(struct autofs_sb_info *);
void autofs4_clean_ino(struct autofs_info *);
+static inline int autofs_prepare_pipe(struct file *pipe)
+{
+ if (!pipe->f_op || !pipe->f_op->write)
+ return -EINVAL;
+ if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode))
+ return -EINVAL;
+ /* We want a packet pipe */
+ pipe->f_flags |= O_DIRECT;
+ return 0;
+}
+
/* Queue management functions */
int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 9dacb85..aa9103f 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -376,7 +376,7 @@
err = -EBADF;
goto out;
}
- if (!pipe->f_op || !pipe->f_op->write) {
+ if (autofs_prepare_pipe(pipe) < 0) {
err = -EPIPE;
fput(pipe);
goto out;
@@ -385,7 +385,6 @@
sbi->pipefd = pipefd;
sbi->pipe = pipe;
sbi->catatonic = 0;
- sbi->compat_daemon = is_compat_task();
}
out:
mutex_unlock(&sbi->wq_mutex);
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index d8dc002..6e488eb 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -19,7 +19,6 @@
#include <linux/parser.h>
#include <linux/bitops.h>
#include <linux/magic.h>
-#include <linux/compat.h>
#include "autofs_i.h"
#include <linux/module.h>
@@ -225,7 +224,6 @@
set_autofs_type_indirect(&sbi->type);
sbi->min_proto = 0;
sbi->max_proto = 0;
- sbi->compat_daemon = is_compat_task();
mutex_init(&sbi->wq_mutex);
mutex_init(&sbi->pipe_mutex);
spin_lock_init(&sbi->fs_lock);
@@ -292,7 +290,7 @@
printk("autofs: could not open pipe file descriptor\n");
goto fail_dput;
}
- if (!pipe->f_op || !pipe->f_op->write)
+ if (autofs_prepare_pipe(pipe) < 0)
goto fail_fput;
sbi->pipe = pipe;
sbi->pipefd = pipefd;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 9c098db..da8876d 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -91,24 +91,7 @@
return (bytes > 0);
}
-
-/*
- * The autofs_v5 packet was misdesigned.
- *
- * The packets are identical on x86-32 and x86-64, but have different
- * alignment. Which means that 'sizeof()' will give different results.
- * Fix it up for the case of running 32-bit user mode on a 64-bit kernel.
- */
-static noinline size_t autofs_v5_packet_size(struct autofs_sb_info *sbi)
-{
- size_t pktsz = sizeof(struct autofs_v5_packet);
-#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
- if (sbi->compat_daemon > 0)
- pktsz -= 4;
-#endif
- return pktsz;
-}
-
+
static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
struct autofs_wait_queue *wq,
int type)
@@ -172,7 +155,8 @@
{
struct autofs_v5_packet *packet = &pkt.v5_pkt.v5_packet;
- pktsz = autofs_v5_packet_size(sbi);
+ pktsz = sizeof(*packet);
+
packet->wait_queue_token = wq->wait_queue_token;
packet->len = wq->name.len;
memcpy(packet->name, wq->name.name, wq->name.len);
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 2eb12f1..d146e18 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -50,9 +50,7 @@
end = PAGE_ALIGN(end);
if (end > start) {
unsigned long addr;
- down_write(¤t->mm->mmap_sem);
- addr = do_brk(start, end - start);
- up_write(¤t->mm->mmap_sem);
+ addr = vm_brk(start, end - start);
if (BAD_ADDR(addr))
return addr;
}
@@ -280,9 +278,7 @@
pos = 32;
map_size = ex.a_text+ex.a_data;
#endif
- down_write(¤t->mm->mmap_sem);
- error = do_brk(text_addr & PAGE_MASK, map_size);
- up_write(¤t->mm->mmap_sem);
+ error = vm_brk(text_addr & PAGE_MASK, map_size);
if (error != (text_addr & PAGE_MASK)) {
send_sig(SIGKILL, current, 0);
return error;
@@ -313,9 +309,7 @@
if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) {
loff_t pos = fd_offset;
- down_write(¤t->mm->mmap_sem);
- do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
- up_write(¤t->mm->mmap_sem);
+ vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
bprm->file->f_op->read(bprm->file,
(char __user *)N_TXTADDR(ex),
ex.a_text+ex.a_data, &pos);
@@ -325,24 +319,20 @@
goto beyond_if;
}
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
+ error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset);
- up_write(¤t->mm->mmap_sem);
if (error != N_TXTADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
}
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
+ error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
fd_offset + ex.a_text);
- up_write(¤t->mm->mmap_sem);
if (error != N_DATADDR(ex)) {
send_sig(SIGKILL, current, 0);
return error;
@@ -412,9 +402,7 @@
"N_TXTOFF is not page aligned. Please convert library: %s\n",
file->f_path.dentry->d_name.name);
}
- down_write(¤t->mm->mmap_sem);
- do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
- up_write(¤t->mm->mmap_sem);
+ vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
file->f_op->read(file, (char __user *)start_addr,
ex.a_text + ex.a_data, &pos);
@@ -425,12 +413,10 @@
goto out;
}
/* Now use mmap to map the library into memory. */
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+ error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
N_TXTOFF(ex));
- up_write(¤t->mm->mmap_sem);
retval = error;
if (error != start_addr)
goto out;
@@ -438,9 +424,7 @@
len = PAGE_ALIGN(ex.a_text + ex.a_data);
bss = ex.a_text + ex.a_data + ex.a_bss;
if (bss > len) {
- down_write(¤t->mm->mmap_sem);
- error = do_brk(start_addr + len, bss - len);
- up_write(¤t->mm->mmap_sem);
+ error = vm_brk(start_addr + len, bss - len);
retval = error;
if (error != start_addr + len)
goto out;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 48ffb3d..16f7354 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -82,9 +82,7 @@
end = ELF_PAGEALIGN(end);
if (end > start) {
unsigned long addr;
- down_write(¤t->mm->mmap_sem);
- addr = do_brk(start, end - start);
- up_write(¤t->mm->mmap_sem);
+ addr = vm_brk(start, end - start);
if (BAD_ADDR(addr))
return addr;
}
@@ -514,9 +512,7 @@
elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);
/* Map the last of the bss segment */
- down_write(¤t->mm->mmap_sem);
- error = do_brk(elf_bss, last_bss - elf_bss);
- up_write(¤t->mm->mmap_sem);
+ error = vm_brk(elf_bss, last_bss - elf_bss);
if (BAD_ADDR(error))
goto out_close;
}
@@ -962,10 +958,8 @@
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
+ error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, 0);
- up_write(¤t->mm->mmap_sem);
}
#ifdef ELF_PLAT_INIT
@@ -1050,8 +1044,7 @@
eppnt++;
/* Now use mmap to map the library into memory. */
- down_write(¤t->mm->mmap_sem);
- error = do_mmap(file,
+ error = vm_mmap(file,
ELF_PAGESTART(eppnt->p_vaddr),
(eppnt->p_filesz +
ELF_PAGEOFFSET(eppnt->p_vaddr)),
@@ -1059,7 +1052,6 @@
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
(eppnt->p_offset -
ELF_PAGEOFFSET(eppnt->p_vaddr)));
- up_write(¤t->mm->mmap_sem);
if (error != ELF_PAGESTART(eppnt->p_vaddr))
goto out_free_ph;
@@ -1072,11 +1064,8 @@
len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr +
ELF_MIN_ALIGN - 1);
bss = eppnt->p_memsz + eppnt->p_vaddr;
- if (bss > len) {
- down_write(¤t->mm->mmap_sem);
- do_brk(len, bss - len);
- up_write(¤t->mm->mmap_sem);
- }
+ if (bss > len)
+ vm_brk(len, bss - len);
error = 0;
out_free_ph:
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 9bd5612..d390a0f 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -390,21 +390,17 @@
(executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
stack_prot |= PROT_EXEC;
- down_write(¤t->mm->mmap_sem);
- current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
+ current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot,
MAP_PRIVATE | MAP_ANONYMOUS |
MAP_UNINITIALIZED | MAP_GROWSDOWN,
0);
if (IS_ERR_VALUE(current->mm->start_brk)) {
- up_write(¤t->mm->mmap_sem);
retval = current->mm->start_brk;
current->mm->start_brk = 0;
goto error_kill;
}
- up_write(¤t->mm->mmap_sem);
-
current->mm->brk = current->mm->start_brk;
current->mm->context.end_brk = current->mm->start_brk;
current->mm->context.end_brk +=
@@ -955,10 +951,8 @@
if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
mflags |= MAP_EXECUTABLE;
- down_write(&mm->mmap_sem);
- maddr = do_mmap(NULL, load_addr, top - base,
+ maddr = vm_mmap(NULL, load_addr, top - base,
PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
- up_write(&mm->mmap_sem);
if (IS_ERR_VALUE(maddr))
return (int) maddr;
@@ -1096,10 +1090,8 @@
/* create the mapping */
disp = phdr->p_vaddr & ~PAGE_MASK;
- down_write(&mm->mmap_sem);
- maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
+ maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
phdr->p_offset - disp);
- up_write(&mm->mmap_sem);
kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
loop, phdr->p_memsz + disp, prot, flags,
@@ -1143,10 +1135,8 @@
unsigned long xmaddr;
flags |= MAP_FIXED | MAP_ANONYMOUS;
- down_write(&mm->mmap_sem);
- xmaddr = do_mmap(NULL, xaddr, excess - excess1,
+ xmaddr = vm_mmap(NULL, xaddr, excess - excess1,
prot, flags, 0);
- up_write(&mm->mmap_sem);
kdebug("mmap[%d] <anon>"
" ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 024d20e..6b2daf9 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -542,10 +542,8 @@
*/
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
- down_write(¤t->mm->mmap_sem);
- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
+ textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
MAP_PRIVATE|MAP_EXECUTABLE, 0);
- up_write(¤t->mm->mmap_sem);
if (!textpos || IS_ERR_VALUE(textpos)) {
if (!textpos)
textpos = (unsigned long) -ENOMEM;
@@ -556,10 +554,8 @@
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
len = PAGE_ALIGN(len);
- down_write(¤t->mm->mmap_sem);
- realdatastart = do_mmap(0, 0, len,
+ realdatastart = vm_mmap(0, 0, len,
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
- up_write(¤t->mm->mmap_sem);
if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
if (!realdatastart)
@@ -603,10 +599,8 @@
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
len = PAGE_ALIGN(len);
- down_write(¤t->mm->mmap_sem);
- textpos = do_mmap(0, 0, len,
+ textpos = vm_mmap(0, 0, len,
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
- up_write(¤t->mm->mmap_sem);
if (!textpos || IS_ERR_VALUE(textpos)) {
if (!textpos)
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index e4fc746..4517aaf 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -147,10 +147,8 @@
code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
current->mm->start_code = code_start;
current->mm->end_code = code_start + code_size;
- down_write(¤t->mm->mmap_sem);
- retval = do_mmap(file, code_start, code_size, prot,
+ retval = vm_mmap(file, code_start, code_size, prot,
flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
- up_write(¤t->mm->mmap_sem);
if (retval < 0 && retval > -1024)
goto out;
@@ -158,20 +156,16 @@
data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
current->mm->start_data = data_start;
current->mm->end_data = bss_start = data_start + data_size;
- down_write(¤t->mm->mmap_sem);
- retval = do_mmap(file, data_start, data_size,
+ retval = vm_mmap(file, data_start, data_size,
prot | PROT_WRITE, flags,
SOM_PAGESTART(hpuxhdr->exec_dfile));
- up_write(¤t->mm->mmap_sem);
if (retval < 0 && retval > -1024)
goto out;
som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
current->mm->start_brk = current->mm->brk = som_brk;
- down_write(¤t->mm->mmap_sem);
- retval = do_mmap(NULL, bss_start, som_brk - bss_start,
+ retval = vm_mmap(NULL, bss_start, som_brk - bss_start,
prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
- up_write(¤t->mm->mmap_sem);
if (retval > 0 || retval < -1024)
retval = 0;
out:
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index f4e9074..bcec067 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -22,6 +22,7 @@
#include "ulist.h"
#include "transaction.h"
#include "delayed-ref.h"
+#include "locking.h"
/*
* this structure records all encountered refs on the way up to the root
@@ -893,18 +894,22 @@
s64 bytes_left = size - 1;
struct extent_buffer *eb = eb_in;
struct btrfs_key found_key;
+ int leave_spinning = path->leave_spinning;
if (bytes_left >= 0)
dest[bytes_left] = '\0';
+ path->leave_spinning = 1;
while (1) {
len = btrfs_inode_ref_name_len(eb, iref);
bytes_left -= len;
if (bytes_left >= 0)
read_extent_buffer(eb, dest + bytes_left,
(unsigned long)(iref + 1), len);
- if (eb != eb_in)
+ if (eb != eb_in) {
+ btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb);
+ }
ret = inode_ref_info(parent, 0, fs_root, path, &found_key);
if (ret > 0)
ret = -ENOENT;
@@ -919,8 +924,11 @@
slot = path->slots[0];
eb = path->nodes[0];
/* make sure we can use eb after releasing the path */
- if (eb != eb_in)
+ if (eb != eb_in) {
atomic_inc(&eb->refs);
+ btrfs_tree_read_lock(eb);
+ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
+ }
btrfs_release_path(path);
iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
@@ -931,6 +939,7 @@
}
btrfs_release_path(path);
+ path->leave_spinning = leave_spinning;
if (ret)
return ERR_PTR(ret);
@@ -1247,7 +1256,7 @@
struct btrfs_path *path,
iterate_irefs_t *iterate, void *ctx)
{
- int ret;
+ int ret = 0;
int slot;
u32 cur;
u32 len;
@@ -1259,7 +1268,8 @@
struct btrfs_inode_ref *iref;
struct btrfs_key found_key;
- while (1) {
+ while (!ret) {
+ path->leave_spinning = 1;
ret = inode_ref_info(inum, parent ? parent+1 : 0, fs_root, path,
&found_key);
if (ret < 0)
@@ -1275,6 +1285,8 @@
eb = path->nodes[0];
/* make sure we can use eb after releasing the path */
atomic_inc(&eb->refs);
+ btrfs_tree_read_lock(eb);
+ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
btrfs_release_path(path);
item = btrfs_item_nr(eb, slot);
@@ -1288,13 +1300,12 @@
(unsigned long long)found_key.objectid,
(unsigned long long)fs_root->objectid);
ret = iterate(parent, iref, eb, ctx);
- if (ret) {
- free_extent_buffer(eb);
+ if (ret)
break;
- }
len = sizeof(*iref) + name_len;
iref = (struct btrfs_inode_ref *)((char *)iref + len);
}
+ btrfs_tree_read_unlock_blocking(eb);
free_extent_buffer(eb);
}
@@ -1414,6 +1425,8 @@
void free_ipath(struct inode_fs_paths *ipath)
{
+ if (!ipath)
+ return;
kfree(ipath->fspath);
kfree(ipath);
}
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index d286b40..86eff48 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -405,6 +405,7 @@
bio_put(bio);
bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS);
+ BUG_ON(!bio);
bio->bi_private = cb;
bio->bi_end_io = end_compressed_bio_write;
bio_add_page(bio, page, PAGE_CACHE_SIZE, 0);
@@ -687,6 +688,7 @@
comp_bio = compressed_bio_alloc(bdev, cur_disk_byte,
GFP_NOFS);
+ BUG_ON(!comp_bio);
comp_bio->bi_private = cb;
comp_bio->bi_end_io = end_compressed_bio_read;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index e801f22..4106264 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -220,10 +220,12 @@
*/
static void add_root_to_dirty_list(struct btrfs_root *root)
{
+ spin_lock(&root->fs_info->trans_lock);
if (root->track_dirty && list_empty(&root->dirty_list)) {
list_add(&root->dirty_list,
&root->fs_info->dirty_cowonly_roots);
}
+ spin_unlock(&root->fs_info->trans_lock);
}
/*
@@ -723,7 +725,7 @@
cur = btrfs_find_tree_block(root, blocknr, blocksize);
if (cur)
- uptodate = btrfs_buffer_uptodate(cur, gen);
+ uptodate = btrfs_buffer_uptodate(cur, gen, 0);
else
uptodate = 0;
if (!cur || !uptodate) {
@@ -1358,7 +1360,12 @@
block1 = btrfs_node_blockptr(parent, slot - 1);
gen = btrfs_node_ptr_generation(parent, slot - 1);
eb = btrfs_find_tree_block(root, block1, blocksize);
- if (eb && btrfs_buffer_uptodate(eb, gen))
+ /*
+ * if we get -eagain from btrfs_buffer_uptodate, we
+ * don't want to return eagain here. That will loop
+ * forever
+ */
+ if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
block1 = 0;
free_extent_buffer(eb);
}
@@ -1366,7 +1373,7 @@
block2 = btrfs_node_blockptr(parent, slot + 1);
gen = btrfs_node_ptr_generation(parent, slot + 1);
eb = btrfs_find_tree_block(root, block2, blocksize);
- if (eb && btrfs_buffer_uptodate(eb, gen))
+ if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
block2 = 0;
free_extent_buffer(eb);
}
@@ -1504,8 +1511,9 @@
tmp = btrfs_find_tree_block(root, blocknr, blocksize);
if (tmp) {
- if (btrfs_buffer_uptodate(tmp, 0)) {
- if (btrfs_buffer_uptodate(tmp, gen)) {
+ /* first we do an atomic uptodate check */
+ if (btrfs_buffer_uptodate(tmp, 0, 1) > 0) {
+ if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
/*
* we found an up to date block without
* sleeping, return
@@ -1523,8 +1531,9 @@
free_extent_buffer(tmp);
btrfs_set_path_blocking(p);
+ /* now we're allowed to do a blocking uptodate check */
tmp = read_tree_block(root, blocknr, blocksize, gen);
- if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
+ if (tmp && btrfs_buffer_uptodate(tmp, gen, 0) > 0) {
*eb_ret = tmp;
return 0;
}
@@ -1559,7 +1568,7 @@
* and give up so that our caller doesn't loop forever
* on our EAGAINs.
*/
- if (!btrfs_buffer_uptodate(tmp, 0))
+ if (!btrfs_buffer_uptodate(tmp, 0, 0))
ret = -EIO;
free_extent_buffer(tmp);
}
@@ -4043,7 +4052,7 @@
tmp = btrfs_find_tree_block(root, blockptr,
btrfs_level_size(root, level - 1));
- if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
+ if (tmp && btrfs_buffer_uptodate(tmp, gen, 1) > 0) {
free_extent_buffer(tmp);
break;
}
@@ -4166,7 +4175,8 @@
struct extent_buffer *cur;
cur = btrfs_find_tree_block(root, blockptr,
btrfs_level_size(root, level - 1));
- if (!cur || !btrfs_buffer_uptodate(cur, gen)) {
+ if (!cur ||
+ btrfs_buffer_uptodate(cur, gen, 1) <= 0) {
slot++;
if (cur)
free_extent_buffer(cur);
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 5b8ef8e..8fd7233 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1078,7 +1078,7 @@
* is required instead of the faster short fsync log commits
*/
u64 last_trans_log_full_commit;
- unsigned long mount_opt:21;
+ unsigned long mount_opt;
unsigned long compress_type:4;
u64 max_inline;
u64 alloc_start;
@@ -2166,7 +2166,7 @@
static inline bool btrfs_root_readonly(struct btrfs_root *root)
{
- return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
+ return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
}
/* struct btrfs_root_backup */
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 20196f4..a7ffc88 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -323,7 +323,8 @@
* in the wrong place.
*/
static int verify_parent_transid(struct extent_io_tree *io_tree,
- struct extent_buffer *eb, u64 parent_transid)
+ struct extent_buffer *eb, u64 parent_transid,
+ int atomic)
{
struct extent_state *cached_state = NULL;
int ret;
@@ -331,6 +332,9 @@
if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
return 0;
+ if (atomic)
+ return -EAGAIN;
+
lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
0, &cached_state);
if (extent_buffer_uptodate(eb) &&
@@ -372,7 +376,8 @@
ret = read_extent_buffer_pages(io_tree, eb, start,
WAIT_COMPLETE,
btree_get_extent, mirror_num);
- if (!ret && !verify_parent_transid(io_tree, eb, parent_transid))
+ if (!ret && !verify_parent_transid(io_tree, eb,
+ parent_transid, 0))
break;
/*
@@ -383,17 +388,16 @@
if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags))
break;
- if (!failed_mirror) {
- failed = 1;
- printk(KERN_ERR "failed mirror was %d\n", eb->failed_mirror);
- failed_mirror = eb->failed_mirror;
- }
-
num_copies = btrfs_num_copies(&root->fs_info->mapping_tree,
eb->start, eb->len);
if (num_copies == 1)
break;
+ if (!failed_mirror) {
+ failed = 1;
+ failed_mirror = eb->read_mirror;
+ }
+
mirror_num++;
if (mirror_num == failed_mirror)
mirror_num++;
@@ -564,7 +568,7 @@
}
static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
- struct extent_state *state)
+ struct extent_state *state, int mirror)
{
struct extent_io_tree *tree;
u64 found_start;
@@ -589,6 +593,7 @@
if (!reads_done)
goto err;
+ eb->read_mirror = mirror;
if (test_bit(EXTENT_BUFFER_IOERR, &eb->bflags)) {
ret = -EIO;
goto err;
@@ -652,7 +657,7 @@
eb = (struct extent_buffer *)page->private;
set_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
- eb->failed_mirror = failed_mirror;
+ eb->read_mirror = failed_mirror;
if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
btree_readahead_hook(root, eb, eb->start, -EIO);
return -EIO; /* we fixed nothing */
@@ -1202,7 +1207,7 @@
root->commit_root = NULL;
root->node = read_tree_block(root, btrfs_root_bytenr(&root->root_item),
blocksize, generation);
- if (!root->node || !btrfs_buffer_uptodate(root->node, generation)) {
+ if (!root->node || !btrfs_buffer_uptodate(root->node, generation, 0)) {
free_extent_buffer(root->node);
root->node = NULL;
return -EIO;
@@ -2254,9 +2259,9 @@
goto fail_sb_buffer;
}
- if (sectorsize < PAGE_SIZE) {
- printk(KERN_WARNING "btrfs: Incompatible sector size "
- "found on %s\n", sb->s_id);
+ if (sectorsize != PAGE_SIZE) {
+ printk(KERN_WARNING "btrfs: Incompatible sector size(%lu) "
+ "found on %s\n", (unsigned long)sectorsize, sb->s_id);
goto fail_sb_buffer;
}
@@ -3143,7 +3148,8 @@
return 0;
}
-int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
+ int atomic)
{
int ret;
struct inode *btree_inode = buf->pages[0]->mapping->host;
@@ -3153,7 +3159,9 @@
return ret;
ret = verify_parent_transid(&BTRFS_I(btree_inode)->io_tree, buf,
- parent_transid);
+ parent_transid, atomic);
+ if (ret == -EAGAIN)
+ return ret;
return !ret;
}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index a7ace1a..ab1830a 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -66,7 +66,8 @@
void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
-int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
+int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
+ int atomic);
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
int btrfs_read_buffer(struct extent_buffer *buf, u64 parent_transid);
u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a844204..49fd7b6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -529,9 +529,7 @@
* allocate blocks for the tree root we can't do the fast caching since
* we likely hold important locks.
*/
- if (trans && (!trans->transaction->in_commit) &&
- (root && root != root->fs_info->tree_root) &&
- btrfs_test_opt(root, SPACE_CACHE)) {
+ if (fs_info->mount_opt & BTRFS_MOUNT_SPACE_CACHE) {
ret = load_free_space_cache(fs_info, cache);
spin_lock(&cache->lock);
@@ -2303,6 +2301,7 @@
if (ret) {
printk(KERN_DEBUG "btrfs: run_delayed_extent_op returned %d\n", ret);
+ spin_lock(&delayed_refs->lock);
return ret;
}
@@ -2333,6 +2332,7 @@
if (ret) {
printk(KERN_DEBUG "btrfs: run_one_delayed_ref returned %d\n", ret);
+ spin_lock(&delayed_refs->lock);
return ret;
}
@@ -3152,15 +3152,14 @@
/*
* returns target flags in extended format or 0 if restripe for this
* chunk_type is not in progress
+ *
+ * should be called with either volume_mutex or balance_lock held
*/
static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
{
struct btrfs_balance_control *bctl = fs_info->balance_ctl;
u64 target = 0;
- BUG_ON(!mutex_is_locked(&fs_info->volume_mutex) &&
- !spin_is_locked(&fs_info->balance_lock));
-
if (!bctl)
return 0;
@@ -3772,13 +3771,10 @@
*/
if (current->journal_info)
return -EAGAIN;
- ret = wait_event_interruptible(space_info->wait,
- !space_info->flush);
- /* Must have been interrupted, return */
- if (ret) {
- printk(KERN_DEBUG "btrfs: %s returning -EINTR\n", __func__);
+ ret = wait_event_killable(space_info->wait, !space_info->flush);
+ /* Must have been killed, return */
+ if (ret)
return -EINTR;
- }
spin_lock(&space_info->lock);
}
@@ -4205,7 +4201,7 @@
num_bytes += div64_u64(data_used + meta_used, 50);
if (num_bytes * 3 > meta_used)
- num_bytes = div64_u64(meta_used, 3) * 2;
+ num_bytes = div64_u64(meta_used, 3);
return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
}
@@ -4218,8 +4214,8 @@
num_bytes = calc_global_metadata_size(fs_info);
- spin_lock(&block_rsv->lock);
spin_lock(&sinfo->lock);
+ spin_lock(&block_rsv->lock);
block_rsv->size = num_bytes;
@@ -4245,8 +4241,8 @@
block_rsv->full = 1;
}
- spin_unlock(&sinfo->lock);
spin_unlock(&block_rsv->lock);
+ spin_unlock(&sinfo->lock);
}
static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
@@ -6572,7 +6568,7 @@
goto skip;
}
- if (!btrfs_buffer_uptodate(next, generation)) {
+ if (!btrfs_buffer_uptodate(next, generation, 0)) {
btrfs_tree_unlock(next);
free_extent_buffer(next);
next = NULL;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 8d904dd..c9018a0 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -402,20 +402,28 @@
return 0;
}
+static struct extent_state *next_state(struct extent_state *state)
+{
+ struct rb_node *next = rb_next(&state->rb_node);
+ if (next)
+ return rb_entry(next, struct extent_state, rb_node);
+ else
+ return NULL;
+}
+
/*
* utility function to clear some bits in an extent state struct.
- * it will optionally wake up any one waiting on this state (wake == 1), or
- * forcibly remove the state from the tree (delete == 1).
+ * it will optionally wake up any one waiting on this state (wake == 1)
*
* If no bits are set on the state struct after clearing things, the
* struct is freed and removed from the tree
*/
-static int clear_state_bit(struct extent_io_tree *tree,
- struct extent_state *state,
- int *bits, int wake)
+static struct extent_state *clear_state_bit(struct extent_io_tree *tree,
+ struct extent_state *state,
+ int *bits, int wake)
{
+ struct extent_state *next;
int bits_to_clear = *bits & ~EXTENT_CTLBITS;
- int ret = state->state & bits_to_clear;
if ((bits_to_clear & EXTENT_DIRTY) && (state->state & EXTENT_DIRTY)) {
u64 range = state->end - state->start + 1;
@@ -427,6 +435,7 @@
if (wake)
wake_up(&state->wq);
if (state->state == 0) {
+ next = next_state(state);
if (state->tree) {
rb_erase(&state->rb_node, &tree->state);
state->tree = NULL;
@@ -436,8 +445,9 @@
}
} else {
merge_state(tree, state);
+ next = next_state(state);
}
- return ret;
+ return next;
}
static struct extent_state *
@@ -476,7 +486,6 @@
struct extent_state *state;
struct extent_state *cached;
struct extent_state *prealloc = NULL;
- struct rb_node *next_node;
struct rb_node *node;
u64 last_end;
int err;
@@ -528,14 +537,11 @@
WARN_ON(state->end < start);
last_end = state->end;
- if (state->end < end && !need_resched())
- next_node = rb_next(&state->rb_node);
- else
- next_node = NULL;
-
/* the state doesn't have the wanted bits, go ahead */
- if (!(state->state & bits))
+ if (!(state->state & bits)) {
+ state = next_state(state);
goto next;
+ }
/*
* | ---- desired range ---- |
@@ -593,16 +599,13 @@
goto out;
}
- clear_state_bit(tree, state, &bits, wake);
+ state = clear_state_bit(tree, state, &bits, wake);
next:
if (last_end == (u64)-1)
goto out;
start = last_end + 1;
- if (start <= end && next_node) {
- state = rb_entry(next_node, struct extent_state,
- rb_node);
+ if (start <= end && state && !need_resched())
goto hit_next;
- }
goto search_again;
out:
@@ -1937,7 +1940,7 @@
struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
u64 start = eb->start;
unsigned long i, num_pages = num_extent_pages(eb->start, eb->len);
- int ret;
+ int ret = 0;
for (i = 0; i < num_pages; i++) {
struct page *p = extent_buffer_page(eb, i);
@@ -2180,6 +2183,10 @@
}
bio = bio_alloc(GFP_NOFS, 1);
+ if (!bio) {
+ free_io_failure(inode, failrec, 0);
+ return -EIO;
+ }
bio->bi_private = state;
bio->bi_end_io = failed_bio->bi_end_io;
bio->bi_sector = failrec->logical >> 9;
@@ -2297,7 +2304,7 @@
u64 start;
u64 end;
int whole_page;
- int failed_mirror;
+ int mirror;
int ret;
if (err)
@@ -2336,20 +2343,18 @@
}
spin_unlock(&tree->lock);
+ mirror = (int)(unsigned long)bio->bi_bdev;
if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
ret = tree->ops->readpage_end_io_hook(page, start, end,
- state);
+ state, mirror);
if (ret)
uptodate = 0;
else
clean_io_failure(start, page);
}
- if (!uptodate)
- failed_mirror = (int)(unsigned long)bio->bi_bdev;
-
if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) {
- ret = tree->ops->readpage_io_failed_hook(page, failed_mirror);
+ ret = tree->ops->readpage_io_failed_hook(page, mirror);
if (!ret && !err &&
test_bit(BIO_UPTODATE, &bio->bi_flags))
uptodate = 1;
@@ -2364,8 +2369,7 @@
* can't handle the error it will return -EIO and we
* remain responsible for that page.
*/
- ret = bio_readpage_error(bio, page, start, end,
- failed_mirror, NULL);
+ ret = bio_readpage_error(bio, page, start, end, mirror, NULL);
if (ret == 0) {
uptodate =
test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -4116,6 +4120,7 @@
if (atomic_inc_not_zero(&exists->refs)) {
spin_unlock(&mapping->private_lock);
unlock_page(p);
+ page_cache_release(p);
mark_extent_buffer_accessed(exists);
goto free_eb;
}
@@ -4195,8 +4200,7 @@
unlock_page(eb->pages[i]);
}
- if (!atomic_dec_and_test(&eb->refs))
- return exists;
+ WARN_ON(!atomic_dec_and_test(&eb->refs));
btrfs_release_extent_buffer(eb);
return exists;
}
@@ -4458,7 +4462,7 @@
}
clear_bit(EXTENT_BUFFER_IOERR, &eb->bflags);
- eb->failed_mirror = 0;
+ eb->read_mirror = 0;
atomic_set(&eb->io_pages, num_reads);
for (i = start_i; i < num_pages; i++) {
page = extent_buffer_page(eb, i);
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index faf10eb5..b516c3b 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -79,7 +79,7 @@
u64 start, u64 end,
struct extent_state *state);
int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
- struct extent_state *state);
+ struct extent_state *state, int mirror);
int (*writepage_end_io_hook)(struct page *page, u64 start, u64 end,
struct extent_state *state, int uptodate);
void (*set_bit_hook)(struct inode *inode, struct extent_state *state,
@@ -135,7 +135,7 @@
spinlock_t refs_lock;
atomic_t refs;
atomic_t io_pages;
- int failed_mirror;
+ int read_mirror;
struct list_head leak_list;
struct rcu_head rcu_head;
pid_t lock_owner;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index d83260d..53bf2d7 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -567,6 +567,7 @@
int extent_type;
int recow;
int ret;
+ int modify_tree = -1;
if (drop_cache)
btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -575,10 +576,13 @@
if (!path)
return -ENOMEM;
+ if (start >= BTRFS_I(inode)->disk_i_size)
+ modify_tree = 0;
+
while (1) {
recow = 0;
ret = btrfs_lookup_file_extent(trans, root, path, ino,
- search_start, -1);
+ search_start, modify_tree);
if (ret < 0)
break;
if (ret > 0 && path->slots[0] > 0 && search_start == start) {
@@ -634,7 +638,8 @@
}
search_start = max(key.offset, start);
- if (recow) {
+ if (recow || !modify_tree) {
+ modify_tree = -1;
btrfs_release_path(path);
continue;
}
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index e88330d3..202008e 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -748,13 +748,6 @@
u64 used = btrfs_block_group_used(&block_group->item);
/*
- * If we're unmounting then just return, since this does a search on the
- * normal root and not the commit root and we could deadlock.
- */
- if (btrfs_fs_closing(fs_info))
- return 0;
-
- /*
* If this block group has been marked to be cleared for one reason or
* another then we can't trust the on disk cache, so just return.
*/
@@ -768,6 +761,8 @@
path = btrfs_alloc_path();
if (!path)
return 0;
+ path->search_commit_root = 1;
+ path->skip_locking = 1;
inode = lookup_free_space_inode(root, block_group, path);
if (IS_ERR(inode)) {
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 115bc05..61b16c6 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1947,7 +1947,7 @@
* extent_io.c will try to find good copies for us.
*/
static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end,
- struct extent_state *state)
+ struct extent_state *state, int mirror)
{
size_t offset = start - ((u64)page->index << PAGE_CACHE_SHIFT);
struct inode *inode = page->mapping->host;
@@ -4069,7 +4069,7 @@
BTRFS_I(inode)->dummy_inode = 1;
inode->i_ino = BTRFS_EMPTY_SUBVOL_DIR_OBJECTID;
- inode->i_op = &simple_dir_inode_operations;
+ inode->i_op = &btrfs_dir_ro_inode_operations;
inode->i_fop = &simple_dir_operations;
inode->i_mode = S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -4140,14 +4140,18 @@
static int btrfs_dentry_delete(const struct dentry *dentry)
{
struct btrfs_root *root;
+ struct inode *inode = dentry->d_inode;
- if (!dentry->d_inode && !IS_ROOT(dentry))
- dentry = dentry->d_parent;
+ if (!inode && !IS_ROOT(dentry))
+ inode = dentry->d_parent->d_inode;
- if (dentry->d_inode) {
- root = BTRFS_I(dentry->d_inode)->root;
+ if (inode) {
+ root = BTRFS_I(inode)->root;
if (btrfs_root_refs(&root->root_item) == 0)
return 1;
+
+ if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
+ return 1;
}
return 0;
}
@@ -4188,7 +4192,6 @@
struct btrfs_path *path;
struct list_head ins_list;
struct list_head del_list;
- struct qstr q;
int ret;
struct extent_buffer *leaf;
int slot;
@@ -4279,7 +4282,6 @@
while (di_cur < di_total) {
struct btrfs_key location;
- struct dentry *tmp;
if (verify_dir_item(root, leaf, di))
break;
@@ -4300,35 +4302,15 @@
d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
btrfs_dir_item_key_to_cpu(leaf, di, &location);
- q.name = name_ptr;
- q.len = name_len;
- q.hash = full_name_hash(q.name, q.len);
- tmp = d_lookup(filp->f_dentry, &q);
- if (!tmp) {
- struct btrfs_key *newkey;
- newkey = kzalloc(sizeof(struct btrfs_key),
- GFP_NOFS);
- if (!newkey)
- goto no_dentry;
- tmp = d_alloc(filp->f_dentry, &q);
- if (!tmp) {
- kfree(newkey);
- dput(tmp);
- goto no_dentry;
- }
- memcpy(newkey, &location,
- sizeof(struct btrfs_key));
- tmp->d_fsdata = newkey;
- tmp->d_flags |= DCACHE_NEED_LOOKUP;
- d_rehash(tmp);
- dput(tmp);
- } else {
- dput(tmp);
- }
-no_dentry:
/* is this a reference to our own snapshot? If so
- * skip it
+ * skip it.
+ *
+ * In contrast to old kernels, we insert the snapshot's
+ * dir item and dir index after it has been created, so
+ * we won't find a reference to our own snapshot. We
+ * still keep the following code for backward
+ * compatibility.
*/
if (location.type == BTRFS_ROOT_ITEM_KEY &&
location.objectid == root->root_key.objectid) {
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 18cc23d..14f8e1f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2262,7 +2262,10 @@
di_args->bytes_used = dev->bytes_used;
di_args->total_bytes = dev->total_bytes;
memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
- strncpy(di_args->path, dev->name, sizeof(di_args->path));
+ if (dev->name)
+ strncpy(di_args->path, dev->name, sizeof(di_args->path));
+ else
+ di_args->path[0] = '\0';
out:
if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args)))
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 4f69028..086e6bd 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -252,7 +252,7 @@
struct btrfs_ioctl_ino_path_args {
__u64 inum; /* in */
- __u32 size; /* in */
+ __u64 size; /* in */
__u64 reserved[4];
/* struct btrfs_data_container *fspath; out */
__u64 fspath; /* out */
@@ -260,7 +260,7 @@
struct btrfs_ioctl_logical_ino_args {
__u64 logical; /* in */
- __u32 size; /* in */
+ __u64 size; /* in */
__u64 reserved[4];
/* struct btrfs_data_container *inodes; out */
__u64 inodes;
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index dc5d331..ac5d010 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -250,14 +250,12 @@
struct btrfs_bio *bbio)
{
int ret;
- int looped = 0;
struct reada_zone *zone;
struct btrfs_block_group_cache *cache = NULL;
u64 start;
u64 end;
int i;
-again:
zone = NULL;
spin_lock(&fs_info->reada_lock);
ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
@@ -274,9 +272,6 @@
spin_unlock(&fs_info->reada_lock);
}
- if (looped)
- return NULL;
-
cache = btrfs_lookup_block_group(fs_info, logical);
if (!cache)
return NULL;
@@ -307,13 +302,15 @@
ret = radix_tree_insert(&dev->reada_zones,
(unsigned long)(zone->end >> PAGE_CACHE_SHIFT),
zone);
- spin_unlock(&fs_info->reada_lock);
- if (ret) {
+ if (ret == -EEXIST) {
kfree(zone);
- looped = 1;
- goto again;
+ ret = radix_tree_gang_lookup(&dev->reada_zones, (void **)&zone,
+ logical >> PAGE_CACHE_SHIFT, 1);
+ if (ret == 1)
+ kref_get(&zone->refcnt);
}
+ spin_unlock(&fs_info->reada_lock);
return zone;
}
@@ -323,26 +320,26 @@
struct btrfs_key *top, int level)
{
int ret;
- int looped = 0;
struct reada_extent *re = NULL;
+ struct reada_extent *re_exist = NULL;
struct btrfs_fs_info *fs_info = root->fs_info;
struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
struct btrfs_bio *bbio = NULL;
struct btrfs_device *dev;
+ struct btrfs_device *prev_dev;
u32 blocksize;
u64 length;
int nzones = 0;
int i;
unsigned long index = logical >> PAGE_CACHE_SHIFT;
-again:
spin_lock(&fs_info->reada_lock);
re = radix_tree_lookup(&fs_info->reada_tree, index);
if (re)
kref_get(&re->refcnt);
spin_unlock(&fs_info->reada_lock);
- if (re || looped)
+ if (re)
return re;
re = kzalloc(sizeof(*re), GFP_NOFS);
@@ -398,16 +395,31 @@
/* insert extent in reada_tree + all per-device trees, all or nothing */
spin_lock(&fs_info->reada_lock);
ret = radix_tree_insert(&fs_info->reada_tree, index, re);
- if (ret) {
+ if (ret == -EEXIST) {
+ re_exist = radix_tree_lookup(&fs_info->reada_tree, index);
+ BUG_ON(!re_exist);
+ kref_get(&re_exist->refcnt);
spin_unlock(&fs_info->reada_lock);
- if (ret != -ENOMEM) {
- /* someone inserted the extent in the meantime */
- looped = 1;
- }
goto error;
}
+ if (ret) {
+ spin_unlock(&fs_info->reada_lock);
+ goto error;
+ }
+ prev_dev = NULL;
for (i = 0; i < nzones; ++i) {
dev = bbio->stripes[i].dev;
+ if (dev == prev_dev) {
+ /*
+ * in case of DUP, just add the first zone. As both
+ * are on the same device, there's nothing to gain
+ * from adding both.
+ * Also, it wouldn't work, as the tree is per device
+ * and adding would fail with EEXIST
+ */
+ continue;
+ }
+ prev_dev = dev;
ret = radix_tree_insert(&dev->reada_extents, index, re);
if (ret) {
while (--i >= 0) {
@@ -450,9 +462,7 @@
}
kfree(bbio);
kfree(re);
- if (looped)
- goto again;
- return NULL;
+ return re_exist;
}
static void reada_kref_dummy(struct kref *kr)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 017281d..646ee21 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1279,7 +1279,9 @@
if (rb_node)
backref_tree_panic(rb_node, -EEXIST, node->bytenr);
} else {
+ spin_lock(&root->fs_info->trans_lock);
list_del_init(&root->root_list);
+ spin_unlock(&root->fs_info->trans_lock);
kfree(node);
}
return 0;
@@ -3811,7 +3813,7 @@
ret = btrfs_block_rsv_check(rc->extent_root, rc->block_rsv, 5);
if (ret < 0) {
- if (ret != -EAGAIN) {
+ if (ret != -ENOSPC) {
err = ret;
WARN_ON(1);
break;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 90acc82..2f3d6f9 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -998,6 +998,7 @@
page = sblock->pagev + page_index;
page->logical = logical;
page->physical = bbio->stripes[mirror_index].physical;
+ /* for missing devices, bdev is NULL */
page->bdev = bbio->stripes[mirror_index].dev->bdev;
page->mirror_num = mirror_index + 1;
page->page = alloc_page(GFP_NOFS);
@@ -1042,8 +1043,16 @@
struct scrub_page *page = sblock->pagev + page_num;
DECLARE_COMPLETION_ONSTACK(complete);
+ if (page->bdev == NULL) {
+ page->io_error = 1;
+ sblock->no_io_error_seen = 0;
+ continue;
+ }
+
BUG_ON(!page->page);
bio = bio_alloc(GFP_NOFS, 1);
+ if (!bio)
+ return -EIO;
bio->bi_bdev = page->bdev;
bio->bi_sector = page->physical >> 9;
bio->bi_end_io = scrub_complete_bio_end_io;
@@ -1171,6 +1180,8 @@
DECLARE_COMPLETION_ONSTACK(complete);
bio = bio_alloc(GFP_NOFS, 1);
+ if (!bio)
+ return -EIO;
bio->bi_bdev = page_bad->bdev;
bio->bi_sector = page_bad->physical >> 9;
bio->bi_end_io = scrub_complete_bio_end_io;
@@ -1253,12 +1264,6 @@
if (memcmp(csum, on_disk_csum, sdev->csum_size))
fail = 1;
- if (fail) {
- spin_lock(&sdev->stat_lock);
- ++sdev->stat.csum_errors;
- spin_unlock(&sdev->stat_lock);
- }
-
return fail;
}
@@ -1331,15 +1336,6 @@
if (memcmp(calculated_csum, on_disk_csum, sdev->csum_size))
++crc_fail;
- if (crc_fail || fail) {
- spin_lock(&sdev->stat_lock);
- if (crc_fail)
- ++sdev->stat.csum_errors;
- if (fail)
- ++sdev->stat.verify_errors;
- spin_unlock(&sdev->stat_lock);
- }
-
return fail || crc_fail;
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 8d5d380..c5f8fca 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -815,7 +815,6 @@
return 0;
}
- btrfs_start_delalloc_inodes(root, 0);
btrfs_wait_ordered_extents(root, 0, 0);
trans = btrfs_start_transaction(root, 0);
@@ -1148,13 +1147,15 @@
if (ret)
goto restore;
} else {
- if (fs_info->fs_devices->rw_devices == 0)
+ if (fs_info->fs_devices->rw_devices == 0) {
ret = -EACCES;
goto restore;
+ }
- if (btrfs_super_log_root(fs_info->super_copy) != 0)
+ if (btrfs_super_log_root(fs_info->super_copy) != 0) {
ret = -EINVAL;
goto restore;
+ }
ret = btrfs_cleanup_fs_roots(fs_info);
if (ret)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 8da29e8..3642225 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -73,8 +73,10 @@
cur_trans = root->fs_info->running_transaction;
if (cur_trans) {
- if (cur_trans->aborted)
+ if (cur_trans->aborted) {
+ spin_unlock(&root->fs_info->trans_lock);
return cur_trans->aborted;
+ }
atomic_inc(&cur_trans->use_count);
atomic_inc(&cur_trans->num_writers);
cur_trans->num_joined++;
@@ -480,6 +482,7 @@
struct btrfs_transaction *cur_trans = trans->transaction;
struct btrfs_fs_info *info = root->fs_info;
int count = 0;
+ int err = 0;
if (--trans->use_count) {
trans->block_rsv = trans->orig_rsv;
@@ -532,18 +535,18 @@
if (current->journal_info == trans)
current->journal_info = NULL;
- memset(trans, 0, sizeof(*trans));
- kmem_cache_free(btrfs_trans_handle_cachep, trans);
if (throttle)
btrfs_run_delayed_iputs(root);
if (trans->aborted ||
root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
- return -EIO;
+ err = -EIO;
}
- return 0;
+ memset(trans, 0, sizeof(*trans));
+ kmem_cache_free(btrfs_trans_handle_cachep, trans);
+ return err;
}
int btrfs_end_transaction(struct btrfs_trans_handle *trans,
@@ -1399,6 +1402,7 @@
ret = commit_fs_roots(trans, root);
if (ret) {
mutex_unlock(&root->fs_info->tree_log_mutex);
+ mutex_unlock(&root->fs_info->reloc_mutex);
goto cleanup_transaction;
}
@@ -1410,6 +1414,7 @@
ret = commit_cowonly_roots(trans, root);
if (ret) {
mutex_unlock(&root->fs_info->tree_log_mutex);
+ mutex_unlock(&root->fs_info->reloc_mutex);
goto cleanup_transaction;
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index d017283..eb1ae90 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -279,7 +279,7 @@
log->fs_info->extent_root,
eb->start, eb->len);
- if (btrfs_buffer_uptodate(eb, gen)) {
+ if (btrfs_buffer_uptodate(eb, gen, 0)) {
if (wc->write)
btrfs_write_tree_block(eb);
if (wc->wait)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a872b48..1411b99 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3324,12 +3324,14 @@
stripe_size = devices_info[ndevs-1].max_avail;
num_stripes = ndevs * dev_stripes;
- if (stripe_size * num_stripes > max_chunk_size * ncopies) {
+ if (stripe_size * ndevs > max_chunk_size * ncopies) {
stripe_size = max_chunk_size * ncopies;
- do_div(stripe_size, num_stripes);
+ do_div(stripe_size, ndevs);
}
do_div(stripe_size, dev_stripes);
+
+ /* align to BTRFS_STRIPE_LEN */
do_div(stripe_size, BTRFS_STRIPE_LEN);
stripe_size *= BTRFS_STRIPE_LEN;
@@ -3805,10 +3807,11 @@
else if (mirror_num)
stripe_index += mirror_num - 1;
else {
+ int old_stripe_index = stripe_index;
stripe_index = find_live_mirror(map, stripe_index,
map->sub_stripes, stripe_index +
current->pid % map->sub_stripes);
- mirror_num = stripe_index + 1;
+ mirror_num = stripe_index - old_stripe_index + 1;
}
} else {
/*
@@ -3833,6 +3836,7 @@
int sub_stripes = 0;
u64 stripes_per_dev = 0;
u32 remaining_stripes = 0;
+ u32 last_stripe = 0;
if (map->type &
(BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
@@ -3846,6 +3850,8 @@
stripe_nr_orig,
factor,
&remaining_stripes);
+ div_u64_rem(stripe_nr_end - 1, factor, &last_stripe);
+ last_stripe *= sub_stripes;
}
for (i = 0; i < num_stripes; i++) {
@@ -3858,16 +3864,29 @@
BTRFS_BLOCK_GROUP_RAID10)) {
bbio->stripes[i].length = stripes_per_dev *
map->stripe_len;
+
if (i / sub_stripes < remaining_stripes)
bbio->stripes[i].length +=
map->stripe_len;
+
+ /*
+ * Special for the first stripe and
+ * the last stripe:
+ *
+ * |-------|...|-------|
+ * |----------|
+ * off end_off
+ */
if (i < sub_stripes)
bbio->stripes[i].length -=
stripe_offset;
- if ((i / sub_stripes + 1) %
- sub_stripes == remaining_stripes)
+
+ if (stripe_index >= last_stripe &&
+ stripe_index <= (last_stripe +
+ sub_stripes - 1))
bbio->stripes[i].length -=
stripe_end_offset;
+
if (i == sub_stripes - 1)
stripe_offset = 0;
} else
@@ -4334,8 +4353,10 @@
ret = __btrfs_open_devices(fs_devices, FMODE_READ,
root->fs_info->bdev_holder);
- if (ret)
+ if (ret) {
+ free_fs_devices(fs_devices);
goto out;
+ }
if (!fs_devices->seeding) {
__btrfs_close_devices(fs_devices);
diff --git a/fs/buffer.c b/fs/buffer.c
index 36d6665..351e18e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -985,7 +985,6 @@
return page;
failed:
- BUG();
unlock_page(page);
page_cache_release(page);
return NULL;
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index d342128..ca6a379 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -370,13 +370,13 @@
(int)(srcaddr->sa_family));
}
- seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
+ seq_printf(s, ",uid=%u", cifs_sb->mnt_uid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID)
seq_printf(s, ",forceuid");
else
seq_printf(s, ",noforceuid");
- seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
+ seq_printf(s, ",gid=%u", cifs_sb->mnt_gid);
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID)
seq_printf(s, ",forcegid");
else
@@ -434,11 +434,15 @@
seq_printf(s, ",noperm");
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO)
seq_printf(s, ",strictcache");
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID)
+ seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID)
+ seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid);
- seq_printf(s, ",rsize=%d", cifs_sb->rsize);
- seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+ seq_printf(s, ",rsize=%u", cifs_sb->rsize);
+ seq_printf(s, ",wsize=%u", cifs_sb->wsize);
/* convert actimeo and display it in seconds */
- seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
+ seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);
return 0;
}
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d1389bb..6536535 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -125,5 +125,5 @@
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
-#define CIFS_VERSION "1.77"
+#define CIFS_VERSION "1.78"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 8fecc99..da2f544 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -3892,13 +3892,12 @@
int rc = 0;
int bytes_returned = 0;
SET_SEC_DESC_REQ *pSMB = NULL;
- NTRANSACT_RSP *pSMBr = NULL;
+ void *pSMBr;
setCifsAclRetry:
- rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB,
- (void **) &pSMBr);
+ rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr);
if (rc)
- return (rc);
+ return rc;
pSMB->MaxSetupCount = 0;
pSMB->Reserved = 0;
@@ -3926,9 +3925,8 @@
pSMB->AclFlags = cpu_to_le32(aclflag);
if (pntsd && acllen) {
- memcpy((char *) &pSMBr->hdr.Protocol + data_offset,
- (char *) pntsd,
- acllen);
+ memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) +
+ data_offset, pntsd, acllen);
inc_rfc1001_len(pSMB, byte_count + data_count);
} else
inc_rfc1001_len(pSMB, byte_count);
@@ -4846,8 +4844,12 @@
max_len = data_end - temp;
node->node_name = cifs_strndup_from_utf16(temp, max_len,
is_unicode, nls_codepage);
- if (!node->node_name)
+ if (!node->node_name) {
rc = -ENOMEM;
+ goto parse_DFS_referrals_exit;
+ }
+
+ ref++;
}
parse_DFS_referrals_exit:
@@ -5708,7 +5710,8 @@
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
- data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
+ data_offset = (char *)pSMB +
+ offsetof(struct smb_hdr, Protocol) + offset;
count = sizeof(FILE_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -5977,7 +5980,7 @@
u16 fid, u32 pid_of_opener)
{
struct smb_com_transaction2_sfi_req *pSMB = NULL;
- FILE_UNIX_BASIC_INFO *data_offset;
+ char *data_offset;
int rc = 0;
u16 params, param_offset, offset, byte_count, count;
@@ -5999,8 +6002,9 @@
param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
offset = param_offset + params;
- data_offset = (FILE_UNIX_BASIC_INFO *)
- ((char *)(&pSMB->hdr.Protocol) + offset);
+ data_offset = (char *)pSMB +
+ offsetof(struct smb_hdr, Protocol) + offset;
+
count = sizeof(FILE_UNIX_BASIC_INFO);
pSMB->MaxParameterCount = cpu_to_le16(2);
@@ -6022,7 +6026,7 @@
inc_rfc1001_len(pSMB, byte_count);
pSMB->ByteCount = cpu_to_le16(byte_count);
- cifs_fill_unix_set_info(data_offset, args);
+ cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args);
rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0);
if (rc)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 302a15c..5dcc551 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -109,6 +109,8 @@
/* Options which could be blank */
Opt_blank_pass,
+ Opt_blank_user,
+ Opt_blank_ip,
Opt_err
};
@@ -183,11 +185,15 @@
{ Opt_wsize, "wsize=%s" },
{ Opt_actimeo, "actimeo=%s" },
+ { Opt_blank_user, "user=" },
+ { Opt_blank_user, "username=" },
{ Opt_user, "user=%s" },
{ Opt_user, "username=%s" },
{ Opt_blank_pass, "pass=" },
{ Opt_pass, "pass=%s" },
{ Opt_pass, "password=%s" },
+ { Opt_blank_ip, "ip=" },
+ { Opt_blank_ip, "addr=" },
{ Opt_ip, "ip=%s" },
{ Opt_ip, "addr=%s" },
{ Opt_unc, "unc=%s" },
@@ -209,6 +215,8 @@
{ Opt_ignore, "cred" },
{ Opt_ignore, "credentials" },
+ { Opt_ignore, "cred=%s" },
+ { Opt_ignore, "credentials=%s" },
{ Opt_ignore, "guest" },
{ Opt_ignore, "rw" },
{ Opt_ignore, "ro" },
@@ -1117,7 +1125,7 @@
string = match_strdup(args);
if (string == NULL)
return -ENOMEM;
- rc = kstrtoul(string, 10, option);
+ rc = kstrtoul(string, 0, option);
kfree(string);
return rc;
@@ -1534,15 +1542,17 @@
/* String Arguments */
+ case Opt_blank_user:
+ /* null user, ie. anonymous authentication */
+ vol->nullauth = 1;
+ vol->username = NULL;
+ break;
case Opt_user:
string = match_strdup(args);
if (string == NULL)
goto out_nomem;
- if (!*string) {
- /* null user, ie. anonymous authentication */
- vol->nullauth = 1;
- } else if (strnlen(string, MAX_USERNAME_SIZE) >
+ if (strnlen(string, MAX_USERNAME_SIZE) >
MAX_USERNAME_SIZE) {
printk(KERN_WARNING "CIFS: username too long\n");
goto cifs_parse_mount_err;
@@ -1565,8 +1575,7 @@
/* Obtain the value string */
value = strchr(data, '=');
- if (value != NULL)
- *value++ = '\0';
+ value++;
/* Set tmp_end to end of the string */
tmp_end = (char *) value + strlen(value);
@@ -1612,14 +1621,15 @@
}
vol->password[j] = '\0';
break;
+ case Opt_blank_ip:
+ vol->UNCip = NULL;
+ break;
case Opt_ip:
string = match_strdup(args);
if (string == NULL)
goto out_nomem;
- if (!*string) {
- vol->UNCip = NULL;
- } else if (strnlen(string, INET6_ADDRSTRLEN) >
+ if (strnlen(string, INET6_ADDRSTRLEN) >
INET6_ADDRSTRLEN) {
printk(KERN_WARNING "CIFS: ip address "
"too long\n");
@@ -1637,18 +1647,19 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: invalid path to "
- "network resource\n");
- goto cifs_parse_mount_err;
- }
-
temp_len = strnlen(string, 300);
if (temp_len == 300) {
printk(KERN_WARNING "CIFS: UNC name too long\n");
goto cifs_parse_mount_err;
}
+ vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
+ if (vol->UNC == NULL) {
+ printk(KERN_WARNING "CIFS: no memory for UNC\n");
+ goto cifs_parse_mount_err;
+ }
+ strcpy(vol->UNC, string);
+
if (strncmp(string, "//", 2) == 0) {
vol->UNC[0] = '\\';
vol->UNC[1] = '\\';
@@ -1658,24 +1669,13 @@
goto cifs_parse_mount_err;
}
- vol->UNC = kmalloc(temp_len+1, GFP_KERNEL);
- if (vol->UNC == NULL) {
- printk(KERN_WARNING "CIFS: no memory "
- "for UNC\n");
- goto cifs_parse_mount_err;
- }
- strcpy(vol->UNC, string);
break;
case Opt_domain:
string = match_strdup(args);
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: invalid domain"
- " name\n");
- goto cifs_parse_mount_err;
- } else if (strnlen(string, 256) == 256) {
+ if (strnlen(string, 256) == 256) {
printk(KERN_WARNING "CIFS: domain name too"
" long\n");
goto cifs_parse_mount_err;
@@ -1694,11 +1694,7 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: srcaddr value not"
- " specified\n");
- goto cifs_parse_mount_err;
- } else if (!cifs_convert_address(
+ if (!cifs_convert_address(
(struct sockaddr *)&vol->srcaddr,
string, strlen(string))) {
printk(KERN_WARNING "CIFS: Could not parse"
@@ -1711,11 +1707,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: Invalid path"
- " prefix\n");
- goto cifs_parse_mount_err;
- }
temp_len = strnlen(string, 1024);
if (string[0] != '/')
temp_len++; /* missing leading slash */
@@ -1743,11 +1734,7 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: Invalid iocharset"
- " specified\n");
- goto cifs_parse_mount_err;
- } else if (strnlen(string, 1024) >= 65) {
+ if (strnlen(string, 1024) >= 65) {
printk(KERN_WARNING "CIFS: iocharset name "
"too long.\n");
goto cifs_parse_mount_err;
@@ -1772,11 +1759,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: No socket option"
- " specified\n");
- goto cifs_parse_mount_err;
- }
if (strnicmp(string, "TCP_NODELAY", 11) == 0)
vol->sockopt_tcp_nodelay = 1;
break;
@@ -1785,12 +1767,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: Invalid (empty)"
- " netbiosname\n");
- break;
- }
-
memset(vol->source_rfc1001_name, 0x20,
RFC1001_NAME_LEN);
/*
@@ -1818,11 +1794,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: Empty server"
- " netbiosname specified\n");
- break;
- }
/* last byte, type, is 0x20 for servr type */
memset(vol->target_rfc1001_name, 0x20,
RFC1001_NAME_LEN_WITH_NULL);
@@ -1849,12 +1820,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- cERROR(1, "no protocol version specified"
- " after vers= mount option");
- goto cifs_parse_mount_err;
- }
-
if (strnicmp(string, "cifs", 4) == 0 ||
strnicmp(string, "1", 1) == 0) {
/* This is the default */
@@ -1869,12 +1834,6 @@
if (string == NULL)
goto out_nomem;
- if (!*string) {
- printk(KERN_WARNING "CIFS: no security flavor"
- " specified\n");
- break;
- }
-
if (cifs_parse_security_flavors(string, vol) != 0)
goto cifs_parse_mount_err;
break;
@@ -2226,6 +2185,7 @@
tcp_ses->session_estab = false;
tcp_ses->sequence_number = 0;
tcp_ses->lstrp = jiffies;
+ spin_lock_init(&tcp_ses->req_lock);
INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
@@ -3271,10 +3231,6 @@
cifs_sb->mnt_uid = pvolume_info->linux_uid;
cifs_sb->mnt_gid = pvolume_info->linux_gid;
- if (pvolume_info->backupuid_specified)
- cifs_sb->mnt_backupuid = pvolume_info->backupuid;
- if (pvolume_info->backupgid_specified)
- cifs_sb->mnt_backupgid = pvolume_info->backupgid;
cifs_sb->mnt_file_mode = pvolume_info->file_mode;
cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
cFYI(1, "file mode: 0x%hx dir mode: 0x%hx",
@@ -3305,10 +3261,14 @@
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
if (pvolume_info->cifs_acl)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
- if (pvolume_info->backupuid_specified)
+ if (pvolume_info->backupuid_specified) {
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
- if (pvolume_info->backupgid_specified)
+ cifs_sb->mnt_backupuid = pvolume_info->backupuid;
+ }
+ if (pvolume_info->backupgid_specified) {
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
+ cifs_sb->mnt_backupgid = pvolume_info->backupgid;
+ }
if (pvolume_info->override_uid)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
if (pvolume_info->override_gid)
@@ -3657,22 +3617,6 @@
return volume_info;
}
-/* make sure ra_pages is a multiple of rsize */
-static inline unsigned int
-cifs_ra_pages(struct cifs_sb_info *cifs_sb)
-{
- unsigned int reads;
- unsigned int rsize_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
-
- if (rsize_pages >= default_backing_dev_info.ra_pages)
- return default_backing_dev_info.ra_pages;
- else if (rsize_pages == 0)
- return rsize_pages;
-
- reads = default_backing_dev_info.ra_pages / rsize_pages;
- return reads * rsize_pages;
-}
-
int
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
{
@@ -3760,7 +3704,7 @@
cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info);
/* tune readahead according to rsize */
- cifs_sb->bdi.ra_pages = cifs_ra_pages(cifs_sb);
+ cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE;
remote_path_check:
#ifdef CONFIG_CIFS_DFS_UPCALL
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index d172c8e..ec4e9a2 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -668,12 +668,19 @@
return 0;
else {
/*
- * Forcibly invalidate automounting directory inodes
- * (remote DFS directories) so to have them
- * instantiated again for automount
+ * If the inode wasn't known to be a dfs entry when
+ * the dentry was instantiated, such as when created
+ * via ->readdir(), it needs to be set now since the
+ * attributes will have been updated by
+ * cifs_revalidate_dentry().
*/
- if (IS_AUTOMOUNT(direntry->d_inode))
- return 0;
+ if (IS_AUTOMOUNT(direntry->d_inode) &&
+ !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
+ spin_lock(&direntry->d_lock);
+ direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+ spin_unlock(&direntry->d_lock);
+ }
+
return 1;
}
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 460d87b..81725e9 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -835,13 +835,21 @@
if ((flock->fl_flags & FL_POSIX) == 0)
return rc;
+try_again:
mutex_lock(&cinode->lock_mutex);
if (!cinode->can_cache_brlcks) {
mutex_unlock(&cinode->lock_mutex);
return rc;
}
- rc = posix_lock_file_wait(file, flock);
+
+ rc = posix_lock_file(file, flock, NULL);
mutex_unlock(&cinode->lock_mutex);
+ if (rc == FILE_LOCK_DEFERRED) {
+ rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next);
+ if (!rc)
+ goto try_again;
+ locks_delete_block(flock);
+ }
return rc;
}
@@ -2170,7 +2178,7 @@
unsigned long nr_pages, i;
size_t copied, len, cur_len;
ssize_t total_written = 0;
- loff_t offset = *poffset;
+ loff_t offset;
struct iov_iter it;
struct cifsFileInfo *open_file;
struct cifs_tcon *tcon;
@@ -2192,6 +2200,7 @@
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
open_file = file->private_data;
tcon = tlink_tcon(open_file->tlink);
+ offset = *poffset;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
pid = open_file->pid;
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
index dd23a32..581c225 100644
--- a/fs/cifs/netmisc.c
+++ b/fs/cifs/netmisc.c
@@ -197,8 +197,7 @@
memcpy(scope_id, pct + 1, slen);
scope_id[slen] = '\0';
- rc = strict_strtoul(scope_id, 0,
- (unsigned long *)&s6->sin6_scope_id);
+ rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id);
rc = (rc == 0) ? 1 : 0;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index b60ddc4..b80531c 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -141,18 +141,29 @@
* Compare 2 name strings, return 0 if they match, otherwise non-zero.
* The strings are both count bytes long, and count is non-zero.
*/
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+
+#include <asm/word-at-a-time.h>
+/*
+ * NOTE! 'cs' and 'scount' come from a dentry, so it has a
+ * aligned allocation for this particular component. We don't
+ * strictly need the load_unaligned_zeropad() safety, but it
+ * doesn't hurt either.
+ *
+ * In contrast, 'ct' and 'tcount' can be from a pathname, and do
+ * need the careful unaligned handling.
+ */
static inline int dentry_cmp(const unsigned char *cs, size_t scount,
const unsigned char *ct, size_t tcount)
{
-#ifdef CONFIG_DCACHE_WORD_ACCESS
unsigned long a,b,mask;
if (unlikely(scount != tcount))
return 1;
for (;;) {
- a = *(unsigned long *)cs;
- b = *(unsigned long *)ct;
+ a = load_unaligned_zeropad(cs);
+ b = load_unaligned_zeropad(ct);
if (tcount < sizeof(unsigned long))
break;
if (unlikely(a != b))
@@ -165,7 +176,13 @@
}
mask = ~(~0ul << tcount*8);
return unlikely(!!((a ^ b) & mask));
+}
+
#else
+
+static inline int dentry_cmp(const unsigned char *cs, size_t scount,
+ const unsigned char *ct, size_t tcount)
+{
if (scount != tcount)
return 1;
@@ -177,9 +194,10 @@
tcount--;
} while (tcount);
return 0;
-#endif
}
+#endif
+
static void __d_free(struct rcu_head *head)
{
struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 21e93605..5dfafdd 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -33,18 +33,10 @@
return count;
}
-static int default_open(struct inode *inode, struct file *file)
-{
- if (inode->i_private)
- file->private_data = inode->i_private;
-
- return 0;
-}
-
const struct file_operations debugfs_file_operations = {
.read = default_read_file,
.write = default_write_file,
- .open = default_open,
+ .open = simple_open,
.llseek = noop_llseek,
};
@@ -447,7 +439,7 @@
static const struct file_operations fops_bool = {
.read = read_file_bool,
.write = write_file_bool,
- .open = default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
@@ -492,7 +484,7 @@
static const struct file_operations fops_blob = {
.read = read_file_blob,
- .open = default_open,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/fs/dlm/debug_fs.c b/fs/dlm/debug_fs.c
index 3dca2b3..1c9b0809 100644
--- a/fs/dlm/debug_fs.c
+++ b/fs/dlm/debug_fs.c
@@ -609,13 +609,6 @@
/*
* dump lkb's on the ls_waiters list
*/
-
-static int waiters_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t waiters_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -644,7 +637,7 @@
static const struct file_operations waiters_fops = {
.owner = THIS_MODULE,
- .open = waiters_open,
+ .open = simple_open,
.read = waiters_read,
.llseek = default_llseek,
};
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index fa5c07d..4c58d4a 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -1737,6 +1737,18 @@
return 1;
/*
+ * Even if the convert is compat with all granted locks,
+ * QUECVT forces it behind other locks on the convert queue.
+ */
+
+ if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) {
+ if (list_empty(&r->res_convertqueue))
+ return 1;
+ else
+ goto out;
+ }
+
+ /*
* The NOORDER flag is set to avoid the standard vms rules on grant
* order.
*/
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 739b098..c0b3c70 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1663,8 +1663,10 @@
if (op == EPOLL_CTL_ADD) {
if (is_file_epoll(tfile)) {
error = -ELOOP;
- if (ep_loop_check(ep, tfile) != 0)
+ if (ep_loop_check(ep, tfile) != 0) {
+ clear_tfile_check_list();
goto error_tgt_fput;
+ }
} else
list_add(&tfile->f_tfile_llink, &tfile_check_list);
}
diff --git a/fs/exec.c b/fs/exec.c
index 9a1d9f0..b1fd202 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1371,7 +1371,7 @@
unsigned int depth = bprm->recursion_depth;
int try,retval;
struct linux_binfmt *fmt;
- pid_t old_pid;
+ pid_t old_pid, old_vpid;
retval = security_bprm_check(bprm);
if (retval)
@@ -1382,8 +1382,9 @@
return retval;
/* Need to fetch pid before load_binary changes it */
+ old_pid = current->pid;
rcu_read_lock();
- old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
+ old_vpid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
rcu_read_unlock();
retval = -ENOENT;
@@ -1406,7 +1407,7 @@
if (retval >= 0) {
if (depth == 0) {
trace_sched_process_exec(current, old_pid, bprm);
- ptrace_event(PTRACE_EVENT_EXEC, old_pid);
+ ptrace_event(PTRACE_EVENT_EXEC, old_vpid);
}
put_binfmt(fmt);
allow_write_access(bprm->file);
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index ab2594a..0e01e90 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1203,9 +1203,6 @@
unsigned long s_ext_blocks;
unsigned long s_ext_extents;
#endif
- /* ext4 extent cache stats */
- unsigned long extent_cache_hits;
- unsigned long extent_cache_misses;
/* for buddy allocator */
struct ext4_group_info ***s_group_info;
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 1421938..abcdeab 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2066,10 +2066,6 @@
ret = 1;
}
errout:
- if (!ret)
- sbi->extent_cache_misses++;
- else
- sbi->extent_cache_hits++;
trace_ext4_ext_in_cache(inode, block, ret);
spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
return ret;
@@ -2882,7 +2878,7 @@
if (err)
goto fix_extent_len;
/* update the extent length and mark as initialized */
- ex->ee_len = cpu_to_le32(ee_len);
+ ex->ee_len = cpu_to_le16(ee_len);
ext4_ext_try_to_merge(inode, path, ex);
err = ext4_ext_dirty(handle, inode, path + depth);
goto out;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ceebaf8..e1fb1d5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1305,20 +1305,20 @@
ext4_msg(sb, KERN_ERR,
"Cannot change journaled "
"quota options when quota turned on");
- return 0;
+ return -1;
}
qname = match_strdup(args);
if (!qname) {
ext4_msg(sb, KERN_ERR,
"Not enough memory for storing quotafile name");
- return 0;
+ return -1;
}
if (sbi->s_qf_names[qtype] &&
strcmp(sbi->s_qf_names[qtype], qname)) {
ext4_msg(sb, KERN_ERR,
"%s quota file already specified", QTYPE2NAME(qtype));
kfree(qname);
- return 0;
+ return -1;
}
sbi->s_qf_names[qtype] = qname;
if (strchr(sbi->s_qf_names[qtype], '/')) {
@@ -1326,7 +1326,7 @@
"quotafile must be on filesystem root");
kfree(sbi->s_qf_names[qtype]);
sbi->s_qf_names[qtype] = NULL;
- return 0;
+ return -1;
}
set_opt(sb, QUOTA);
return 1;
@@ -1341,7 +1341,7 @@
sbi->s_qf_names[qtype]) {
ext4_msg(sb, KERN_ERR, "Cannot change journaled quota options"
" when quota turned on");
- return 0;
+ return -1;
}
/*
* The space will be released later when all options are confirmed
@@ -1450,6 +1450,16 @@
const struct mount_opts *m;
int arg = 0;
+#ifdef CONFIG_QUOTA
+ if (token == Opt_usrjquota)
+ return set_qf_name(sb, USRQUOTA, &args[0]);
+ else if (token == Opt_grpjquota)
+ return set_qf_name(sb, GRPQUOTA, &args[0]);
+ else if (token == Opt_offusrjquota)
+ return clear_qf_name(sb, USRQUOTA);
+ else if (token == Opt_offgrpjquota)
+ return clear_qf_name(sb, GRPQUOTA);
+#endif
if (args->from && match_int(args, &arg))
return -1;
switch (token) {
@@ -1549,18 +1559,6 @@
sbi->s_mount_opt |= m->mount_opt;
}
#ifdef CONFIG_QUOTA
- } else if (token == Opt_usrjquota) {
- if (!set_qf_name(sb, USRQUOTA, &args[0]))
- return -1;
- } else if (token == Opt_grpjquota) {
- if (!set_qf_name(sb, GRPQUOTA, &args[0]))
- return -1;
- } else if (token == Opt_offusrjquota) {
- if (!clear_qf_name(sb, USRQUOTA))
- return -1;
- } else if (token == Opt_offgrpjquota) {
- if (!clear_qf_name(sb, GRPQUOTA))
- return -1;
} else if (m->flags & MOPT_QFMT) {
if (sb_any_quota_loaded(sb) &&
sbi->s_jquota_fmt != m->mount_opt) {
@@ -1599,7 +1597,9 @@
unsigned int *journal_ioprio,
int is_remount)
{
+#ifdef CONFIG_QUOTA
struct ext4_sb_info *sbi = EXT4_SB(sb);
+#endif
char *p;
substring_t args[MAX_OPT_ARGS];
int token;
@@ -2366,18 +2366,6 @@
EXT4_SB(sb)->s_sectors_written_start) >> 1)));
}
-static ssize_t extent_cache_hits_show(struct ext4_attr *a,
- struct ext4_sb_info *sbi, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_hits);
-}
-
-static ssize_t extent_cache_misses_show(struct ext4_attr *a,
- struct ext4_sb_info *sbi, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%lu\n", sbi->extent_cache_misses);
-}
-
static ssize_t inode_readahead_blks_store(struct ext4_attr *a,
struct ext4_sb_info *sbi,
const char *buf, size_t count)
@@ -2435,8 +2423,6 @@
EXT4_RO_ATTR(delayed_allocation_blocks);
EXT4_RO_ATTR(session_write_kbytes);
EXT4_RO_ATTR(lifetime_write_kbytes);
-EXT4_RO_ATTR(extent_cache_hits);
-EXT4_RO_ATTR(extent_cache_misses);
EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, sbi_ui_show,
inode_readahead_blks_store, s_inode_readahead_blks);
EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
@@ -2452,8 +2438,6 @@
ATTR_LIST(delayed_allocation_blocks),
ATTR_LIST(session_write_kbytes),
ATTR_LIST(lifetime_write_kbytes),
- ATTR_LIST(extent_cache_hits),
- ATTR_LIST(extent_cache_misses),
ATTR_LIST(inode_readahead_blks),
ATTR_LIST(inode_goal),
ATTR_LIST(mb_stats),
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 2066328..df5ac04 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -387,9 +387,6 @@
if (fc->no_create)
return -ENOSYS;
- if (flags & O_DIRECT)
- return -EINVAL;
-
forget = fuse_alloc_forget();
if (!forget)
return -ENOMEM;
@@ -644,13 +641,12 @@
fuse_put_request(fc, req);
if (!err) {
struct inode *inode = entry->d_inode;
+ struct fuse_inode *fi = get_fuse_inode(inode);
- /*
- * Set nlink to zero so the inode can be cleared, if the inode
- * does have more links this will be discovered at the next
- * lookup/getattr.
- */
- clear_nlink(inode);
+ spin_lock(&fc->lock);
+ fi->attr_version = ++fc->attr_version;
+ drop_nlink(inode);
+ spin_unlock(&fc->lock);
fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir);
fuse_invalidate_entry_cache(entry);
@@ -762,8 +758,17 @@
will reflect changes in the backing inode (link count,
etc.)
*/
- if (!err || err == -EINTR)
+ if (!err) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+
+ spin_lock(&fc->lock);
+ fi->attr_version = ++fc->attr_version;
+ inc_nlink(inode);
+ spin_unlock(&fc->lock);
fuse_invalidate_attr(inode);
+ } else if (err == -EINTR) {
+ fuse_invalidate_attr(inode);
+ }
return err;
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index a841868..504e61b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -194,10 +194,6 @@
struct fuse_conn *fc = get_fuse_conn(inode);
int err;
- /* VFS checks this, but only _after_ ->open() */
- if (file->f_flags & O_DIRECT)
- return -EINVAL;
-
err = generic_file_open(inode, file);
if (err)
return err;
@@ -932,17 +928,23 @@
struct file *file = iocb->ki_filp;
struct address_space *mapping = file->f_mapping;
size_t count = 0;
+ size_t ocount = 0;
ssize_t written = 0;
+ ssize_t written_buffered = 0;
struct inode *inode = mapping->host;
ssize_t err;
struct iov_iter i;
+ loff_t endbyte = 0;
WARN_ON(iocb->ki_pos != pos);
- err = generic_segment_checks(iov, &nr_segs, &count, VERIFY_READ);
+ ocount = 0;
+ err = generic_segment_checks(iov, &nr_segs, &ocount, VERIFY_READ);
if (err)
return err;
+ count = ocount;
+
mutex_lock(&inode->i_mutex);
vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
@@ -962,11 +964,41 @@
file_update_time(file);
- iov_iter_init(&i, iov, nr_segs, count, 0);
- written = fuse_perform_write(file, mapping, &i, pos);
- if (written >= 0)
- iocb->ki_pos = pos + written;
+ if (file->f_flags & O_DIRECT) {
+ written = generic_file_direct_write(iocb, iov, &nr_segs,
+ pos, &iocb->ki_pos,
+ count, ocount);
+ if (written < 0 || written == count)
+ goto out;
+ pos += written;
+ count -= written;
+
+ iov_iter_init(&i, iov, nr_segs, count, written);
+ written_buffered = fuse_perform_write(file, mapping, &i, pos);
+ if (written_buffered < 0) {
+ err = written_buffered;
+ goto out;
+ }
+ endbyte = pos + written_buffered - 1;
+
+ err = filemap_write_and_wait_range(file->f_mapping, pos,
+ endbyte);
+ if (err)
+ goto out;
+
+ invalidate_mapping_pages(file->f_mapping,
+ pos >> PAGE_CACHE_SHIFT,
+ endbyte >> PAGE_CACHE_SHIFT);
+
+ written += written_buffered;
+ iocb->ki_pos = pos + written_buffered;
+ } else {
+ iov_iter_init(&i, iov, nr_segs, count, 0);
+ written = fuse_perform_write(file, mapping, &i, pos);
+ if (written >= 0)
+ iocb->ki_pos = pos + written;
+ }
out:
current->backing_dev_info = NULL;
mutex_unlock(&inode->i_mutex);
@@ -1101,6 +1133,24 @@
return res;
}
+static ssize_t __fuse_direct_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ ssize_t res;
+
+ res = generic_write_checks(file, ppos, &count, 0);
+ if (!res) {
+ res = fuse_direct_io(file, buf, count, ppos, 1);
+ if (res > 0)
+ fuse_write_update_size(inode, *ppos);
+ }
+
+ fuse_invalidate_attr(inode);
+
+ return res;
+}
+
static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1112,16 +1162,9 @@
/* Don't allow parallel writes to the same file */
mutex_lock(&inode->i_mutex);
- res = generic_write_checks(file, ppos, &count, 0);
- if (!res) {
- res = fuse_direct_io(file, buf, count, ppos, 1);
- if (res > 0)
- fuse_write_update_size(inode, *ppos);
- }
+ res = __fuse_direct_write(file, buf, count, ppos);
mutex_unlock(&inode->i_mutex);
- fuse_invalidate_attr(inode);
-
return res;
}
@@ -2077,6 +2120,57 @@
return 0;
}
+static ssize_t fuse_loop_dio(struct file *filp, const struct iovec *iov,
+ unsigned long nr_segs, loff_t *ppos, int rw)
+{
+ const struct iovec *vector = iov;
+ ssize_t ret = 0;
+
+ while (nr_segs > 0) {
+ void __user *base;
+ size_t len;
+ ssize_t nr;
+
+ base = vector->iov_base;
+ len = vector->iov_len;
+ vector++;
+ nr_segs--;
+
+ if (rw == WRITE)
+ nr = __fuse_direct_write(filp, base, len, ppos);
+ else
+ nr = fuse_direct_read(filp, base, len, ppos);
+
+ if (nr < 0) {
+ if (!ret)
+ ret = nr;
+ break;
+ }
+ ret += nr;
+ if (nr != len)
+ break;
+ }
+
+ return ret;
+}
+
+
+static ssize_t
+fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+ loff_t offset, unsigned long nr_segs)
+{
+ ssize_t ret = 0;
+ struct file *file = NULL;
+ loff_t pos = 0;
+
+ file = iocb->ki_filp;
+ pos = offset;
+
+ ret = fuse_loop_dio(file, iov, nr_segs, &pos, rw);
+
+ return ret;
+}
+
static const struct file_operations fuse_file_operations = {
.llseek = fuse_file_llseek,
.read = do_sync_read,
@@ -2120,6 +2214,7 @@
.readpages = fuse_readpages,
.set_page_dirty = __set_page_dirty_nobuffers,
.bmap = fuse_bmap,
+ .direct_IO = fuse_direct_IO,
};
void fuse_init_file_inode(struct inode *inode)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 4aec599..26783eb 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -947,6 +947,7 @@
sb->s_magic = FUSE_SUPER_MAGIC;
sb->s_op = &fuse_super_operations;
sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_time_gran = 1;
sb->s_export_op = &fuse_export_operations;
file = fget(d.fd);
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig
index c465ae0..eb08c9e 100644
--- a/fs/gfs2/Kconfig
+++ b/fs/gfs2/Kconfig
@@ -1,10 +1,6 @@
config GFS2_FS
tristate "GFS2 file system support"
depends on (64BIT || LBDAF)
- select DLM if GFS2_FS_LOCKING_DLM
- select CONFIGFS_FS if GFS2_FS_LOCKING_DLM
- select SYSFS if GFS2_FS_LOCKING_DLM
- select IP_SCTP if DLM_SCTP
select FS_POSIX_ACL
select CRC32
select QUOTACTL
@@ -29,7 +25,8 @@
config GFS2_FS_LOCKING_DLM
bool "GFS2 DLM locking"
- depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && HOTPLUG
+ depends on (GFS2_FS!=n) && NET && INET && (IPV6 || IPV6=n) && \
+ HOTPLUG && DLM && CONFIGFS_FS && SYSFS
help
Multiple node locking module for GFS2
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 38b7a74..9b2ff0e 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -807,7 +807,7 @@
if (inode == sdp->sd_rindex) {
adjust_fs_space(inode);
- ip->i_gh.gh_flags |= GL_NOCACHE;
+ sdp->sd_rindex_uptodate = 0;
}
brelse(dibh);
@@ -873,7 +873,7 @@
if (inode == sdp->sd_rindex) {
adjust_fs_space(inode);
- ip->i_gh.gh_flags |= GL_NOCACHE;
+ sdp->sd_rindex_uptodate = 0;
}
brelse(dibh);
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 197c5c4..03c04fe 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -724,7 +724,11 @@
int metadata;
unsigned int revokes = 0;
int x;
- int error = 0;
+ int error;
+
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
if (!*top)
sm->sm_first = 0;
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index c35573a..a836056 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -1844,6 +1844,10 @@
unsigned int x, size = len * sizeof(u64);
int error;
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
ht = kzalloc(size, GFP_NOFS);
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index c98a60e..a9ba244 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -1031,7 +1031,13 @@
struct buffer_head *bh;
struct gfs2_holder ghs[3];
struct gfs2_rgrpd *rgd;
- int error = -EROFS;
+ int error;
+
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
+ error = -EROFS;
gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, ghs);
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, ghs + 1);
@@ -1224,6 +1230,10 @@
return 0;
}
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
if (odip != ndip) {
error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE,
0, &r_gh);
@@ -1345,7 +1355,6 @@
error = alloc_required;
if (error < 0)
goto out_gunlock;
- error = 0;
if (alloc_required) {
struct gfs2_qadata *qa = gfs2_qadata_get(ndip);
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index f8411bd..5f5e70e 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -200,10 +200,11 @@
return -1;
}
-static u32 make_flags(const u32 lkid, const unsigned int gfs_flags,
+static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags,
const int req)
{
u32 lkf = DLM_LKF_VALBLK;
+ u32 lkid = gl->gl_lksb.sb_lkid;
if (gfs_flags & LM_FLAG_TRY)
lkf |= DLM_LKF_NOQUEUE;
@@ -227,8 +228,11 @@
BUG();
}
- if (lkid != 0)
+ if (lkid != 0) {
lkf |= DLM_LKF_CONVERT;
+ if (test_bit(GLF_BLOCKING, &gl->gl_flags))
+ lkf |= DLM_LKF_QUECVT;
+ }
return lkf;
}
@@ -250,7 +254,7 @@
char strname[GDLM_STRNAME_BYTES] = "";
req = make_mode(req_state);
- lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req);
+ lkf = make_flags(gl, flags, req);
gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT);
if (gl->gl_lksb.sb_lkid) {
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 19bde40..3df65c9 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -332,9 +332,6 @@
struct rb_node *n, *next;
struct gfs2_rgrpd *cur;
- if (gfs2_rindex_update(sdp))
- return NULL;
-
spin_lock(&sdp->sd_rindex_spin);
n = sdp->sd_rindex_tree.rb_node;
while (n) {
@@ -640,6 +637,7 @@
return 0;
error = 0; /* someone else read in the rgrp; free it and ignore it */
+ gfs2_glock_put(rgd->rd_gl);
fail:
kfree(rgd->rd_bits);
@@ -927,6 +925,10 @@
} else if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT;
+ ret = gfs2_rindex_update(sdp);
+ if (ret)
+ return ret;
+
rgd = gfs2_blk2rgrpd(sdp, r.start, 0);
rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0);
diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
index 2e5ba42..927f4df 100644
--- a/fs/gfs2/xattr.c
+++ b/fs/gfs2/xattr.c
@@ -238,6 +238,10 @@
unsigned int x;
int error;
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
if (GFS2_EA_IS_STUFFED(ea))
return 0;
@@ -1330,6 +1334,10 @@
unsigned int x;
int error;
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, &indbh);
@@ -1439,6 +1447,10 @@
struct gfs2_holder gh;
int error;
+ error = gfs2_rindex_update(sdp);
+ if (error)
+ return error;
+
rgd = gfs2_blk2rgrpd(sdp, ip->i_eattr, 1);
if (!rgd) {
gfs2_consist_inode(ip);
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index 4dfbfec..ec2a9c2 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -366,6 +366,10 @@
err = hfs_brec_find(&src_fd);
if (err)
goto out;
+ if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
src_fd.entrylength);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 88e155f..26b53fb 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -150,6 +150,11 @@
filp->f_pos++;
/* fall through */
case 1:
+ if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
+
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
fd.entrylength);
if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
@@ -181,6 +186,12 @@
err = -EIO;
goto out;
}
+
+ if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
+
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
fd.entrylength);
type = be16_to_cpu(entry.type);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index ea25174..001ef01 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -485,6 +485,7 @@
inode->i_fop = &simple_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */
inc_nlink(inode);
+ lockdep_annotate_inode_mutex_key(inode);
}
return inode;
}
@@ -1031,7 +1032,6 @@
}
error = PTR_ERR(vfsmount);
- unregister_filesystem(&hugetlbfs_fs_type);
out:
kmem_cache_destroy(hugetlbfs_inode_cachep);
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 806525a..840f70f 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -723,7 +723,7 @@
if (commit_transaction->t_need_data_flush &&
(journal->j_fs_dev != journal->j_dev) &&
(journal->j_flags & JBD2_BARRIER))
- blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+ blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
/* Done it all: now write the commit record asynchronously. */
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
@@ -859,7 +859,7 @@
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
journal->j_flags & JBD2_BARRIER) {
- blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+ blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL);
}
if (err)
diff --git a/fs/libfs.c b/fs/libfs.c
index 4a0d1f0..18d08f5 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -264,6 +264,13 @@
return ERR_PTR(-ENOMEM);
}
+int simple_open(struct inode *inode, struct file *file)
+{
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+ return 0;
+}
+
int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
@@ -522,6 +529,7 @@
return 0;
out:
d_genocide(root);
+ shrink_dcache_parent(root);
dput(root);
return -ENOMEM;
}
@@ -984,6 +992,7 @@
EXPORT_SYMBOL(simple_empty);
EXPORT_SYMBOL(simple_fill_super);
EXPORT_SYMBOL(simple_getattr);
+EXPORT_SYMBOL(simple_open);
EXPORT_SYMBOL(simple_link);
EXPORT_SYMBOL(simple_lookup);
EXPORT_SYMBOL(simple_pin_fs);
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 3ddcbb1..13ad153 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -241,7 +241,7 @@
p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
- if (unlikely(*p > nlm4_failed))
+ if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
goto out_bad_xdr;
*stat = *p;
return 0;
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 3d35e3e..d269ada 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -236,7 +236,7 @@
p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
- if (unlikely(*p > nlm_lck_denied_grace_period))
+ if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
goto out_enum;
*stat = *p;
return 0;
diff --git a/fs/locks.c b/fs/locks.c
index 637694b..0d68f1f 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -510,12 +510,13 @@
/*
*/
-static void locks_delete_block(struct file_lock *waiter)
+void locks_delete_block(struct file_lock *waiter)
{
lock_flocks();
__locks_delete_block(waiter);
unlock_flocks();
}
+EXPORT_SYMBOL(locks_delete_block);
/* Insert waiter into blocker's block list.
* We use a circular list so that processes can be easily woken up in
diff --git a/fs/namei.c b/fs/namei.c
index 1898198..c427919 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1407,18 +1407,9 @@
*/
#ifdef CONFIG_DCACHE_WORD_ACCESS
-#ifdef CONFIG_64BIT
+#include <asm/word-at-a-time.h>
-/*
- * Jan Achrenius on G+: microoptimized version of
- * the simpler "(mask & ONEBYTES) * ONEBYTES >> 56"
- * that works for the bytemasks without having to
- * mask them first.
- */
-static inline long count_masked_bytes(unsigned long mask)
-{
- return mask*0x0001020304050608ul >> 56;
-}
+#ifdef CONFIG_64BIT
static inline unsigned int fold_hash(unsigned long hash)
{
@@ -1428,15 +1419,6 @@
#else /* 32-bit case */
-/* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
-static inline long count_masked_bytes(long mask)
-{
- /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
- long a = (0x0ff0001+mask) >> 23;
- /* Fix the 1 for 00 case */
- return a & mask;
-}
-
#define fold_hash(x) (x)
#endif
@@ -1447,7 +1429,7 @@
unsigned long hash = 0;
for (;;) {
- a = *(unsigned long *)name;
+ a = load_unaligned_zeropad(name);
if (len < sizeof(unsigned long))
break;
hash += a;
@@ -1464,17 +1446,6 @@
}
EXPORT_SYMBOL(full_name_hash);
-#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
-#define ONEBYTES REPEAT_BYTE(0x01)
-#define SLASHBYTES REPEAT_BYTE('/')
-#define HIGHBITS REPEAT_BYTE(0x80)
-
-/* Return the high bit set in the first byte that is a zero */
-static inline unsigned long has_zero(unsigned long a)
-{
- return ((a - ONEBYTES) & ~a) & HIGHBITS;
-}
-
/*
* Calculate the length and hash of the path component, and
* return the length of the component;
@@ -1488,9 +1459,9 @@
do {
hash = (hash + a) * 9;
len += sizeof(unsigned long);
- a = *(unsigned long *)(name+len);
+ a = load_unaligned_zeropad(name+len);
/* Do we have any NUL or '/' bytes in this word? */
- mask = has_zero(a) | has_zero(a ^ SLASHBYTES);
+ mask = has_zero(a) | has_zero(a ^ REPEAT_BYTE('/'));
} while (!mask);
/* The mask *below* the first high bit set */
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 9c94297..7f6a23f 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -38,6 +38,8 @@
#include <linux/buffer_head.h> /* various write calls */
#include <linux/prefetch.h>
+#include "../pnfs.h"
+#include "../internal.h"
#include "blocklayout.h"
#define NFSDBG_FACILITY NFSDBG_PNFS_LD
@@ -868,7 +870,7 @@
* GETDEVICEINFO's maxcount
*/
max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
- max_pages = max_resp_sz >> PAGE_SHIFT;
+ max_pages = nfs_page_array_len(0, max_resp_sz);
dprintk("%s max_resp_sz %u max_pages %d\n",
__func__, max_resp_sz, max_pages);
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index da7b5e4..60f7e4e 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -1729,7 +1729,8 @@
*/
struct nfs_server *nfs_clone_server(struct nfs_server *source,
struct nfs_fh *fh,
- struct nfs_fattr *fattr)
+ struct nfs_fattr *fattr,
+ rpc_authflavor_t flavor)
{
struct nfs_server *server;
struct nfs_fattr *fattr_fsinfo;
@@ -1758,7 +1759,7 @@
error = nfs_init_server_rpcclient(server,
source->client->cl_timeout,
- source->client->cl_auth->au_flavor);
+ flavor);
if (error < 0)
goto out_free_server;
if (!IS_ERR(source->client_acl))
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 4aaf031..8789210 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1429,7 +1429,7 @@
}
open_flags = nd->intent.open.flags;
- attr.ia_valid = 0;
+ attr.ia_valid = ATTR_OPEN;
ctx = create_nfs_open_context(dentry, open_flags);
res = ERR_CAST(ctx);
@@ -1536,7 +1536,7 @@
if (IS_ERR(ctx))
goto out;
- attr.ia_valid = 0;
+ attr.ia_valid = ATTR_OPEN;
if (openflags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index b7f348b..ba3019f 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -554,12 +554,16 @@
struct nfs_client *clp;
int error = 0;
+ if (!try_module_get(THIS_MODULE))
+ return 0;
+
while ((clp = nfs_get_client_for_event(sb->s_fs_info, event))) {
error = __rpc_pipefs_event(clp, event, sb);
nfs_put_client(clp);
if (error)
break;
}
+ module_put(THIS_MODULE);
return error;
}
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 2476dc6..b777bda 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -165,7 +165,8 @@
extern void nfs_free_server(struct nfs_server *server);
extern struct nfs_server *nfs_clone_server(struct nfs_server *,
struct nfs_fh *,
- struct nfs_fattr *);
+ struct nfs_fattr *,
+ rpc_authflavor_t);
extern void nfs_mark_client_ready(struct nfs_client *clp, int state);
extern int nfs4_check_client_ready(struct nfs_client *clp);
extern struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp,
@@ -186,10 +187,10 @@
/* nfs4namespace.c */
#ifdef CONFIG_NFS_V4
-extern struct vfsmount *nfs_do_refmount(struct dentry *dentry);
+extern struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry);
#else
static inline
-struct vfsmount *nfs_do_refmount(struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
{
return ERR_PTR(-ENOENT);
}
@@ -234,7 +235,6 @@
/* nfs4proc.c */
#ifdef CONFIG_NFS_V4
extern struct rpc_procinfo nfs4_procedures[];
-void nfs_fixup_secinfo_attributes(struct nfs_fattr *, struct nfs_fh *);
#endif
extern int nfs4_init_ds_session(struct nfs_client *clp);
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index 1807866..d51868e 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -148,66 +148,31 @@
return pseudoflavor;
}
-static int nfs_negotiate_security(const struct dentry *parent,
- const struct dentry *dentry,
- rpc_authflavor_t *flavor)
+static struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
+ struct qstr *name,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr)
{
- struct page *page;
- struct nfs4_secinfo_flavors *flavors;
- int (*secinfo)(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
- int ret = -EPERM;
-
- secinfo = NFS_PROTO(parent->d_inode)->secinfo;
- if (secinfo != NULL) {
- page = alloc_page(GFP_KERNEL);
- if (!page) {
- ret = -ENOMEM;
- goto out;
- }
- flavors = page_address(page);
- ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
- *flavor = nfs_find_best_sec(flavors);
- put_page(page);
- }
-
-out:
- return ret;
-}
-
-static int nfs_lookup_with_sec(struct nfs_server *server, struct dentry *parent,
- struct dentry *dentry, struct path *path,
- struct nfs_fh *fh, struct nfs_fattr *fattr,
- rpc_authflavor_t *flavor)
-{
- struct rpc_clnt *clone;
- struct rpc_auth *auth;
int err;
- err = nfs_negotiate_security(parent, path->dentry, flavor);
- if (err < 0)
- goto out;
- clone = rpc_clone_client(server->client);
- auth = rpcauth_create(*flavor, clone);
- if (!auth) {
- err = -EIO;
- goto out_shutdown;
- }
- err = server->nfs_client->rpc_ops->lookup(clone, parent->d_inode,
- &path->dentry->d_name,
- fh, fattr);
-out_shutdown:
- rpc_shutdown_client(clone);
-out:
- return err;
+ if (NFS_PROTO(dir)->version == 4)
+ return nfs4_proc_lookup_mountpoint(dir, name, fh, fattr);
+
+ err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
+ if (err)
+ return ERR_PTR(err);
+ return rpc_clone_client(NFS_SERVER(dir)->client);
}
#else /* CONFIG_NFS_V4 */
-static inline int nfs_lookup_with_sec(struct nfs_server *server,
- struct dentry *parent, struct dentry *dentry,
- struct path *path, struct nfs_fh *fh,
- struct nfs_fattr *fattr,
- rpc_authflavor_t *flavor)
+static inline struct rpc_clnt *nfs_lookup_mountpoint(struct inode *dir,
+ struct qstr *name,
+ struct nfs_fh *fh,
+ struct nfs_fattr *fattr)
{
- return -EPERM;
+ int err = NFS_PROTO(dir)->lookup(NFS_SERVER(dir)->client, dir, name, fh, fattr);
+ if (err)
+ return ERR_PTR(err);
+ return rpc_clone_client(NFS_SERVER(dir)->client);
}
#endif /* CONFIG_NFS_V4 */
@@ -226,12 +191,10 @@
struct vfsmount *nfs_d_automount(struct path *path)
{
struct vfsmount *mnt;
- struct nfs_server *server = NFS_SERVER(path->dentry->d_inode);
struct dentry *parent;
struct nfs_fh *fh = NULL;
struct nfs_fattr *fattr = NULL;
- int err;
- rpc_authflavor_t flavor = RPC_AUTH_UNIX;
+ struct rpc_clnt *client;
dprintk("--> nfs_d_automount()\n");
@@ -249,21 +212,19 @@
/* Look it up again to get its attributes */
parent = dget_parent(path->dentry);
- err = server->nfs_client->rpc_ops->lookup(server->client, parent->d_inode,
- &path->dentry->d_name,
- fh, fattr);
- if (err == -EPERM && NFS_PROTO(parent->d_inode)->secinfo != NULL)
- err = nfs_lookup_with_sec(server, parent, path->dentry, path, fh, fattr, &flavor);
+ client = nfs_lookup_mountpoint(parent->d_inode, &path->dentry->d_name, fh, fattr);
dput(parent);
- if (err != 0) {
- mnt = ERR_PTR(err);
+ if (IS_ERR(client)) {
+ mnt = ERR_CAST(client);
goto out;
}
if (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)
- mnt = nfs_do_refmount(path->dentry);
+ mnt = nfs_do_refmount(client, path->dentry);
else
- mnt = nfs_do_submount(path->dentry, fh, fattr, flavor);
+ mnt = nfs_do_submount(path->dentry, fh, fattr, client->cl_auth->au_flavor);
+ rpc_shutdown_client(client);
+
if (IS_ERR(mnt))
goto out;
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 97ecc86..8d75021 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -59,6 +59,7 @@
#define NFS_SEQID_CONFIRMED 1
struct nfs_seqid_counter {
+ ktime_t create_time;
int owner_id;
int flags;
u32 counter;
@@ -204,6 +205,9 @@
extern const struct dentry_operations nfs4_dentry_operations;
extern const struct inode_operations nfs4_dir_inode_operations;
+/* nfs4namespace.c */
+struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *, struct inode *, struct qstr *);
+
/* nfs4proc.c */
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
@@ -212,8 +216,11 @@
extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
extern int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait, bool roc);
extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
-extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
- struct nfs4_fs_locations *fs_locations, struct page *page);
+extern int nfs4_proc_fs_locations(struct rpc_clnt *, struct inode *, const struct qstr *,
+ struct nfs4_fs_locations *, struct page *);
+extern struct rpc_clnt *nfs4_proc_lookup_mountpoint(struct inode *, struct qstr *,
+ struct nfs_fh *, struct nfs_fattr *);
+extern int nfs4_proc_secinfo(struct inode *, const struct qstr *, struct nfs4_secinfo_flavors *);
extern int nfs4_release_lockowner(struct nfs4_lock_state *);
extern const struct xattr_handler *nfs4_xattr_handlers[];
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index a866bbd..c9cff9a 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -699,7 +699,7 @@
* GETDEVICEINFO's maxcount
*/
max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
- max_pages = max_resp_sz >> PAGE_SHIFT;
+ max_pages = nfs_page_array_len(0, max_resp_sz);
dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
__func__, inode, max_resp_sz, max_pages);
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 9c8eca31..a7f3ded 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -52,6 +52,30 @@
}
/*
+ * return the path component of "<server>:<path>"
+ * nfspath - the "<server>:<path>" string
+ * end - one past the last char that could contain "<server>:"
+ * returns NULL on failure
+ */
+static char *nfs_path_component(const char *nfspath, const char *end)
+{
+ char *p;
+
+ if (*nfspath == '[') {
+ /* parse [] escaped IPv6 addrs */
+ p = strchr(nfspath, ']');
+ if (p != NULL && ++p < end && *p == ':')
+ return p + 1;
+ } else {
+ /* otherwise split on first colon */
+ p = strchr(nfspath, ':');
+ if (p != NULL && p < end)
+ return p + 1;
+ }
+ return NULL;
+}
+
+/*
* Determine the mount path as a string
*/
static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
@@ -59,9 +83,9 @@
char *limit;
char *path = nfs_path(&limit, dentry, buffer, buflen);
if (!IS_ERR(path)) {
- char *colon = strchr(path, ':');
- if (colon && colon < limit)
- path = colon + 1;
+ char *path_component = nfs_path_component(path, limit);
+ if (path_component)
+ return path_component;
}
return path;
}
@@ -108,6 +132,58 @@
return ret;
}
+static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name)
+{
+ struct page *page;
+ struct nfs4_secinfo_flavors *flavors;
+ rpc_authflavor_t flavor;
+ int err;
+
+ page = alloc_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ flavors = page_address(page);
+
+ err = nfs4_proc_secinfo(inode, name, flavors);
+ if (err < 0) {
+ flavor = err;
+ goto out;
+ }
+
+ flavor = nfs_find_best_sec(flavors);
+
+out:
+ put_page(page);
+ return flavor;
+}
+
+/*
+ * Please call rpc_shutdown_client() when you are done with this client.
+ */
+struct rpc_clnt *nfs4_create_sec_client(struct rpc_clnt *clnt, struct inode *inode,
+ struct qstr *name)
+{
+ struct rpc_clnt *clone;
+ struct rpc_auth *auth;
+ rpc_authflavor_t flavor;
+
+ flavor = nfs4_negotiate_security(inode, name);
+ if (flavor < 0)
+ return ERR_PTR(flavor);
+
+ clone = rpc_clone_client(clnt);
+ if (IS_ERR(clone))
+ return clone;
+
+ auth = rpcauth_create(flavor, clone);
+ if (!auth) {
+ rpc_shutdown_client(clone);
+ clone = ERR_PTR(-EIO);
+ }
+
+ return clone;
+}
+
static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
char *page, char *page2,
const struct nfs4_fs_location *location)
@@ -224,7 +300,7 @@
* @dentry - dentry of referral
*
*/
-struct vfsmount *nfs_do_refmount(struct dentry *dentry)
+struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *dentry)
{
struct vfsmount *mnt = ERR_PTR(-ENOMEM);
struct dentry *parent;
@@ -250,7 +326,7 @@
dprintk("%s: getting locations for %s/%s\n",
__func__, parent->d_name.name, dentry->d_name.name);
- err = nfs4_proc_fs_locations(parent->d_inode, &dentry->d_name, fs_locations, page);
+ err = nfs4_proc_fs_locations(client, parent->d_inode, &dentry->d_name, fs_locations, page);
dput(parent);
if (err != 0 ||
fs_locations->nlocations <= 0 ||
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f82bde0..99650aa 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -838,7 +838,8 @@
p->o_arg.open_flags = flags;
p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
p->o_arg.clientid = server->nfs_client->cl_clientid;
- p->o_arg.id = sp->so_seqid.owner_id;
+ p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
+ p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
p->o_arg.name = &dentry->d_name;
p->o_arg.server = server;
p->o_arg.bitmask = server->attr_bitmask;
@@ -1466,8 +1467,7 @@
goto unlock_no_action;
rcu_read_unlock();
}
- /* Update sequence id. */
- data->o_arg.id = sp->so_seqid.owner_id;
+ /* Update client id. */
data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
@@ -1954,10 +1954,19 @@
};
int err;
do {
- err = nfs4_handle_exception(server,
- _nfs4_do_setattr(inode, cred, fattr, sattr, state),
- &exception);
+ err = _nfs4_do_setattr(inode, cred, fattr, sattr, state);
+ switch (err) {
+ case -NFS4ERR_OPENMODE:
+ if (state && !(state->state & FMODE_WRITE)) {
+ err = -EBADF;
+ if (sattr->ia_valid & ATTR_OPEN)
+ err = -EACCES;
+ goto out;
+ }
+ }
+ err = nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
+out:
return err;
}
@@ -2368,8 +2377,9 @@
* Note that we'll actually follow the referral later when
* we detect fsid mismatch in inode revalidation
*/
-static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
- struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+static int nfs4_get_referral(struct rpc_clnt *client, struct inode *dir,
+ const struct qstr *name, struct nfs_fattr *fattr,
+ struct nfs_fh *fhandle)
{
int status = -ENOMEM;
struct page *page = NULL;
@@ -2382,7 +2392,7 @@
if (locations == NULL)
goto out;
- status = nfs4_proc_fs_locations(dir, name, locations, page);
+ status = nfs4_proc_fs_locations(client, dir, name, locations, page);
if (status != 0)
goto out;
/* Make sure server returned a different fsid for the referral */
@@ -2519,37 +2529,82 @@
return status;
}
-void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr, struct nfs_fh *fh)
+static void nfs_fixup_secinfo_attributes(struct nfs_fattr *fattr)
{
- memset(fh, 0, sizeof(struct nfs_fh));
- fattr->fsid.major = 1;
fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
- NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_FSID | NFS_ATTR_FATTR_MOUNTPOINT;
+ NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_MOUNTPOINT;
fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO;
fattr->nlink = 2;
}
+static int nfs4_proc_lookup_common(struct rpc_clnt **clnt, struct inode *dir,
+ struct qstr *name, struct nfs_fh *fhandle,
+ struct nfs_fattr *fattr)
+{
+ struct nfs4_exception exception = { };
+ struct rpc_clnt *client = *clnt;
+ int err;
+ do {
+ err = _nfs4_proc_lookup(client, dir, name, fhandle, fattr);
+ switch (err) {
+ case -NFS4ERR_BADNAME:
+ err = -ENOENT;
+ goto out;
+ case -NFS4ERR_MOVED:
+ err = nfs4_get_referral(client, dir, name, fattr, fhandle);
+ goto out;
+ case -NFS4ERR_WRONGSEC:
+ err = -EPERM;
+ if (client != *clnt)
+ goto out;
+
+ client = nfs4_create_sec_client(client, dir, name);
+ if (IS_ERR(client))
+ return PTR_ERR(client);
+
+ exception.retry = 1;
+ break;
+ default:
+ err = nfs4_handle_exception(NFS_SERVER(dir), err, &exception);
+ }
+ } while (exception.retry);
+
+out:
+ if (err == 0)
+ *clnt = client;
+ else if (client != *clnt)
+ rpc_shutdown_client(client);
+
+ return err;
+}
+
static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
- struct nfs4_exception exception = { };
- int err;
- do {
- int status;
+ int status;
+ struct rpc_clnt *client = NFS_CLIENT(dir);
- status = _nfs4_proc_lookup(clnt, dir, name, fhandle, fattr);
- switch (status) {
- case -NFS4ERR_BADNAME:
- return -ENOENT;
- case -NFS4ERR_MOVED:
- return nfs4_get_referral(dir, name, fattr, fhandle);
- case -NFS4ERR_WRONGSEC:
- nfs_fixup_secinfo_attributes(fattr, fhandle);
- }
- err = nfs4_handle_exception(NFS_SERVER(dir),
- status, &exception);
- } while (exception.retry);
- return err;
+ status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
+ if (client != NFS_CLIENT(dir)) {
+ rpc_shutdown_client(client);
+ nfs_fixup_secinfo_attributes(fattr);
+ }
+ return status;
+}
+
+struct rpc_clnt *
+nfs4_proc_lookup_mountpoint(struct inode *dir, struct qstr *name,
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+{
+ int status;
+ struct rpc_clnt *client = rpc_clone_client(NFS_CLIENT(dir));
+
+ status = nfs4_proc_lookup_common(&client, dir, name, fhandle, fattr);
+ if (status < 0) {
+ rpc_shutdown_client(client);
+ return ERR_PTR(status);
+ }
+ return client;
}
static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry)
@@ -3619,16 +3674,16 @@
return ret;
}
-static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
+static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size_t pgbase, size_t acl_len)
{
struct nfs4_cached_acl *acl;
- if (buf && acl_len <= PAGE_SIZE) {
+ if (pages && acl_len <= PAGE_SIZE) {
acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
if (acl == NULL)
goto out;
acl->cached = 1;
- memcpy(acl->data, buf, acl_len);
+ _copy_from_pages(acl->data, pages, pgbase, acl_len);
} else {
acl = kmalloc(sizeof(*acl), GFP_KERNEL);
if (acl == NULL)
@@ -3661,7 +3716,6 @@
struct nfs_getaclres res = {
.acl_len = buflen,
};
- void *resp_buf;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
.rpc_argp = &args,
@@ -3675,24 +3729,27 @@
if (npages == 0)
npages = 1;
+ /* Add an extra page to handle the bitmap returned */
+ npages++;
+
for (i = 0; i < npages; i++) {
pages[i] = alloc_page(GFP_KERNEL);
if (!pages[i])
goto out_free;
}
- if (npages > 1) {
- /* for decoding across pages */
- res.acl_scratch = alloc_page(GFP_KERNEL);
- if (!res.acl_scratch)
- goto out_free;
- }
+
+ /* for decoding across pages */
+ res.acl_scratch = alloc_page(GFP_KERNEL);
+ if (!res.acl_scratch)
+ goto out_free;
+
args.acl_len = npages * PAGE_SIZE;
args.acl_pgbase = 0;
+
/* Let decode_getfacl know not to fail if the ACL data is larger than
* the page we send as a guess */
if (buf == NULL)
res.acl_flags |= NFS4_ACL_LEN_REQUEST;
- resp_buf = page_address(pages[0]);
dprintk("%s buf %p buflen %zu npages %d args.acl_len %zu\n",
__func__, buf, buflen, npages, args.acl_len);
@@ -3703,9 +3760,9 @@
acl_len = res.acl_len - res.acl_data_offset;
if (acl_len > args.acl_len)
- nfs4_write_cached_acl(inode, NULL, acl_len);
+ nfs4_write_cached_acl(inode, NULL, 0, acl_len);
else
- nfs4_write_cached_acl(inode, resp_buf + res.acl_data_offset,
+ nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
acl_len);
if (buf) {
ret = -ERANGE;
@@ -4558,7 +4615,9 @@
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .inode = state->inode,
+ };
int err;
do {
@@ -4576,7 +4635,9 @@
static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .inode = state->inode,
+ };
int err;
err = nfs4_set_lock_state(state, request);
@@ -4676,6 +4737,7 @@
{
struct nfs4_exception exception = {
.state = state,
+ .inode = state->inode,
};
int err;
@@ -4721,6 +4783,20 @@
if (state == NULL)
return -ENOLCK;
+ /*
+ * Don't rely on the VFS having checked the file open mode,
+ * since it won't do this for flock() locks.
+ */
+ switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
+ case F_RDLCK:
+ if (!(filp->f_mode & FMODE_READ))
+ return -EBADF;
+ break;
+ case F_WRLCK:
+ if (!(filp->f_mode & FMODE_WRITE))
+ return -EBADF;
+ }
+
do {
status = nfs4_proc_setlk(state, cmd, request);
if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4891,8 +4967,10 @@
fattr->nlink = 2;
}
-int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
- struct nfs4_fs_locations *fs_locations, struct page *page)
+static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
+ const struct qstr *name,
+ struct nfs4_fs_locations *fs_locations,
+ struct page *page)
{
struct nfs_server *server = NFS_SERVER(dir);
u32 bitmask[2] = {
@@ -4926,11 +5004,26 @@
nfs_fattr_init(&fs_locations->fattr);
fs_locations->server = server;
fs_locations->nlocations = 0;
- status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+ status = nfs4_call_sync(client, server, &msg, &args.seq_args, &res.seq_res, 0);
dprintk("%s: returned status = %d\n", __func__, status);
return status;
}
+int nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir,
+ const struct qstr *name,
+ struct nfs4_fs_locations *fs_locations,
+ struct page *page)
+{
+ struct nfs4_exception exception = { };
+ int err;
+ do {
+ err = nfs4_handle_exception(NFS_SERVER(dir),
+ _nfs4_proc_fs_locations(client, dir, name, fs_locations, page),
+ &exception);
+ } while (exception.retry);
+ return err;
+}
+
static int _nfs4_proc_secinfo(struct inode *dir, const struct qstr *name, struct nfs4_secinfo_flavors *flavors)
{
int status;
@@ -4953,8 +5046,8 @@
return status;
}
-static int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
- struct nfs4_secinfo_flavors *flavors)
+int nfs4_proc_secinfo(struct inode *dir, const struct qstr *name,
+ struct nfs4_secinfo_flavors *flavors)
{
struct nfs4_exception exception = { };
int err;
@@ -5029,10 +5122,9 @@
nfs4_construct_boot_verifier(clp, &verifier);
args.id_len = scnprintf(args.id, sizeof(args.id),
- "%s/%s.%s/%u",
+ "%s/%s/%u",
clp->cl_ipaddr,
- init_utsname()->nodename,
- init_utsname()->domainname,
+ clp->cl_rpcclient->cl_nodename,
clp->cl_rpcclient->cl_auth->au_flavor);
res.server_scope = kzalloc(sizeof(struct server_scope), GFP_KERNEL);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0f43414..7f0fcfc 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -393,6 +393,7 @@
static void
nfs4_init_seqid_counter(struct nfs_seqid_counter *sc)
{
+ sc->create_time = ktime_get();
sc->flags = 0;
sc->counter = 0;
spin_lock_init(&sc->lock);
@@ -434,13 +435,17 @@
static void
nfs4_drop_state_owner(struct nfs4_state_owner *sp)
{
- if (!RB_EMPTY_NODE(&sp->so_server_node)) {
+ struct rb_node *rb_node = &sp->so_server_node;
+
+ if (!RB_EMPTY_NODE(rb_node)) {
struct nfs_server *server = sp->so_server;
struct nfs_client *clp = server->nfs_client;
spin_lock(&clp->cl_lock);
- rb_erase(&sp->so_server_node, &server->state_owners);
- RB_CLEAR_NODE(&sp->so_server_node);
+ if (!RB_EMPTY_NODE(rb_node)) {
+ rb_erase(rb_node, &server->state_owners);
+ RB_CLEAR_NODE(rb_node);
+ }
spin_unlock(&clp->cl_lock);
}
}
@@ -516,6 +521,14 @@
/**
* nfs4_put_state_owner - Release a nfs4_state_owner
* @sp: state owner data to release
+ *
+ * Note that we keep released state owners on an LRU
+ * list.
+ * This caches valid state owners so that they can be
+ * reused, to avoid the OPEN_CONFIRM on minor version 0.
+ * It also pins the uniquifier of dropped state owners for
+ * a while, to ensure that those state owner names are
+ * never reused.
*/
void nfs4_put_state_owner(struct nfs4_state_owner *sp)
{
@@ -525,15 +538,9 @@
if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock))
return;
- if (!RB_EMPTY_NODE(&sp->so_server_node)) {
- sp->so_expires = jiffies;
- list_add_tail(&sp->so_lru, &server->state_owners_lru);
- spin_unlock(&clp->cl_lock);
- } else {
- nfs4_remove_state_owner_locked(sp);
- spin_unlock(&clp->cl_lock);
- nfs4_free_state_owner(sp);
- }
+ sp->so_expires = jiffies;
+ list_add_tail(&sp->so_lru, &server->state_owners_lru);
+ spin_unlock(&clp->cl_lock);
}
/**
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c74fdb1..c54aae3 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -74,7 +74,7 @@
/* lock,open owner id:
* we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
*/
-#define open_owner_id_maxsz (1 + 1 + 4)
+#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2)
#define lock_owner_id_maxsz (1 + 1 + 4)
#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
@@ -1340,12 +1340,13 @@
*/
encode_nfs4_seqid(xdr, arg->seqid);
encode_share_access(xdr, arg->fmode);
- p = reserve_space(xdr, 32);
+ p = reserve_space(xdr, 36);
p = xdr_encode_hyper(p, arg->clientid);
- *p++ = cpu_to_be32(20);
+ *p++ = cpu_to_be32(24);
p = xdr_encode_opaque_fixed(p, "open id:", 8);
*p++ = cpu_to_be32(arg->server->s_dev);
- xdr_encode_hyper(p, arg->id);
+ *p++ = cpu_to_be32(arg->id.uniquifier);
+ xdr_encode_hyper(p, arg->id.create_time);
}
static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
@@ -4257,8 +4258,6 @@
status = decode_attr_error(xdr, bitmap, &err);
if (status < 0)
goto xdr_error;
- if (err == -NFS4ERR_WRONGSEC)
- nfs_fixup_secinfo_attributes(fattr, fh);
status = decode_attr_filehandle(xdr, bitmap, fh);
if (status < 0)
@@ -4901,11 +4900,19 @@
bitmap[3] = {0};
struct kvec *iov = req->rq_rcv_buf.head;
int status;
+ size_t page_len = xdr->buf->page_len;
res->acl_len = 0;
if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
goto out;
+
bm_p = xdr->p;
+ res->acl_data_offset = be32_to_cpup(bm_p) + 2;
+ res->acl_data_offset <<= 2;
+ /* Check if the acl data starts beyond the allocated buffer */
+ if (res->acl_data_offset > page_len)
+ return -ERANGE;
+
if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
goto out;
if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
@@ -4915,28 +4922,24 @@
return -EIO;
if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
size_t hdrlen;
- u32 recvd;
/* The bitmap (xdr len + bitmaps) and the attr xdr len words
* are stored with the acl data to handle the problem of
* variable length bitmaps.*/
xdr->p = bm_p;
- res->acl_data_offset = be32_to_cpup(bm_p) + 2;
- res->acl_data_offset <<= 2;
/* We ignore &savep and don't do consistency checks on
* the attr length. Let userspace figure it out.... */
hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
attrlen += res->acl_data_offset;
- recvd = req->rq_rcv_buf.len - hdrlen;
- if (attrlen > recvd) {
+ if (attrlen > page_len) {
if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
/* getxattr interface called with a NULL buf */
res->acl_len = attrlen;
goto out;
}
- dprintk("NFS: acl reply: attrlen %u > recvd %u\n",
- attrlen, recvd);
+ dprintk("NFS: acl reply: attrlen %u > page_len %zu\n",
+ attrlen, page_len);
return -EINVAL;
}
xdr_read_pages(xdr, attrlen);
@@ -5089,16 +5092,13 @@
return -EINVAL;
}
-static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
{
struct nfs4_secinfo_flavor *sec_flavor;
int status;
__be32 *p;
int i, num_flavors;
- status = decode_op_hdr(xdr, OP_SECINFO);
- if (status)
- goto out;
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
goto out_overflow;
@@ -5124,6 +5124,7 @@
res->flavors->num_flavors++;
}
+ status = 0;
out:
return status;
out_overflow:
@@ -5131,7 +5132,23 @@
return -EIO;
}
+static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+{
+ int status = decode_op_hdr(xdr, OP_SECINFO);
+ if (status)
+ return status;
+ return decode_secinfo_common(xdr, res);
+}
+
#if defined(CONFIG_NFS_V4_1)
+static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
+{
+ int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME);
+ if (status)
+ return status;
+ return decode_secinfo_common(xdr, res);
+}
+
static int decode_exchange_id(struct xdr_stream *xdr,
struct nfs41_exchange_id_res *res)
{
@@ -6816,7 +6833,7 @@
status = decode_putrootfh(xdr);
if (status)
goto out;
- status = decode_secinfo(xdr, res);
+ status = decode_secinfo_no_name(xdr, res);
out:
return status;
}
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
index 8d45f1c..595c5fc 100644
--- a/fs/nfs/objlayout/objlayout.c
+++ b/fs/nfs/objlayout/objlayout.c
@@ -604,7 +604,6 @@
{
struct objlayout_deviceinfo *odi;
struct pnfs_device pd;
- struct super_block *sb;
struct page *page, **pages;
u32 *p;
int err;
@@ -623,7 +622,6 @@
pd.pglen = PAGE_SIZE;
pd.mincount = 0;
- sb = pnfslay->plh_inode->i_sb;
err = nfs4_proc_getdeviceinfo(NFS_SERVER(pnfslay->plh_inode), &pd);
dprintk("%s nfs_getdeviceinfo returned %d\n", __func__, err);
if (err)
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index b5d4515..38512bc 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -587,7 +587,7 @@
/* allocate pages for xdr post processing */
max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
- max_pages = max_resp_sz >> PAGE_SHIFT;
+ max_pages = nfs_page_array_len(0, max_resp_sz);
pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags);
if (!pages)
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 9a0e8ef4..0a4be28 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -322,7 +322,7 @@
while (!list_empty(res)) {
data = list_entry(res->next, struct nfs_read_data, list);
list_del(&data->list);
- nfs_readdata_free(data);
+ nfs_readdata_release(data);
}
nfs_readpage_release(req);
return -ENOMEM;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 37412f7..4ac7fca 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2428,7 +2428,7 @@
dprintk("--> nfs_xdev_mount()\n");
/* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
if (IS_ERR(server)) {
error = PTR_ERR(server);
goto out_err_noserver;
@@ -2767,11 +2767,15 @@
char *root_devname;
size_t len;
- len = strlen(hostname) + 3;
+ len = strlen(hostname) + 5;
root_devname = kmalloc(len, GFP_KERNEL);
if (root_devname == NULL)
return ERR_PTR(-ENOMEM);
- snprintf(root_devname, len, "%s:/", hostname);
+ /* Does hostname needs to be enclosed in brackets? */
+ if (strchr(hostname, ':'))
+ snprintf(root_devname, len, "[%s]:/", hostname);
+ else
+ snprintf(root_devname, len, "%s:/", hostname);
root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
kfree(root_devname);
return root_mnt;
@@ -2951,7 +2955,7 @@
dprintk("--> nfs4_xdev_mount()\n");
/* create a new volume representation */
- server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr);
+ server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
if (IS_ERR(server)) {
error = PTR_ERR(server);
goto out_err_noserver;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 2c68818..c074623 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -682,7 +682,8 @@
req->wb_bytes = rqend - req->wb_offset;
out_unlock:
spin_unlock(&inode->i_lock);
- nfs_clear_request_commit(req);
+ if (req)
+ nfs_clear_request_commit(req);
return req;
out_flushme:
spin_unlock(&inode->i_lock);
@@ -1018,7 +1019,7 @@
while (!list_empty(res)) {
data = list_entry(res->next, struct nfs_write_data, list);
list_del(&data->list);
- nfs_writedata_free(data);
+ nfs_writedata_release(data);
}
nfs_redirty_request(req);
return -ENOMEM;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 08c6e36..43f46cd 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -803,13 +803,13 @@
return p;
}
-static int
+static __be32
compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
const char *name, int namlen)
{
struct svc_export *exp;
struct dentry *dparent, *dchild;
- int rv = 0;
+ __be32 rv = nfserr_noent;
dparent = cd->fh.fh_dentry;
exp = cd->fh.fh_export;
@@ -817,26 +817,20 @@
if (isdotent(name, namlen)) {
if (namlen == 2) {
dchild = dget_parent(dparent);
- if (dchild == dparent) {
- /* filesystem root - cannot return filehandle for ".." */
- dput(dchild);
- return -ENOENT;
- }
+ /* filesystem root - cannot return filehandle for ".." */
+ if (dchild == dparent)
+ goto out;
} else
dchild = dget(dparent);
} else
dchild = lookup_one_len(name, dparent, namlen);
if (IS_ERR(dchild))
- return -ENOENT;
- rv = -ENOENT;
+ return rv;
if (d_mountpoint(dchild))
goto out;
- rv = fh_compose(fhp, exp, dchild, &cd->fh);
- if (rv)
- goto out;
if (!dchild->d_inode)
goto out;
- rv = 0;
+ rv = fh_compose(fhp, exp, dchild, &cd->fh);
out:
dput(dchild);
return rv;
@@ -845,7 +839,7 @@
static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
{
struct svc_fh fh;
- int err;
+ __be32 err;
fh_init(&fh, NFS3_FHSIZE);
err = compose_entry_fh(cd, &fh, name, namlen);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 2ed14df..987e719 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -235,17 +235,17 @@
*/
if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
- FATTR4_WORD1_TIME_MODIFY);
+ FATTR4_WORD1_TIME_MODIFY);
} else {
status = nfsd_lookup(rqstp, current_fh,
open->op_fname.data, open->op_fname.len, resfh);
fh_unlock(current_fh);
- if (status)
- goto out;
- status = nfsd_check_obj_isreg(resfh);
}
if (status)
goto out;
+ status = nfsd_check_obj_isreg(resfh);
+ if (status)
+ goto out;
if (is_create_with_attrs(open) && open->op_acl != NULL)
do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
@@ -841,6 +841,7 @@
struct nfsd4_setattr *setattr)
{
__be32 status = nfs_ok;
+ int err;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
@@ -852,9 +853,9 @@
return status;
}
}
- status = fh_want_write(&cstate->current_fh);
- if (status)
- return status;
+ err = fh_want_write(&cstate->current_fh);
+ if (err)
+ return nfserrno(err);
status = nfs_ok;
status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 4767429..ed3f920 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -577,7 +577,7 @@
struct cld_net *cn = nn->cld_net;
if (mlen != sizeof(*cmsg)) {
- dprintk("%s: got %lu bytes, expected %lu\n", __func__, mlen,
+ dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
sizeof(*cmsg));
return -EINVAL;
}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1841f8b..7f71c69 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4211,16 +4211,14 @@
* vfs_test_lock. (Arguably perhaps test_lock should be done with an
* inode operation.)
*/
-static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
+static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
{
struct file *file;
- int err;
-
- err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
- if (err)
- return err;
- err = vfs_test_lock(file, lock);
- nfsd_close(file);
+ __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
+ if (!err) {
+ err = nfserrno(vfs_test_lock(file, lock));
+ nfsd_close(file);
+ }
return err;
}
@@ -4234,7 +4232,6 @@
struct inode *inode;
struct file_lock file_lock;
struct nfs4_lockowner *lo;
- int error;
__be32 status;
if (locks_in_grace())
@@ -4280,12 +4277,10 @@
nfs4_transform_lock_offset(&file_lock);
- status = nfs_ok;
- error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
- if (error) {
- status = nfserrno(error);
+ status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+ if (status)
goto out;
- }
+
if (file_lock.fl_type != F_UNLCK) {
status = nfserr_denied;
nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bcd8904..74c00bc 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1392,7 +1392,7 @@
for (i = 0; i < test_stateid->ts_num_ids; i++) {
stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
if (!stateid) {
- status = PTR_ERR(stateid);
+ status = nfserrno(-ENOMEM);
goto out;
}
@@ -3410,7 +3410,7 @@
*p++ = htonl(test_stateid->ts_num_ids);
list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
- *p++ = htonl(stateid->ts_id_status);
+ *p++ = stateid->ts_id_status;
}
ADJUST_ARGS();
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 296d671..5686661 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1458,7 +1458,7 @@
switch (createmode) {
case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode))
- err = nfserr_exist;
+ goto out;
else if (truncp) {
/* in nfsv4, we need to treat this case a little
* differently. we don't want to truncate the
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 3165aeb..31b9463 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1134,7 +1134,7 @@
}
el = path_leaf_el(path);
- rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1];
+ rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1];
ocfs2_adjust_rightmost_records(handle, et, path, rec);
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index cf78233..9f32d7c 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -1036,14 +1036,14 @@
tmp_el = left_path->p_node[subtree_root].el;
blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
- for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+ for (i = 0; i < le16_to_cpu(tmp_el->l_next_free_rec); i++) {
if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
*cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
break;
}
}
- BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+ BUG_ON(i == le16_to_cpu(tmp_el->l_next_free_rec));
out:
ocfs2_free_path(left_path);
@@ -1468,7 +1468,7 @@
trace_ocfs2_divide_leaf_refcount_block(
(unsigned long long)ref_leaf_bh->b_blocknr,
- le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used));
+ le16_to_cpu(rl->rl_count), le16_to_cpu(rl->rl_used));
/*
* XXX: Improvement later.
@@ -2411,7 +2411,7 @@
rb = (struct ocfs2_refcount_block *)
prev_bh->b_data;
- if (le64_to_cpu(rb->rf_records.rl_used) +
+ if (le16_to_cpu(rb->rf_records.rl_used) +
recs_add >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
@@ -2476,7 +2476,7 @@
if (prev_bh) {
rb = (struct ocfs2_refcount_block *)prev_bh->b_data;
- if (le64_to_cpu(rb->rf_records.rl_used) + recs_add >
+ if (le16_to_cpu(rb->rf_records.rl_used) + recs_add >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
@@ -3629,7 +3629,7 @@
* one will split a refcount rec, so totally we need
* clusters * 2 new refcount rec.
*/
- if (le64_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
+ if (le16_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index ba5d97e..f169da4 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -600,7 +600,7 @@
ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode,
cluster_ac->ac_bh,
le64_to_cpu(rec->e_blkno),
- le32_to_cpu(rec->e_leaf_clusters));
+ le16_to_cpu(rec->e_leaf_clusters));
if (ret)
mlog_errno(ret);
/* Try all the clusters to free */
@@ -1628,7 +1628,7 @@
{
unsigned int bpc = le16_to_cpu(cl->cl_bpc);
unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
- unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc;
+ unsigned int bitcount = le16_to_cpu(rec->e_leaf_clusters) * bpc;
if (res->sr_bit_offset < bitoff)
return 0;
diff --git a/fs/pipe.c b/fs/pipe.c
index 25feaa3..fec5e4a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -346,6 +346,16 @@
.get = generic_pipe_buf_get,
};
+static const struct pipe_buf_operations packet_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .confirm = generic_pipe_buf_confirm,
+ .release = anon_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
static ssize_t
pipe_read(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t pos)
@@ -407,6 +417,13 @@
ret += chars;
buf->offset += chars;
buf->len -= chars;
+
+ /* Was it a packet buffer? Clean up and exit */
+ if (buf->flags & PIPE_BUF_FLAG_PACKET) {
+ total_len = chars;
+ buf->len = 0;
+ }
+
if (!buf->len) {
buf->ops = NULL;
ops->release(pipe, buf);
@@ -459,6 +476,11 @@
return ret;
}
+static inline int is_packetized(struct file *file)
+{
+ return (file->f_flags & O_DIRECT) != 0;
+}
+
static ssize_t
pipe_write(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t ppos)
@@ -593,6 +615,11 @@
buf->ops = &anon_pipe_buf_ops;
buf->offset = 0;
buf->len = chars;
+ buf->flags = 0;
+ if (is_packetized(filp)) {
+ buf->ops = &packet_pipe_buf_ops;
+ buf->flags = PIPE_BUF_FLAG_PACKET;
+ }
pipe->nrbufs = ++bufs;
pipe->tmp_page = NULL;
@@ -1013,7 +1040,7 @@
goto err_dentry;
f->f_mapping = inode->i_mapping;
- f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
+ f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
f->f_version = 0;
return f;
@@ -1057,7 +1084,7 @@
int error;
int fdw, fdr;
- if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))
return -EINVAL;
fw = create_write_pipe(flags);
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 46a15d8..eed44bf 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -115,12 +115,13 @@
if (IS_ERR(sb))
return ERR_CAST(sb);
+ if (!proc_parse_options(options, ns)) {
+ deactivate_locked_super(sb);
+ return ERR_PTR(-EINVAL);
+ }
+
if (!sb->s_root) {
sb->s_flags = flags;
- if (!proc_parse_options(options, ns)) {
- deactivate_locked_super(sb);
- return ERR_PTR(-EINVAL);
- }
err = proc_fill_super(sb);
if (err) {
deactivate_locked_super(sb);
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index 6a0c62d..64c3b31 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -18,19 +18,39 @@
#ifndef arch_irq_stat
#define arch_irq_stat() 0
#endif
-#ifndef arch_idle_time
-#define arch_idle_time(cpu) 0
-#endif
+
+#ifdef arch_idle_time
+
+static cputime64_t get_idle_time(int cpu)
+{
+ cputime64_t idle;
+
+ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
+ if (cpu_online(cpu) && !nr_iowait_cpu(cpu))
+ idle += arch_idle_time(cpu);
+ return idle;
+}
+
+static cputime64_t get_iowait_time(int cpu)
+{
+ cputime64_t iowait;
+
+ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
+ if (cpu_online(cpu) && nr_iowait_cpu(cpu))
+ iowait += arch_idle_time(cpu);
+ return iowait;
+}
+
+#else
static u64 get_idle_time(int cpu)
{
u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
- if (idle_time == -1ULL) {
+ if (idle_time == -1ULL)
/* !NO_HZ so we can rely on cpustat.idle */
idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
- idle += arch_idle_time(cpu);
- } else
+ else
idle = usecs_to_cputime64(idle_time);
return idle;
@@ -49,6 +69,8 @@
return iowait;
}
+#endif
+
static int show_stat(struct seq_file *p, void *v)
{
int i, j;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2b9a760..2d60492 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -597,9 +597,6 @@
if (!page)
continue;
- if (PageReserved(page))
- continue;
-
/* Clear accessed and referenced bits. */
ptep_test_and_clear_young(vma, addr, pte);
ClearPageReferenced(page);
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 50952c9..1950788 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -52,12 +52,6 @@
char data[];
};
-static int pstore_file_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t pstore_file_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -67,7 +61,7 @@
}
static const struct file_operations pstore_file_operations = {
- .open = pstore_file_open,
+ .open = simple_open,
.read = pstore_file_read,
.llseek = default_llseek,
};
diff --git a/fs/splice.c b/fs/splice.c
index 5f883de..f847684 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -30,6 +30,7 @@
#include <linux/uio.h>
#include <linux/security.h>
#include <linux/gfp.h>
+#include <linux/socket.h>
/*
* Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -690,7 +691,9 @@
if (!likely(file->f_op && file->f_op->sendpage))
return -EINVAL;
- more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
+ more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0;
+ if (sd->len < sd->total_len)
+ more |= MSG_SENDPAGE_NOTLAST;
return file->f_op->sendpage(file, buf->page, buf->offset,
sd->len, &pos, more);
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 2a7a3f5..35a36d3 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -729,6 +729,9 @@
else
parent_sd = &sysfs_root;
+ if (!parent_sd)
+ return -ENOENT;
+
if (sysfs_ns_type(parent_sd))
ns = kobj->ktype->namespace(kobj);
type = sysfs_read_ns_type(kobj);
@@ -878,7 +881,6 @@
dup_name = sd->s_name;
sd->s_name = new_name;
- sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
}
/* Move to the appropriate place in the appropriate directories rbtree. */
@@ -886,6 +888,7 @@
sysfs_get(new_parent_sd);
sysfs_put(sd->s_parent);
sd->s_ns = new_ns;
+ sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name);
sd->s_parent = new_parent_sd;
sysfs_link_sibling(sd);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index dd1701c..2df555c 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -67,7 +67,11 @@
/* Updates may happen before the object has been instantiated */
if (unlikely(update && !kobj->sd))
return -EINVAL;
-
+ if (!grp->attrs) {
+ WARN(1, "sysfs: attrs not set by subsystem for group: %s/%s\n",
+ kobj->name, grp->name ? "" : grp->name);
+ return -EINVAL;
+ }
if (grp->name) {
error = sysfs_create_subdir(kobj, grp->name, &sd);
if (error)
diff --git a/fs/xattr.c b/fs/xattr.c
index d6dfd24..3c8c1cc 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -19,8 +19,9 @@
#include <linux/export.h>
#include <linux/fsnotify.h>
#include <linux/audit.h>
-#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <asm/uaccess.h>
/*
* Check permissions for extended attribute access. This is a bit complicated
@@ -320,6 +321,7 @@
{
int error;
void *kvalue = NULL;
+ void *vvalue = NULL; /* If non-NULL, we used vmalloc() */
char kname[XATTR_NAME_MAX + 1];
if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
@@ -334,13 +336,25 @@
if (size) {
if (size > XATTR_SIZE_MAX)
return -E2BIG;
- kvalue = memdup_user(value, size);
- if (IS_ERR(kvalue))
- return PTR_ERR(kvalue);
+ kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
+ if (!kvalue) {
+ vvalue = vmalloc(size);
+ if (!vvalue)
+ return -ENOMEM;
+ kvalue = vvalue;
+ }
+ if (copy_from_user(kvalue, value, size)) {
+ error = -EFAULT;
+ goto out;
+ }
}
error = vfs_setxattr(d, kname, kvalue, size, flags);
- kfree(kvalue);
+out:
+ if (vvalue)
+ vfree(vvalue);
+ else
+ kfree(kvalue);
return error;
}
@@ -492,13 +506,18 @@
{
ssize_t error;
char *klist = NULL;
+ char *vlist = NULL; /* If non-NULL, we used vmalloc() */
if (size) {
if (size > XATTR_LIST_MAX)
size = XATTR_LIST_MAX;
- klist = kmalloc(size, GFP_KERNEL);
- if (!klist)
- return -ENOMEM;
+ klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
+ if (!klist) {
+ vlist = vmalloc(size);
+ if (!vlist)
+ return -ENOMEM;
+ klist = vlist;
+ }
}
error = vfs_listxattr(d, klist, size);
@@ -510,7 +529,10 @@
than XATTR_LIST_MAX bytes. Not possible. */
error = -E2BIG;
}
- kfree(klist);
+ if (vlist)
+ vfree(vlist);
+ else
+ kfree(klist);
return error;
}
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index eba6604..e8bcc47 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -499,9 +499,10 @@
#define ACPI_STATE_D0 (u8) 0
#define ACPI_STATE_D1 (u8) 1
#define ACPI_STATE_D2 (u8) 2
-#define ACPI_STATE_D3 (u8) 3
-#define ACPI_STATE_D3_COLD (u8) 4
-#define ACPI_D_STATES_MAX ACPI_STATE_D3_COLD
+#define ACPI_STATE_D3_HOT (u8) 3
+#define ACPI_STATE_D3 (u8) 4
+#define ACPI_STATE_D3_COLD ACPI_STATE_D3
+#define ACPI_D_STATES_MAX ACPI_STATE_D3
#define ACPI_D_STATE_COUNT 5
#define ACPI_STATE_C0 (u8) 0
diff --git a/include/asm-generic/cmpxchg.h b/include/asm-generic/cmpxchg.h
index 8a36183..1488302 100644
--- a/include/asm-generic/cmpxchg.h
+++ b/include/asm-generic/cmpxchg.h
@@ -10,6 +10,7 @@
#error "Cannot use generic cmpxchg on SMP"
#endif
+#include <linux/types.h>
#include <linux/irqflags.h>
#ifndef xchg
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 0dd4e87..5e5e386 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -35,6 +35,14 @@
#define __ARCH_SI_BAND_T long
#endif
+#ifndef __ARCH_SI_CLOCK_T
+#define __ARCH_SI_CLOCK_T __kernel_clock_t
+#endif
+
+#ifndef __ARCH_SI_ATTRIBUTES
+#define __ARCH_SI_ATTRIBUTES
+#endif
+
#ifndef HAVE_ARCH_SIGINFO_T
typedef struct siginfo {
@@ -72,8 +80,8 @@
__kernel_pid_t _pid; /* which child */
__ARCH_SI_UID_T _uid; /* sender's uid */
int _status; /* exit code */
- __kernel_clock_t _utime;
- __kernel_clock_t _stime;
+ __ARCH_SI_CLOCK_T _utime;
+ __ARCH_SI_CLOCK_T _stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -91,7 +99,7 @@
int _fd;
} _sigpoll;
} _sifields;
-} siginfo_t;
+} __ARCH_SI_ATTRIBUTES siginfo_t;
#endif
diff --git a/include/asm-generic/statfs.h b/include/asm-generic/statfs.h
index 0fd28e0..c749af9 100644
--- a/include/asm-generic/statfs.h
+++ b/include/asm-generic/statfs.h
@@ -15,7 +15,7 @@
* with a 10' pole.
*/
#ifndef __statfs_word
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
#define __statfs_word long
#else
#define __statfs_word __u32
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
index d838c94..2eba340 100644
--- a/include/crypto/internal/aead.h
+++ b/include/crypto/internal/aead.h
@@ -31,6 +31,8 @@
crypto_set_spawn(&spawn->base, inst);
}
+struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, u32 mask);
+
int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
u32 type, u32 mask);
diff --git a/include/crypto/internal/skcipher.h b/include/crypto/internal/skcipher.h
index 3a748a6..06e8b32 100644
--- a/include/crypto/internal/skcipher.h
+++ b/include/crypto/internal/skcipher.h
@@ -34,6 +34,8 @@
int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
u32 type, u32 mask);
+struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, u32 mask);
+
static inline void crypto_drop_skcipher(struct crypto_skcipher_spawn *spawn)
{
crypto_drop_spawn(&spawn->base);
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 34a7b89..64ff02d 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -617,6 +617,17 @@
__u64 value;
};
+#define DRM_CLOEXEC O_CLOEXEC
+struct drm_prime_handle {
+ __u32 handle;
+
+ /** Flags.. only applicable for handle->fd */
+ __u32 flags;
+
+ /** Returned dmabuf file descriptor */
+ __s32 fd;
+};
+
#include "drm_mode.h"
#define DRM_IOCTL_BASE 'd'
@@ -673,7 +684,8 @@
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
-#define DRM_IOCTL_GEM_PRIME_OPEN DRM_IOWR(0x2e, struct drm_gem_open)
+#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
+#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 574bd1c..dd73104 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -91,6 +91,7 @@
#define DRM_UT_CORE 0x01
#define DRM_UT_DRIVER 0x02
#define DRM_UT_KMS 0x04
+#define DRM_UT_PRIME 0x08
/*
* Three debug levels are defined.
* drm_core, drm_driver, drm_kms
@@ -150,6 +151,7 @@
#define DRIVER_IRQ_VBL2 0x800
#define DRIVER_GEM 0x1000
#define DRIVER_MODESET 0x2000
+#define DRIVER_PRIME 0x4000
#define DRIVER_BUS_PCI 0x1
#define DRIVER_BUS_PLATFORM 0x2
@@ -215,6 +217,11 @@
drm_ut_debug_printk(DRM_UT_KMS, DRM_NAME, \
__func__, fmt, ##args); \
} while (0)
+#define DRM_DEBUG_PRIME(fmt, args...) \
+ do { \
+ drm_ut_debug_printk(DRM_UT_PRIME, DRM_NAME, \
+ __func__, fmt, ##args); \
+ } while (0)
#define DRM_LOG(fmt, args...) \
do { \
drm_ut_debug_printk(DRM_UT_CORE, NULL, \
@@ -238,6 +245,7 @@
#else
#define DRM_DEBUG_DRIVER(fmt, args...) do { } while (0)
#define DRM_DEBUG_KMS(fmt, args...) do { } while (0)
+#define DRM_DEBUG_PRIME(fmt, args...) do { } while (0)
#define DRM_DEBUG(fmt, arg...) do { } while (0)
#define DRM_LOG(fmt, arg...) do { } while (0)
#define DRM_LOG_KMS(fmt, args...) do { } while (0)
@@ -410,6 +418,12 @@
void (*destroy)(struct drm_pending_event *event);
};
+/* initial implementaton using a linked list - todo hashtab */
+struct drm_prime_file_private {
+ struct list_head head;
+ struct mutex lock;
+};
+
/** File private data */
struct drm_file {
int authenticated;
@@ -437,6 +451,8 @@
wait_queue_head_t event_wait;
struct list_head event_list;
int event_space;
+
+ struct drm_prime_file_private prime;
};
/** Wait queue */
@@ -652,6 +668,12 @@
uint32_t pending_write_domain;
void *driver_private;
+
+ /* dma buf exported from this GEM object */
+ struct dma_buf *export_dma_buf;
+
+ /* dma buf attachment backing this object */
+ struct dma_buf_attachment *import_attach;
};
#include "drm_crtc.h"
@@ -890,6 +912,20 @@
int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
+ /* prime: */
+ /* export handle -> fd (see drm_gem_prime_handle_to_fd() helper) */
+ int (*prime_handle_to_fd)(struct drm_device *dev, struct drm_file *file_priv,
+ uint32_t handle, uint32_t flags, int *prime_fd);
+ /* import fd -> handle (see drm_gem_prime_fd_to_handle() helper) */
+ int (*prime_fd_to_handle)(struct drm_device *dev, struct drm_file *file_priv,
+ int prime_fd, uint32_t *handle);
+ /* export GEM -> dmabuf */
+ struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
+ struct drm_gem_object *obj, int flags);
+ /* import dmabuf -> GEM */
+ struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
+ struct dma_buf *dma_buf);
+
/* vga arb irq handler */
void (*vgaarb_irq)(struct drm_device *dev, bool state);
@@ -1509,6 +1545,32 @@
extern int drm_clients_info(struct seq_file *m, void* data);
extern int drm_gem_name_info(struct seq_file *m, void *data);
+
+extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
+ struct drm_file *file_priv, uint32_t handle, uint32_t flags,
+ int *prime_fd);
+extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
+ struct drm_file *file_priv, int prime_fd, uint32_t *handle);
+
+extern int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+extern int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
+
+extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages);
+extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
+
+
+void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
+void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
+int drm_prime_add_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
+int drm_prime_lookup_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
+void drm_prime_remove_imported_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+
+int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
+int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,
+ struct drm_gem_object **obj);
+
#if DRM_DEBUG_CODE
extern int drm_vma_info(struct seq_file *m, void *data);
#endif
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
index 3963116..e478de4 100644
--- a/include/drm/exynos_drm.h
+++ b/include/drm/exynos_drm.h
@@ -85,7 +85,7 @@
struct drm_exynos_vidi_connection {
unsigned int connection;
unsigned int extensions;
- uint64_t *edid;
+ uint64_t edid;
};
struct drm_exynos_plane_set_zpos {
@@ -96,7 +96,8 @@
/* memory type definitions. */
enum e_drm_exynos_gem_mem_type {
/* Physically Non-Continuous memory. */
- EXYNOS_BO_NONCONTIG = 1 << 0
+ EXYNOS_BO_NONCONTIG = 1 << 0,
+ EXYNOS_BO_MASK = EXYNOS_BO_NONCONTIG
};
#define DRM_EXYNOS_GEM_CREATE 0x00
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index 0a0001b..923afb5 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -44,4 +44,8 @@
/* flag for GFDT type */
#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
+#ifdef CONFIG_INTEL_IOMMU
+extern int intel_iommu_gfx_mapped;
+#endif
+
#endif
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index d05df28..3c9b616 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -3,6 +3,7 @@
header-y += caif/
header-y += dvb/
header-y += hdlc/
+header-y += hsi/
header-y += isdn/
header-y += mmc/
header-y += nfsd/
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 7847e19..8d54f79 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -30,7 +30,6 @@
struct device dev;
struct resource res;
struct clk *pclk;
- struct regulator *vcore;
u64 dma_mask;
unsigned int periphid;
unsigned int irq[AMBA_NR_IRQS];
@@ -75,12 +74,6 @@
#define amba_pclk_disable(d) \
do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
-#define amba_vcore_enable(d) \
- (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
-
-#define amba_vcore_disable(d) \
- do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
-
/* Some drivers don't use the struct amba_device */
#define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
#define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
diff --git a/include/linux/amba/pl022.h b/include/linux/amba/pl022.h
index b8c5112..76dd1b1 100644
--- a/include/linux/amba/pl022.h
+++ b/include/linux/amba/pl022.h
@@ -25,6 +25,8 @@
#ifndef _SSP_PL022_H
#define _SSP_PL022_H
+#include <linux/types.h>
+
/**
* whether SSP is in loopback mode or not
*/
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 606cf33..2aa2466 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -426,14 +426,10 @@
(1 << QUEUE_FLAG_SAME_COMP) | \
(1 << QUEUE_FLAG_ADD_RANDOM))
-static inline int queue_is_locked(struct request_queue *q)
+static inline void queue_lockdep_assert_held(struct request_queue *q)
{
-#ifdef CONFIG_SMP
- spinlock_t *lock = q->queue_lock;
- return lock && spin_is_locked(lock);
-#else
- return 1;
-#endif
+ if (q->queue_lock)
+ lockdep_assert_held(q->queue_lock);
}
static inline void queue_flag_set_unlocked(unsigned int flag,
@@ -445,7 +441,7 @@
static inline int queue_flag_test_and_clear(unsigned int flag,
struct request_queue *q)
{
- WARN_ON_ONCE(!queue_is_locked(q));
+ queue_lockdep_assert_held(q);
if (test_bit(flag, &q->queue_flags)) {
__clear_bit(flag, &q->queue_flags);
@@ -458,7 +454,7 @@
static inline int queue_flag_test_and_set(unsigned int flag,
struct request_queue *q)
{
- WARN_ON_ONCE(!queue_is_locked(q));
+ queue_lockdep_assert_held(q);
if (!test_bit(flag, &q->queue_flags)) {
__set_bit(flag, &q->queue_flags);
@@ -470,7 +466,7 @@
static inline void queue_flag_set(unsigned int flag, struct request_queue *q)
{
- WARN_ON_ONCE(!queue_is_locked(q));
+ queue_lockdep_assert_held(q);
__set_bit(flag, &q->queue_flags);
}
@@ -487,7 +483,7 @@
static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
{
- WARN_ON_ONCE(!queue_is_locked(q));
+ queue_lockdep_assert_held(q);
__clear_bit(flag, &q->queue_flags);
}
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 1ffdb98..a2c819d 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -764,12 +764,6 @@
*
*/
#ifndef CONFIG_DISABLE_OBSOLETE_CPUMASK_FUNCTIONS
-/* These strip const, as traditionally they weren't const. */
-#define cpu_possible_map (*(cpumask_t *)cpu_possible_mask)
-#define cpu_online_map (*(cpumask_t *)cpu_online_mask)
-#define cpu_present_map (*(cpumask_t *)cpu_present_mask)
-#define cpu_active_map (*(cpumask_t *)cpu_active_mask)
-
#define cpumask_of_cpu(cpu) (*get_cpu_mask(cpu))
#define CPU_MASK_LAST_WORD BITMAP_LAST_WORD_MASK(NR_CPUS)
diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h
index 532fb58..4abf2ea 100644
--- a/include/linux/cryptouser.h
+++ b/include/linux/cryptouser.h
@@ -100,3 +100,6 @@
char type[CRYPTO_MAX_NAME];
unsigned int seedsize;
};
+
+#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
+ sizeof(struct crypto_report_blkcipher))
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index 71ad34e..547ab56 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -13,6 +13,8 @@
enum dma_attr {
DMA_ATTR_WRITE_BARRIER,
DMA_ATTR_WEAK_ORDERING,
+ DMA_ATTR_WRITE_COMBINE,
+ DMA_ATTR_NON_CONSISTENT,
DMA_ATTR_MAX,
};
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 5a736af..dfc099e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -9,10 +9,15 @@
#include <linux/scatterlist.h>
struct dma_map_ops {
- void* (*alloc_coherent)(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp);
- void (*free_coherent)(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
+ void* (*alloc)(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs);
+ void (*free)(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs);
+ int (*mmap)(struct device *, struct vm_area_struct *,
+ void *, dma_addr_t, size_t, struct dma_attrs *attrs);
+
dma_addr_t (*map_page)(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 676f967..f9a2e5e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -974,6 +974,7 @@
void dma_async_device_unregister(struct dma_device *device);
void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
+struct dma_chan *net_dma_find_channel(void);
#define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
/* --- Helper iov-locking functions --- */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 88ec806..ec45ccd 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -554,7 +554,18 @@
#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
+#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_APPEND_WRITE)
/*
* The type of search to perform when calling boottime->locate_handle
*/
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index e1d9e0e..f5647b5 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -896,8 +896,7 @@
*
* All operations are optional (i.e. the function pointer may be set
* to %NULL) and callers must take this into account. Callers must
- * hold the RTNL, except that for @get_drvinfo the caller may or may
- * not hold the RTNL.
+ * hold the RTNL lock.
*
* See the structures used by these operations for further documentation.
*
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 4db7b68..cdc9b71 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -2,6 +2,7 @@
#define _LINUX_FIREWIRE_H
#include <linux/completion.h>
+#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/kref.h>
@@ -64,8 +65,6 @@
#define CSR_MODEL 0x17
#define CSR_DIRECTORY_ID 0x20
-struct device;
-
struct fw_csr_iterator {
const u32 *p;
const u32 *end;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 135693e..8de6755 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1215,6 +1215,7 @@
extern int lease_modify(struct file_lock **, int);
extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
+extern void locks_delete_block(struct file_lock *waiter);
extern void lock_flocks(void);
extern void unlock_flocks(void);
#else /* !CONFIG_FILE_LOCKING */
@@ -1359,6 +1360,10 @@
return 1;
}
+static inline void locks_delete_block(struct file_lock *waiter)
+{
+}
+
static inline void lock_flocks(void)
{
}
@@ -2506,6 +2511,7 @@
extern int simple_setattr(struct dentry *, struct iattr *);
extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct dentry *, struct kstatfs *);
+extern int simple_open(struct inode *inode, struct file *file);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
extern int simple_rmdir(struct inode *, struct dentry *);
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 8ba2c94..8f2ab8f 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -593,7 +593,7 @@
__u64 off;
__u32 namelen;
__u32 type;
- char name[0];
+ char name[];
};
#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
diff --git a/include/linux/gpio-pxa.h b/include/linux/gpio-pxa.h
index 05071ee..d755b28 100644
--- a/include/linux/gpio-pxa.h
+++ b/include/linux/gpio-pxa.h
@@ -13,4 +13,8 @@
extern int pxa_irq_to_gpio(int irq);
+struct pxa_gpio_platform_data {
+ int (*gpio_set_wake)(unsigned int gpio, unsigned int on);
+};
+
#endif /* __GPIO_PXA_H */
diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild
new file mode 100644
index 0000000..271a770
--- /dev/null
+++ b/include/linux/hsi/Kbuild
@@ -0,0 +1 @@
+header-y += hsi_char.h
diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h
new file mode 100644
index 0000000..56fae86
--- /dev/null
+++ b/include/linux/hsi/hsi.h
@@ -0,0 +1,413 @@
+/*
+ * HSI core header file.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Carlos Chinea <carlos.chinea@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef __LINUX_HSI_H__
+#define __LINUX_HSI_H__
+
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/scatterlist.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+
+/* HSI message ttype */
+#define HSI_MSG_READ 0
+#define HSI_MSG_WRITE 1
+
+/* HSI configuration values */
+enum {
+ HSI_MODE_STREAM = 1,
+ HSI_MODE_FRAME,
+};
+
+enum {
+ HSI_FLOW_SYNC, /* Synchronized flow */
+ HSI_FLOW_PIPE, /* Pipelined flow */
+};
+
+enum {
+ HSI_ARB_RR, /* Round-robin arbitration */
+ HSI_ARB_PRIO, /* Channel priority arbitration */
+};
+
+#define HSI_MAX_CHANNELS 16
+
+/* HSI message status codes */
+enum {
+ HSI_STATUS_COMPLETED, /* Message transfer is completed */
+ HSI_STATUS_PENDING, /* Message pending to be read/write (POLL) */
+ HSI_STATUS_PROCEEDING, /* Message transfer is ongoing */
+ HSI_STATUS_QUEUED, /* Message waiting to be served */
+ HSI_STATUS_ERROR, /* Error when message transfer was ongoing */
+};
+
+/* HSI port event codes */
+enum {
+ HSI_EVENT_START_RX,
+ HSI_EVENT_STOP_RX,
+};
+
+/**
+ * struct hsi_config - Configuration for RX/TX HSI modules
+ * @mode: Bit transmission mode (STREAM or FRAME)
+ * @channels: Number of channels to use [1..16]
+ * @speed: Max bit transmission speed (Kbit/s)
+ * @flow: RX flow type (SYNCHRONIZED or PIPELINE)
+ * @arb_mode: Arbitration mode for TX frame (Round robin, priority)
+ */
+struct hsi_config {
+ unsigned int mode;
+ unsigned int channels;
+ unsigned int speed;
+ union {
+ unsigned int flow; /* RX only */
+ unsigned int arb_mode; /* TX only */
+ };
+};
+
+/**
+ * struct hsi_board_info - HSI client board info
+ * @name: Name for the HSI device
+ * @hsi_id: HSI controller id where the client sits
+ * @port: Port number in the controller where the client sits
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @platform_data: Platform related data
+ * @archdata: Architecture-dependent device data
+ */
+struct hsi_board_info {
+ const char *name;
+ unsigned int hsi_id;
+ unsigned int port;
+ struct hsi_config tx_cfg;
+ struct hsi_config rx_cfg;
+ void *platform_data;
+ struct dev_archdata *archdata;
+};
+
+#ifdef CONFIG_HSI_BOARDINFO
+extern int hsi_register_board_info(struct hsi_board_info const *info,
+ unsigned int len);
+#else
+static inline int hsi_register_board_info(struct hsi_board_info const *info,
+ unsigned int len)
+{
+ return 0;
+}
+#endif /* CONFIG_HSI_BOARDINFO */
+
+/**
+ * struct hsi_client - HSI client attached to an HSI port
+ * @device: Driver model representation of the device
+ * @tx_cfg: HSI TX configuration
+ * @rx_cfg: HSI RX configuration
+ * @e_handler: Callback for handling port events (RX Wake High/Low)
+ * @pclaimed: Keeps tracks if the clients claimed its associated HSI port
+ * @nb: Notifier block for port events
+ */
+struct hsi_client {
+ struct device device;
+ struct hsi_config tx_cfg;
+ struct hsi_config rx_cfg;
+ /* private: */
+ void (*ehandler)(struct hsi_client *, unsigned long);
+ unsigned int pclaimed:1;
+ struct notifier_block nb;
+};
+
+#define to_hsi_client(dev) container_of(dev, struct hsi_client, device)
+
+static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data)
+{
+ dev_set_drvdata(&cl->device, data);
+}
+
+static inline void *hsi_client_drvdata(struct hsi_client *cl)
+{
+ return dev_get_drvdata(&cl->device);
+}
+
+int hsi_register_port_event(struct hsi_client *cl,
+ void (*handler)(struct hsi_client *, unsigned long));
+int hsi_unregister_port_event(struct hsi_client *cl);
+
+/**
+ * struct hsi_client_driver - Driver associated to an HSI client
+ * @driver: Driver model representation of the driver
+ */
+struct hsi_client_driver {
+ struct device_driver driver;
+};
+
+#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\
+ driver)
+
+int hsi_register_client_driver(struct hsi_client_driver *drv);
+
+static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+
+/**
+ * struct hsi_msg - HSI message descriptor
+ * @link: Free to use by the current descriptor owner
+ * @cl: HSI device client that issues the transfer
+ * @sgt: Head of the scatterlist array
+ * @context: Client context data associated to the transfer
+ * @complete: Transfer completion callback
+ * @destructor: Destructor to free resources when flushing
+ * @status: Status of the transfer when completed
+ * @actual_len: Actual length of data transfered on completion
+ * @channel: Channel were to TX/RX the message
+ * @ttype: Transfer type (TX if set, RX otherwise)
+ * @break_frame: if true HSI will send/receive a break frame. Data buffers are
+ * ignored in the request.
+ */
+struct hsi_msg {
+ struct list_head link;
+ struct hsi_client *cl;
+ struct sg_table sgt;
+ void *context;
+
+ void (*complete)(struct hsi_msg *msg);
+ void (*destructor)(struct hsi_msg *msg);
+
+ int status;
+ unsigned int actual_len;
+ unsigned int channel;
+ unsigned int ttype:1;
+ unsigned int break_frame:1;
+};
+
+struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags);
+void hsi_free_msg(struct hsi_msg *msg);
+
+/**
+ * struct hsi_port - HSI port device
+ * @device: Driver model representation of the device
+ * @tx_cfg: Current TX path configuration
+ * @rx_cfg: Current RX path configuration
+ * @num: Port number
+ * @shared: Set when port can be shared by different clients
+ * @claimed: Reference count of clients which claimed the port
+ * @lock: Serialize port claim
+ * @async: Asynchronous transfer callback
+ * @setup: Callback to set the HSI client configuration
+ * @flush: Callback to clean the HW state and destroy all pending transfers
+ * @start_tx: Callback to inform that a client wants to TX data
+ * @stop_tx: Callback to inform that a client no longer wishes to TX data
+ * @release: Callback to inform that a client no longer uses the port
+ * @n_head: Notifier chain for signaling port events to the clients.
+ */
+struct hsi_port {
+ struct device device;
+ struct hsi_config tx_cfg;
+ struct hsi_config rx_cfg;
+ unsigned int num;
+ unsigned int shared:1;
+ int claimed;
+ struct mutex lock;
+ int (*async)(struct hsi_msg *msg);
+ int (*setup)(struct hsi_client *cl);
+ int (*flush)(struct hsi_client *cl);
+ int (*start_tx)(struct hsi_client *cl);
+ int (*stop_tx)(struct hsi_client *cl);
+ int (*release)(struct hsi_client *cl);
+ /* private */
+ struct atomic_notifier_head n_head;
+};
+
+#define to_hsi_port(dev) container_of(dev, struct hsi_port, device)
+#define hsi_get_port(cl) to_hsi_port((cl)->device.parent)
+
+int hsi_event(struct hsi_port *port, unsigned long event);
+int hsi_claim_port(struct hsi_client *cl, unsigned int share);
+void hsi_release_port(struct hsi_client *cl);
+
+static inline int hsi_port_claimed(struct hsi_client *cl)
+{
+ return cl->pclaimed;
+}
+
+static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data)
+{
+ dev_set_drvdata(&port->device, data);
+}
+
+static inline void *hsi_port_drvdata(struct hsi_port *port)
+{
+ return dev_get_drvdata(&port->device);
+}
+
+/**
+ * struct hsi_controller - HSI controller device
+ * @device: Driver model representation of the device
+ * @owner: Pointer to the module owning the controller
+ * @id: HSI controller ID
+ * @num_ports: Number of ports in the HSI controller
+ * @port: Array of HSI ports
+ */
+struct hsi_controller {
+ struct device device;
+ struct module *owner;
+ unsigned int id;
+ unsigned int num_ports;
+ struct hsi_port **port;
+};
+
+#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device)
+
+struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags);
+void hsi_put_controller(struct hsi_controller *hsi);
+int hsi_register_controller(struct hsi_controller *hsi);
+void hsi_unregister_controller(struct hsi_controller *hsi);
+
+static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi,
+ void *data)
+{
+ dev_set_drvdata(&hsi->device, data);
+}
+
+static inline void *hsi_controller_drvdata(struct hsi_controller *hsi)
+{
+ return dev_get_drvdata(&hsi->device);
+}
+
+static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi,
+ unsigned int num)
+{
+ return (num < hsi->num_ports) ? hsi->port[num] : NULL;
+}
+
+/*
+ * API for HSI clients
+ */
+int hsi_async(struct hsi_client *cl, struct hsi_msg *msg);
+
+/**
+ * hsi_id - Get HSI controller ID associated to a client
+ * @cl: Pointer to a HSI client
+ *
+ * Return the controller id where the client is attached to
+ */
+static inline unsigned int hsi_id(struct hsi_client *cl)
+{
+ return to_hsi_controller(cl->device.parent->parent)->id;
+}
+
+/**
+ * hsi_port_id - Gets the port number a client is attached to
+ * @cl: Pointer to HSI client
+ *
+ * Return the port number associated to the client
+ */
+static inline unsigned int hsi_port_id(struct hsi_client *cl)
+{
+ return to_hsi_port(cl->device.parent)->num;
+}
+
+/**
+ * hsi_setup - Configure the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * When sharing ports, clients should either relay on a single
+ * client setup or have the same setup for all of them.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_setup(struct hsi_client *cl)
+{
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+ return hsi_get_port(cl)->setup(cl);
+}
+
+/**
+ * hsi_flush - Flush all pending transactions on the client's port
+ * @cl: Pointer to the HSI client
+ *
+ * This function will destroy all pending hsi_msg in the port and reset
+ * the HW port so it is ready to receive and transmit from a clean state.
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_flush(struct hsi_client *cl)
+{
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+ return hsi_get_port(cl)->flush(cl);
+}
+
+/**
+ * hsi_async_read - Submit a read transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg)
+{
+ msg->ttype = HSI_MSG_READ;
+ return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_async_write - Submit a write transfer
+ * @cl: Pointer to the HSI client
+ * @msg: HSI message descriptor of the transfer
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg)
+{
+ msg->ttype = HSI_MSG_WRITE;
+ return hsi_async(cl, msg);
+}
+
+/**
+ * hsi_start_tx - Signal the port that the client wants to start a TX
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_start_tx(struct hsi_client *cl)
+{
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+ return hsi_get_port(cl)->start_tx(cl);
+}
+
+/**
+ * hsi_stop_tx - Signal the port that the client no longer wants to transmit
+ * @cl: Pointer to the HSI client
+ *
+ * Return -errno on failure, 0 on success
+ */
+static inline int hsi_stop_tx(struct hsi_client *cl)
+{
+ if (!hsi_port_claimed(cl))
+ return -EACCES;
+ return hsi_get_port(cl)->stop_tx(cl);
+}
+#endif /* __LINUX_HSI_H__ */
diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h
new file mode 100644
index 0000000..76160b4
--- /dev/null
+++ b/include/linux/hsi/hsi_char.h
@@ -0,0 +1,63 @@
+/*
+ * Part of the HSI character device driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos at nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+#ifndef __HSI_CHAR_H
+#define __HSI_CHAR_H
+
+#define HSI_CHAR_MAGIC 'k'
+#define HSC_IOW(num, dtype) _IOW(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOR(num, dtype) _IOR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOWR(num, dtype) _IOWR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IO(num) _IO(HSI_CHAR_MAGIC, num)
+
+#define HSC_RESET HSC_IO(16)
+#define HSC_SET_PM HSC_IO(17)
+#define HSC_SEND_BREAK HSC_IO(18)
+#define HSC_SET_RX HSC_IOW(19, struct hsc_rx_config)
+#define HSC_GET_RX HSC_IOW(20, struct hsc_rx_config)
+#define HSC_SET_TX HSC_IOW(21, struct hsc_tx_config)
+#define HSC_GET_TX HSC_IOW(22, struct hsc_tx_config)
+
+#define HSC_PM_DISABLE 0
+#define HSC_PM_ENABLE 1
+
+#define HSC_MODE_STREAM 1
+#define HSC_MODE_FRAME 2
+#define HSC_FLOW_SYNC 0
+#define HSC_ARB_RR 0
+#define HSC_ARB_PRIO 1
+
+struct hsc_rx_config {
+ uint32_t mode;
+ uint32_t flow;
+ uint32_t channels;
+};
+
+struct hsc_tx_config {
+ uint32_t mode;
+ uint32_t channels;
+ uint32_t speed;
+ uint32_t arb_mode;
+};
+
+#endif /* __HSI_CHAR_H */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 2463b61..1f90de0 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -666,23 +666,11 @@
unsigned int check_defaults:1;
unsigned int reset_registers:1;
unsigned int hs_extmute:1;
- u16 hs_left_step;
- u16 hs_right_step;
- u16 hf_left_step;
- u16 hf_right_step;
void (*set_hs_extmute)(int mute);
};
struct twl4030_vibra_data {
unsigned int coexist;
-
- /* twl6040 */
- unsigned int vibldrv_res; /* left driver resistance */
- unsigned int vibrdrv_res; /* right driver resistance */
- unsigned int viblmotor_res; /* left motor resistance */
- unsigned int vibrmotor_res; /* right motor resistance */
- int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */
- int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */
};
struct twl4030_audio_data {
diff --git a/include/linux/if_eql.h b/include/linux/if_eql.h
index 79c4f26..18a5d02 100644
--- a/include/linux/if_eql.h
+++ b/include/linux/if_eql.h
@@ -22,7 +22,7 @@
#define EQL_DEFAULT_SLAVE_PRIORITY 28800
#define EQL_DEFAULT_MAX_SLAVES 4
#define EQL_DEFAULT_MTU 576
-#define EQL_DEFAULT_RESCHED_IVAL 100
+#define EQL_DEFAULT_RESCHED_IVAL HZ
#define EQL_ENSLAVE (SIOCDEVPRIVATE)
#define EQL_EMANCIPATE (SIOCDEVPRIVATE + 1)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index bff29c5..b27cfcf 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -49,6 +49,12 @@
* IRQ_TYPE_LEVEL_LOW - low level triggered
* IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits
* IRQ_TYPE_SENSE_MASK - Mask for all the above bits
+ * IRQ_TYPE_DEFAULT - For use by some PICs to ask irq_set_type
+ * to setup the HW to a sane default (used
+ * by irqdomain map() callbacks to synchronize
+ * the HW state and SW flags for a newly
+ * allocated descriptor).
+ *
* IRQ_TYPE_PROBE - Special flag for probing in progress
*
* Bits which can be modified via irq_set/clear/modify_status_flags()
@@ -77,6 +83,7 @@
IRQ_TYPE_LEVEL_LOW = 0x00000008,
IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH),
IRQ_TYPE_SENSE_MASK = 0x0000000f,
+ IRQ_TYPE_DEFAULT = IRQ_TYPE_SENSE_MASK,
IRQ_TYPE_PROBE = 0x00000010,
@@ -263,6 +270,11 @@
d->state_use_accessors &= ~IRQD_IRQ_INPROGRESS;
}
+static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d)
+{
+ return d->hwirq;
+}
+
/**
* struct irq_chip - hardware interrupt chip descriptor
*
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index ead4a42..c65740d 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -42,12 +42,6 @@
/* Number of irqs reserved for a legacy isa controller */
#define NUM_ISA_INTERRUPTS 16
-/* This type is the placeholder for a hardware interrupt number. It has to
- * be big enough to enclose whatever representation is used by a given
- * platform.
- */
-typedef unsigned long irq_hw_number_t;
-
/**
* struct irq_domain_ops - Methods for irq_domain objects
* @match: Match an interrupt controller device node to a host, returns
@@ -104,6 +98,9 @@
unsigned int size;
unsigned int *revmap;
} linear;
+ struct {
+ unsigned int max_irq;
+ } nomap;
struct radix_tree_root tree;
} revmap_data;
const struct irq_domain_ops *ops;
@@ -126,6 +123,7 @@
const struct irq_domain_ops *ops,
void *host_data);
struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+ unsigned int max_irq,
const struct irq_domain_ops *ops,
void *host_data);
struct irq_domain *irq_domain_add_tree(struct device_node *of_node,
@@ -134,7 +132,6 @@
extern struct irq_domain *irq_find_host(struct device_node *node);
extern void irq_set_default_host(struct irq_domain *host);
-extern void irq_set_virq_count(unsigned int count);
static inline struct irq_domain *irq_domain_add_legacy_isa(
struct device_node *of_node,
@@ -146,7 +143,6 @@
}
extern struct irq_domain *irq_find_host(struct device_node *node);
extern void irq_set_default_host(struct irq_domain *host);
-extern void irq_set_virq_count(unsigned int count);
extern unsigned int irq_create_mapping(struct irq_domain *host,
diff --git a/include/linux/kconfig.h b/include/linux/kconfig.h
index 067eda0..be342b9 100644
--- a/include/linux/kconfig.h
+++ b/include/linux/kconfig.h
@@ -4,29 +4,43 @@
#include <generated/autoconf.h>
/*
- * Helper macros to use CONFIG_ options in C expressions. Note that
+ * Helper macros to use CONFIG_ options in C/CPP expressions. Note that
* these only work with boolean and tristate options.
*/
/*
+ * Getting something that works in C and CPP for an arg that may or may
+ * not be defined is tricky. Here, if we have "#define CONFIG_BOOGER 1"
+ * we match on the placeholder define, insert the "0," for arg1 and generate
+ * the triplet (0, 1, 0). Then the last step cherry picks the 2nd arg (a one).
+ * When CONFIG_BOOGER is not defined, we generate a (... 1, 0) pair, and when
+ * the last step cherry picks the 2nd arg, we get a zero.
+ */
+#define __ARG_PLACEHOLDER_1 0,
+#define config_enabled(cfg) _config_enabled(cfg)
+#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
+#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
+#define ___config_enabled(__ignored, val, ...) val
+
+/*
* IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm',
* 0 otherwise.
*
*/
#define IS_ENABLED(option) \
- (__enabled_ ## option || __enabled_ ## option ## _MODULE)
+ (config_enabled(option) || config_enabled(option##_MODULE))
/*
* IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0
* otherwise. For boolean options, this is equivalent to
* IS_ENABLED(CONFIG_FOO).
*/
-#define IS_BUILTIN(option) __enabled_ ## option
+#define IS_BUILTIN(option) config_enabled(option)
/*
* IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0
* otherwise.
*/
-#define IS_MODULE(option) __enabled_ ## option ## _MODULE
+#define IS_MODULE(option) config_enabled(option##_MODULE)
#endif /* __LINUX_KCONFIG_H */
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index fa39183..c4d2fc1 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -63,7 +63,8 @@
BP_HARDWARE_BREAKPOINT,
BP_WRITE_WATCHPOINT,
BP_READ_WATCHPOINT,
- BP_ACCESS_WATCHPOINT
+ BP_ACCESS_WATCHPOINT,
+ BP_POKE_BREAKPOINT,
};
enum kgdb_bpstate {
@@ -207,8 +208,8 @@
/* Optional functions. */
extern int kgdb_validate_break_address(unsigned long addr);
-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
+extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
/**
* kgdb_arch_late - Perform any architecture specific initalization.
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 9efeae6..dd99c329 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -110,12 +110,29 @@
extern struct ctl_table usermodehelper_table[];
+enum umh_disable_depth {
+ UMH_ENABLED = 0,
+ UMH_FREEZING,
+ UMH_DISABLED,
+};
+
extern void usermodehelper_init(void);
-extern int usermodehelper_disable(void);
-extern void usermodehelper_enable(void);
-extern bool usermodehelper_is_disabled(void);
-extern void read_lock_usermodehelper(void);
-extern void read_unlock_usermodehelper(void);
+extern int __usermodehelper_disable(enum umh_disable_depth depth);
+extern void __usermodehelper_set_disable_depth(enum umh_disable_depth depth);
+
+static inline int usermodehelper_disable(void)
+{
+ return __usermodehelper_disable(UMH_DISABLED);
+}
+
+static inline void usermodehelper_enable(void)
+{
+ __usermodehelper_set_disable_depth(UMH_ENABLED);
+}
+
+extern int usermodehelper_read_trylock(void);
+extern long usermodehelper_read_lock_wait(long timeout);
+extern void usermodehelper_read_unlock(void);
#endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 665a260..72cbf08 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -596,6 +596,7 @@
#ifdef CONFIG_IOMMU_API
int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
int kvm_iommu_map_guest(struct kvm *kvm);
int kvm_iommu_unmap_guest(struct kvm *kvm);
int kvm_assign_device(struct kvm *kvm,
@@ -609,6 +610,11 @@
return 0;
}
+static inline void kvm_iommu_unmap_pages(struct kvm *kvm,
+ struct kvm_memory_slot *slot)
+{
+}
+
static inline int kvm_iommu_map_guest(struct kvm *kvm)
{
return -ENODEV;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 42378d6..e926df7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -996,7 +996,8 @@
extern void ata_sas_port_destroy(struct ata_port *);
extern struct ata_port *ata_sas_port_alloc(struct ata_host *,
struct ata_port_info *, struct Scsi_Host *);
-extern int ata_sas_async_port_init(struct ata_port *);
+extern void ata_sas_async_probe(struct ata_port *ap);
+extern int ata_sas_sync_probe(struct ata_port *ap);
extern int ata_sas_port_init(struct ata_port *);
extern int ata_sas_port_start(struct ata_port *ap);
extern void ata_sas_port_stop(struct ata_port *ap);
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index eab507f..fad48aa 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -22,6 +22,23 @@
#include <linux/key.h>
#include <linux/skbuff.h>
+struct lsm_network_audit {
+ int netif;
+ struct sock *sk;
+ u16 family;
+ __be16 dport;
+ __be16 sport;
+ union {
+ struct {
+ __be32 daddr;
+ __be32 saddr;
+ } v4;
+ struct {
+ struct in6_addr daddr;
+ struct in6_addr saddr;
+ } v6;
+ } fam;
+};
/* Auxiliary data to use in generating the audit record. */
struct common_audit_data {
@@ -41,23 +58,7 @@
struct path path;
struct dentry *dentry;
struct inode *inode;
- struct {
- int netif;
- struct sock *sk;
- u16 family;
- __be16 dport;
- __be16 sport;
- union {
- struct {
- __be32 daddr;
- __be32 saddr;
- } v4;
- struct {
- struct in6_addr daddr;
- struct in6_addr saddr;
- } v6;
- } fam;
- } net;
+ struct lsm_network_audit *net;
int cap;
int ipc_id;
struct task_struct *tsk;
@@ -72,64 +73,15 @@
/* this union contains LSM specific data */
union {
#ifdef CONFIG_SECURITY_SMACK
- /* SMACK data */
- struct smack_audit_data {
- const char *function;
- char *subject;
- char *object;
- char *request;
- int result;
- } smack_audit_data;
+ struct smack_audit_data *smack_audit_data;
#endif
#ifdef CONFIG_SECURITY_SELINUX
- /* SELinux data */
- struct {
- u32 ssid;
- u32 tsid;
- u16 tclass;
- u32 requested;
- u32 audited;
- u32 denied;
- /*
- * auditdeny is a bit tricky and unintuitive. See the
- * comments in avc.c for it's meaning and usage.
- */
- u32 auditdeny;
- struct av_decision *avd;
- int result;
- } selinux_audit_data;
+ struct selinux_audit_data *selinux_audit_data;
#endif
#ifdef CONFIG_SECURITY_APPARMOR
- struct {
- int error;
- int op;
- int type;
- void *profile;
- const char *name;
- const char *info;
- union {
- void *target;
- struct {
- long pos;
- void *target;
- } iface;
- struct {
- int rlim;
- unsigned long max;
- } rlim;
- struct {
- const char *target;
- u32 request;
- u32 denied;
- uid_t ouid;
- } fs;
- };
- } apparmor_audit_data;
+ struct apparmor_audit_data *apparmor_audit_data;
#endif
- };
- /* these callback will be implemented by a specific LSM */
- void (*lsm_pre_audit)(struct audit_buffer *, void *);
- void (*lsm_post_audit)(struct audit_buffer *, void *);
+ }; /* per LSM data pointer union */
};
#define v4info fam.v4
@@ -146,6 +98,8 @@
{ memset((_d), 0, sizeof(struct common_audit_data)); \
(_d)->type = LSM_AUDIT_DATA_##_t; }
-void common_lsm_audit(struct common_audit_data *a);
+void common_lsm_audit(struct common_audit_data *a,
+ void (*pre_audit)(struct audit_buffer *, void *),
+ void (*post_audit)(struct audit_buffer *, void *));
#endif
diff --git a/include/linux/mfd/db5500-prcmu.h b/include/linux/mfd/db5500-prcmu.h
index 9890687..5a049df 100644
--- a/include/linux/mfd/db5500-prcmu.h
+++ b/include/linux/mfd/db5500-prcmu.h
@@ -8,70 +8,6 @@
#ifndef __MFD_DB5500_PRCMU_H
#define __MFD_DB5500_PRCMU_H
-#ifdef CONFIG_MFD_DB5500_PRCMU
-
-void db5500_prcmu_early_init(void);
-int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state);
-int db5500_prcmu_set_display_clocks(void);
-int db5500_prcmu_disable_dsipll(void);
-int db5500_prcmu_enable_dsipll(void);
-int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
-void db5500_prcmu_enable_wakeups(u32 wakeups);
-int db5500_prcmu_request_clock(u8 clock, bool enable);
-void db5500_prcmu_config_abb_event_readout(u32 abb_events);
-void db5500_prcmu_get_abb_event_buffer(void __iomem **buf);
-int prcmu_resetout(u8 resoutn, u8 state);
-int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
- bool keep_ap_pll);
-int db5500_prcmu_config_esram0_deep_sleep(u8 state);
-void db5500_prcmu_system_reset(u16 reset_code);
-u16 db5500_prcmu_get_reset_code(void);
-bool db5500_prcmu_is_ac_wake_requested(void);
-int db5500_prcmu_set_arm_opp(u8 opp);
-int db5500_prcmu_get_arm_opp(void);
-
-#else /* !CONFIG_UX500_SOC_DB5500 */
-
-static inline void db5500_prcmu_early_init(void) {}
-
-static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
- return -ENOSYS;
-}
-
-static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_set_display_clocks(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_disable_dsipll(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_enable_dsipll(void)
-{
- return 0;
-}
-
-static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
-{
- return 0;
-}
-
-static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
-
static inline int prcmu_resetout(u8 resoutn, u8 state)
{
return 0;
@@ -82,8 +18,10 @@
return 0;
}
-static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
-static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
+static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
+{
+ return 0;
+}
static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
bool keep_ap_pll)
@@ -91,7 +29,10 @@
return 0;
}
-static inline void db5500_prcmu_system_reset(u16 reset_code) {}
+static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
+{
+ return 0;
+}
static inline u16 db5500_prcmu_get_reset_code(void)
{
@@ -113,6 +54,51 @@
return 0;
}
+static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
+
+static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
+
+static inline void db5500_prcmu_system_reset(u16 reset_code) {}
+
+static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
+
+#ifdef CONFIG_MFD_DB5500_PRCMU
+
+void db5500_prcmu_early_init(void);
+int db5500_prcmu_set_display_clocks(void);
+int db5500_prcmu_disable_dsipll(void);
+int db5500_prcmu_enable_dsipll(void);
+int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+#else /* !CONFIG_UX500_SOC_DB5500 */
+
+static inline void db5500_prcmu_early_init(void) {}
+
+static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+ return -ENOSYS;
+}
+
+static inline int db5500_prcmu_set_display_clocks(void)
+{
+ return 0;
+}
+
+static inline int db5500_prcmu_disable_dsipll(void)
+{
+ return 0;
+}
+
+static inline int db5500_prcmu_enable_dsipll(void)
+{
+ return 0;
+}
#endif /* CONFIG_MFD_DB5500_PRCMU */
diff --git a/include/linux/mfd/rc5t583.h b/include/linux/mfd/rc5t583.h
index a2c6160..0b64b19 100644
--- a/include/linux/mfd/rc5t583.h
+++ b/include/linux/mfd/rc5t583.h
@@ -26,6 +26,7 @@
#include <linux/mutex.h>
#include <linux/types.h>
+#include <linux/regmap.h>
#define RC5T583_MAX_REGS 0xF8
@@ -279,14 +280,44 @@
bool enable_shutdown;
};
-int rc5t583_write(struct device *dev, u8 reg, uint8_t val);
-int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val);
-int rc5t583_set_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask);
-int rc5t583_clear_bits(struct device *dev, unsigned int reg,
- unsigned int bit_mask);
-int rc5t583_update(struct device *dev, unsigned int reg,
- unsigned int val, unsigned int mask);
+static inline int rc5t583_write(struct device *dev, uint8_t reg, uint8_t val)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_write(rc5t583->regmap, reg, val);
+}
+
+static inline int rc5t583_read(struct device *dev, uint8_t reg, uint8_t *val)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ unsigned int ival;
+ int ret;
+ ret = regmap_read(rc5t583->regmap, reg, &ival);
+ if (!ret)
+ *val = (uint8_t)ival;
+ return ret;
+}
+
+static inline int rc5t583_set_bits(struct device *dev, unsigned int reg,
+ unsigned int bit_mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, bit_mask, bit_mask);
+}
+
+static inline int rc5t583_clear_bits(struct device *dev, unsigned int reg,
+ unsigned int bit_mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, bit_mask, 0);
+}
+
+static inline int rc5t583_update(struct device *dev, unsigned int reg,
+ unsigned int val, unsigned int mask)
+{
+ struct rc5t583 *rc5t583 = dev_get_drvdata(dev);
+ return regmap_update_bits(rc5t583->regmap, reg, mask, val);
+}
+
int rc5t583_ext_power_req_config(struct device *dev, int deepsleep_id,
int ext_pwr_req, int deepsleep_slot_nr);
int rc5t583_irq_init(struct rc5t583 *rc5t583, int irq, int irq_base);
diff --git a/include/linux/mfd/twl6040.h b/include/linux/mfd/twl6040.h
index 9bc9ac6..b15b5f0 100644
--- a/include/linux/mfd/twl6040.h
+++ b/include/linux/mfd/twl6040.h
@@ -174,8 +174,35 @@
#define TWL6040_SYSCLK_SEL_LPPLL 0
#define TWL6040_SYSCLK_SEL_HPPLL 1
+struct twl6040_codec_data {
+ u16 hs_left_step;
+ u16 hs_right_step;
+ u16 hf_left_step;
+ u16 hf_right_step;
+};
+
+struct twl6040_vibra_data {
+ unsigned int vibldrv_res; /* left driver resistance */
+ unsigned int vibrdrv_res; /* right driver resistance */
+ unsigned int viblmotor_res; /* left motor resistance */
+ unsigned int vibrmotor_res; /* right motor resistance */
+ int vddvibl_uV; /* VDDVIBL volt, set 0 for fixed reg */
+ int vddvibr_uV; /* VDDVIBR volt, set 0 for fixed reg */
+};
+
+struct twl6040_platform_data {
+ int audpwron_gpio; /* audio power-on gpio */
+ unsigned int irq_base;
+
+ struct twl6040_codec_data *codec;
+ struct twl6040_vibra_data *vibra;
+};
+
+struct regmap;
+
struct twl6040 {
struct device *dev;
+ struct regmap *regmap;
struct mutex mutex;
struct mutex io_mutex;
struct mutex irq_mutex;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d8738a4..74aa71b 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1393,29 +1393,20 @@
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
- unsigned long len, unsigned long prot,
- unsigned long flag, unsigned long pgoff);
extern unsigned long mmap_region(struct file *file, unsigned long addr,
unsigned long len, unsigned long flags,
vm_flags_t vm_flags, unsigned long pgoff);
-
-static inline unsigned long do_mmap(struct file *file, unsigned long addr,
- unsigned long len, unsigned long prot,
- unsigned long flag, unsigned long offset)
-{
- unsigned long ret = -EINVAL;
- if ((offset + PAGE_ALIGN(len)) < offset)
- goto out;
- if (!(offset & ~PAGE_MASK))
- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
-out:
- return ret;
-}
-
+extern unsigned long do_mmap(struct file *, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
-extern unsigned long do_brk(unsigned long, unsigned long);
+/* These take the mm semaphore themselves */
+extern unsigned long vm_brk(unsigned long, unsigned long);
+extern int vm_munmap(unsigned long, size_t);
+extern unsigned long vm_mmap(struct file *, unsigned long,
+ unsigned long, unsigned long,
+ unsigned long, unsigned long);
/* truncate.c */
extern void truncate_inode_pages(struct address_space *, loff_t);
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 01beae7..629b823 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -481,7 +481,7 @@
struct device_driver drv;
int (*probe)(struct mmc_card *);
void (*remove)(struct mmc_card *);
- int (*suspend)(struct mmc_card *, pm_message_t);
+ int (*suspend)(struct mmc_card *);
int (*resume)(struct mmc_card *);
};
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1f77540..5cbaa20 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2604,8 +2604,6 @@
extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
extern void dev_seq_stop(struct seq_file *seq, void *v);
-extern int dev_seq_open_ops(struct inode *inode, struct file *file,
- const struct seq_operations *ops);
#endif
extern int netdev_class_create_file(struct class_attribute *class_attr);
diff --git a/include/linux/netfilter/xt_set.h b/include/linux/netfilter/xt_set.h
index c0405ac..e3a9978 100644
--- a/include/linux/netfilter/xt_set.h
+++ b/include/linux/netfilter/xt_set.h
@@ -58,8 +58,8 @@
struct xt_set_info_target_v2 {
struct xt_set_info add_set;
struct xt_set_info del_set;
- u32 flags;
- u32 timeout;
+ __u32 flags;
+ __u32 timeout;
};
#endif /*_XT_SET_H*/
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 0ddd161..31d2844 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -104,9 +104,18 @@
} daddr;
};
+static inline void br_drop_fake_rtable(struct sk_buff *skb)
+{
+ struct dst_entry *dst = skb_dst(skb);
+
+ if (dst && (dst->flags & DST_FAKE_RTABLE))
+ skb_dst_drop(skb);
+}
+
#else
#define nf_bridge_maybe_copy_header(skb) (0)
#define nf_bridge_pad(skb) (0)
+#define br_drop_fake_rtable(skb) do { } while (0)
#endif /* CONFIG_BRIDGE_NETFILTER */
#endif /* __KERNEL__ */
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index f549adc..1bc898b 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -287,7 +287,17 @@
struct xt_table *table);
/* Check for an extension */
-extern int ip6t_ext_hdr(u8 nexthdr);
+static inline int
+ip6t_ext_hdr(u8 nexthdr)
+{ return (nexthdr == IPPROTO_HOPOPTS) ||
+ (nexthdr == IPPROTO_ROUTING) ||
+ (nexthdr == IPPROTO_FRAGMENT) ||
+ (nexthdr == IPPROTO_ESP) ||
+ (nexthdr == IPPROTO_AH) ||
+ (nexthdr == IPPROTO_NONE) ||
+ (nexthdr == IPPROTO_DSTOPTS);
+}
+
/* find specified header and get offset to it */
extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
int target, unsigned short *fragoff);
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index bfd0d1b..7ba3551 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -312,6 +312,11 @@
int rpc_status;
};
+struct stateowner_id {
+ __u64 create_time;
+ __u32 uniquifier;
+};
+
/*
* Arguments to the open call.
*/
@@ -321,7 +326,7 @@
int open_flags;
fmode_t fmode;
__u64 clientid;
- __u64 id;
+ struct stateowner_id id;
union {
struct {
struct iattr * attrs; /* UNCHECKED, GUARDED */
diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
index b8d4001..5b7d84a 100644
--- a/include/linux/nfsd/Kbuild
+++ b/include/linux/nfsd/Kbuild
@@ -1,3 +1,4 @@
+header-y += cld.h
header-y += debug.h
header-y += export.h
header-y += nfsfh.h
diff --git a/include/linux/pinctrl/machine.h b/include/linux/pinctrl/machine.h
index fee4349..e4d1de7 100644
--- a/include/linux/pinctrl/machine.h
+++ b/include/linux/pinctrl/machine.h
@@ -12,6 +12,8 @@
#ifndef __LINUX_PINCTRL_MACHINE_H
#define __LINUX_PINCTRL_MACHINE_H
+#include <linux/bug.h>
+
#include "pinctrl-state.h"
enum pinctrl_map_type {
@@ -148,7 +150,7 @@
#define PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(dev, grp, cfgs) \
PIN_MAP_CONFIGS_GROUP(dev, PINCTRL_STATE_DEFAULT, dev, grp, cfgs)
-#ifdef CONFIG_PINMUX
+#ifdef CONFIG_PINCTRL
extern int pinctrl_register_mappings(struct pinctrl_map const *map,
unsigned num_maps);
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 6d626ff..e1ac1ce 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -6,6 +6,7 @@
#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
+#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */
/**
* struct pipe_buffer - a linux kernel pipe buffer
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index d056263..b0f2c56 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -4,8 +4,8 @@
* GPL v2 Only
*/
-#ifndef __ATMEL_NAND_H__
-#define __ATMEL_NAND_H__
+#ifndef __ATMEL_H__
+#define __ATMEL_H__
#include <linux/mtd/nand.h>
@@ -24,4 +24,4 @@
unsigned int num_parts;
};
-#endif /* __ATMEL_NAND_H__ */
+#endif /* __ATMEL_H__ */
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 2e9191a..233149c 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -8,6 +8,7 @@
#include <linux/notifier.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
+#include <linux/workqueue.h>
enum {
PM_QOS_RESERVED = 0,
@@ -29,6 +30,7 @@
struct pm_qos_request {
struct plist_node node;
int pm_qos_class;
+ struct delayed_work work; /* for pm_qos_update_request_timeout */
};
struct dev_pm_qos_request {
@@ -73,6 +75,8 @@
s32 value);
void pm_qos_update_request(struct pm_qos_request *req,
s32 new_value);
+void pm_qos_update_request_timeout(struct pm_qos_request *req,
+ s32 new_value, unsigned long timeout_us);
void pm_qos_remove_request(struct pm_qos_request *req);
int pm_qos_request(int pm_qos_class);
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h
index 7abb160..b021084 100644
--- a/include/linux/regulator/machine.h
+++ b/include/linux/regulator/machine.h
@@ -71,7 +71,7 @@
* @uV_offset: Offset applied to voltages from consumer to compensate for
* voltage drops.
*
- * @min_uA: Smallest consumers consumers may set.
+ * @min_uA: Smallest current consumers may set.
* @max_uA: Largest current consumers may set.
*
* @valid_modes_mask: Mask of modes which may be configured by consumers.
@@ -134,10 +134,8 @@
/**
* struct regulator_consumer_supply - supply -> device mapping
*
- * This maps a supply name to a device. Only one of dev or dev_name
- * can be specified. Use of dev_name allows support for buses which
- * make struct device available late such as I2C and is the preferred
- * form.
+ * This maps a supply name to a device. Use of dev_name allows support for
+ * buses which make struct device available late such as I2C.
*
* @dev_name: Result of dev_name() for the consumer.
* @supply: Name for the supply.
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index c6db9fb..600060e2 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -141,7 +141,7 @@
unsigned ret;
repeat:
- ret = s->sequence;
+ ret = ACCESS_ONCE(s->sequence);
if (unlikely(ret & 1)) {
cpu_relax();
goto repeat;
@@ -166,6 +166,27 @@
}
/**
+ * raw_seqcount_begin - begin a seq-read critical section
+ * @s: pointer to seqcount_t
+ * Returns: count to be passed to read_seqcount_retry
+ *
+ * raw_seqcount_begin opens a read critical section of the given seqcount.
+ * Validity of the critical section is tested by checking read_seqcount_retry
+ * function.
+ *
+ * Unlike read_seqcount_begin(), this function will not wait for the count
+ * to stabilize. If a writer is active when we begin, we will fail the
+ * read_seqcount_retry() instead of stabilizing at the beginning of the
+ * critical section.
+ */
+static inline unsigned raw_seqcount_begin(const seqcount_t *s)
+{
+ unsigned ret = ACCESS_ONCE(s->sequence);
+ smp_rmb();
+ return ret & ~1;
+}
+
+/**
* __read_seqcount_retry - end a seq-read critical section (without barrier)
* @s: pointer to seqcount_t
* @start: count, from read_seqcount_begin
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index f51bf2e..2db407a 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -357,7 +357,7 @@
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR ((__force upf_t) (1 << 25))
-#define UPF_IIR_ONCE ((__force upf_t) (1 << 26))
+#define UPF_BUG_THRE ((__force upf_t) (1 << 26))
/* The exact UART type is known and should not be probed. */
#define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3337027..111f26b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -238,11 +238,12 @@
/*
* The callback notifies userspace to release buffers when skb DMA is done in
* lower device, the skb last reference should be 0 when calling this.
- * The desc is used to track userspace buffer index.
+ * The ctx field is used to track device context.
+ * The desc field is used to track userspace buffer index.
*/
struct ubuf_info {
- void (*callback)(void *);
- void *arg;
+ void (*callback)(struct ubuf_info *);
+ void *ctx;
unsigned long desc;
};
@@ -481,6 +482,7 @@
union {
__u32 mark;
__u32 dropcount;
+ __u32 avail_size;
};
sk_buff_data_t transport_header;
@@ -1018,7 +1020,7 @@
}
/**
- * skb_queue_splice - join two skb lists and reinitialise the emptied list
+ * skb_queue_splice_init - join two skb lists and reinitialise the emptied list
* @list: the new list to add
* @head: the place to add it in the first list
*
@@ -1049,7 +1051,7 @@
}
/**
- * skb_queue_splice_tail - join two skb lists and reinitialise the emptied list
+ * skb_queue_splice_tail_init - join two skb lists and reinitialise the emptied list
* @list: the new list to add
* @head: the place to add it in the first list
*
@@ -1366,6 +1368,18 @@
}
/**
+ * skb_availroom - bytes at buffer end
+ * @skb: buffer to check
+ *
+ * Return the number of bytes of free space at the tail of an sk_buff
+ * allocated by sk_stream_alloc()
+ */
+static inline int skb_availroom(const struct sk_buff *skb)
+{
+ return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len;
+}
+
+/**
* skb_reserve - adjust headroom
* @skb: buffer to alter
* @len: bytes to move
diff --git a/include/linux/socket.h b/include/linux/socket.h
index da2d3e2..b84bbd4 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -265,7 +265,7 @@
#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
#define MSG_MORE 0x8000 /* Sender will send more */
#define MSG_WAITFORONE 0x10000 /* recvmmsg(): block until 1+ packets avail */
-
+#define MSG_SENDPAGE_NOTLAST 0x20000 /* sendpage() internal : not the last page */
#define MSG_EOF MSG_FIN
#define MSG_CMSG_CLOEXEC 0x40000000 /* Set close_on_exit for file
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index 98679b0..fa702ae 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -254,7 +254,7 @@
* driver is finished with this message, it must call
* spi_finalize_current_message() so the subsystem can issue the next
* transfer
- * @prepare_transfer_hardware: there are currently no more messages on the
+ * @unprepare_transfer_hardware: there are currently no more messages on the
* queue so the subsystem notifies the driver that it may relax the
* hardware by issuing this call
*
diff --git a/include/linux/stddef.h b/include/linux/stddef.h
index 6a40c76..1747b67 100644
--- a/include/linux/stddef.h
+++ b/include/linux/stddef.h
@@ -3,15 +3,11 @@
#include <linux/compiler.h>
-#undef NULL
-#if defined(__cplusplus)
-#define NULL 0
-#else
-#define NULL ((void *)0)
-#endif
-
#ifdef __KERNEL__
+#undef NULL
+#define NULL ((void *)0)
+
enum {
false = 0,
true = 1
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 8dc0ea7..b1fd5c7 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -305,6 +305,13 @@
return vm_swappiness;
}
#endif
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
+extern void mem_cgroup_uncharge_swap(swp_entry_t ent);
+#else
+static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
+{
+}
+#endif
#ifdef CONFIG_SWAP
/* linux/mm/page_io.c */
extern int swap_readpage(struct page *);
@@ -375,13 +382,6 @@
{
}
#endif
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
-extern void mem_cgroup_uncharge_swap(swp_entry_t ent);
-#else
-static inline void mem_cgroup_uncharge_swap(swp_entry_t ent)
-{
-}
-#endif
#else /* CONFIG_SWAP */
diff --git a/include/linux/types.h b/include/linux/types.h
index e5fa503..7f480db6 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -210,6 +210,12 @@
typedef phys_addr_t resource_size_t;
+/*
+ * This type is the placeholder for a hardware interrupt number. It has to be
+ * big enough to enclose whatever representation is used by a given platform.
+ */
+typedef unsigned long irq_hw_number_t;
+
typedef struct {
int counter;
} atomic_t;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 5de4157..d28cc78 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -126,6 +126,8 @@
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
+ unsigned broken_pci_sleep:1; /* Don't put the
+ controller in PCI-D3 for system sleep */
unsigned int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index f67810f..38ab3f4 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -94,6 +94,7 @@
struct usb_otg *otg;
+ struct device *io_dev;
struct usb_phy_io_ops *io_ops;
void __iomem *io_priv;
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h
index fbb666b..4742838 100644
--- a/include/linux/usb/serial.h
+++ b/include/linux/usb/serial.h
@@ -28,13 +28,6 @@
/* parity check flag */
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-enum port_dev_state {
- PORT_UNREGISTERED,
- PORT_REGISTERING,
- PORT_REGISTERED,
- PORT_UNREGISTERING,
-};
-
/* USB serial flags */
#define USB_SERIAL_WRITE_BUSY 0
@@ -124,7 +117,6 @@
char throttle_req;
unsigned long sysrq; /* sysrq timeout */
struct device dev;
- enum port_dev_state dev_state;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 9c3120d..b572f80 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -47,6 +47,8 @@
*/
#define VGA_DEFAULT_DEVICE (NULL)
+struct pci_dev;
+
/* For use by clients */
/**
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 03b90cdc..06f8e38 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -26,13 +26,14 @@
PGFREE, PGACTIVATE, PGDEACTIVATE,
PGFAULT, PGMAJFAULT,
FOR_ALL_ZONES(PGREFILL),
- FOR_ALL_ZONES(PGSTEAL),
+ FOR_ALL_ZONES(PGSTEAL_KSWAPD),
+ FOR_ALL_ZONES(PGSTEAL_DIRECT),
FOR_ALL_ZONES(PGSCAN_KSWAPD),
FOR_ALL_ZONES(PGSCAN_DIRECT),
#ifdef CONFIG_NUMA
PGSCAN_ZONE_RECLAIM_FAILED,
#endif
- PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL,
+ PGINODESTEAL, SLABS_SCANNED, KSWAPD_INODESTEAL,
KSWAPD_LOW_WMARK_HIT_QUICKLY, KSWAPD_HIGH_WMARK_HIT_QUICKLY,
KSWAPD_SKIP_CONGESTION_WAIT,
PAGEOUTRUN, ALLOCSTALL, PGROTATED,
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 344b0f9..d47e523 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -92,6 +92,7 @@
HCI_SERVICE_CACHE,
HCI_LINK_KEYS,
HCI_DEBUG_KEYS,
+ HCI_UNREGISTER,
HCI_LE_SCAN,
HCI_SSP_ENABLED,
@@ -1327,8 +1328,8 @@
#define HCI_DEV_NONE 0xffff
#define HCI_CHANNEL_RAW 0
-#define HCI_CHANNEL_CONTROL 1
#define HCI_CHANNEL_MONITOR 2
+#define HCI_CHANNEL_CONTROL 3
struct hci_filter {
unsigned long type_mask;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index daefaac..db1c5df 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -314,6 +314,7 @@
__u8 remote_cap;
__u8 remote_auth;
+ bool flush_key;
unsigned int sent;
@@ -427,7 +428,7 @@
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
- return (test_bit(HCI_SSP_ENABLED, &hdev->flags) &&
+ return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
test_bit(HCI_CONN_SSP_ENABLED, &conn->flags));
}
@@ -907,11 +908,13 @@
static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
{
- u8 field_len;
- size_t parsed;
+ size_t parsed = 0;
- for (parsed = 0; parsed < data_len - 1; parsed += field_len) {
- field_len = data[0];
+ if (data_len < 2)
+ return false;
+
+ while (parsed < data_len - 1) {
+ u8 field_len = data[0];
if (field_len == 0)
break;
@@ -978,7 +981,7 @@
int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
- u8 persistent);
+ bool persistent);
int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u32 flags, u8 *name, u8 name_len,
u8 *dev_class);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index ffc1377..ebfd91f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -117,7 +117,7 @@
#define MGMT_OP_SET_DISCOVERABLE 0x0006
struct mgmt_cp_set_discoverable {
__u8 val;
- __u16 timeout;
+ __le16 timeout;
} __packed;
#define MGMT_SET_DISCOVERABLE_SIZE 3
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 248fb05..83d800c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -620,8 +620,10 @@
* @llid: mesh local link id
* @plid: mesh peer link id
* @plink_state: mesh peer link state
- * @signal: signal strength of last received packet in dBm
- * @signal_avg: signal strength average in dBm
+ * @signal: the signal strength, type depends on the wiphy's signal_type
+ NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
+ * @signal_avg: avg signal strength, type depends on the wiphy's signal_type
+ NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @txrate: current unicast bitrate from this station
* @rxrate: current unicast bitrate to this station
* @rx_packets: packets received from this station
diff --git a/include/net/dst.h b/include/net/dst.h
index 59c5d18..bed833d 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -36,7 +36,11 @@
struct net_device *dev;
struct dst_ops *ops;
unsigned long _metrics;
- unsigned long expires;
+ union {
+ unsigned long expires;
+ /* point to where the dst_entry copied from */
+ struct dst_entry *from;
+ };
struct dst_entry *path;
struct neighbour __rcu *_neighbour;
#ifdef CONFIG_XFRM
@@ -55,6 +59,7 @@
#define DST_NOCACHE 0x0010
#define DST_NOCOUNT 0x0020
#define DST_NOPEER 0x0040
+#define DST_FAKE_RTABLE 0x0080
short error;
short obsolete;
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index b26bb81..0ae759a 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -123,6 +123,54 @@
return ((struct rt6_info *)dst)->rt6i_idev;
}
+static inline void rt6_clean_expires(struct rt6_info *rt)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
+ rt->rt6i_flags &= ~RTF_EXPIRES;
+ rt->dst.from = NULL;
+}
+
+static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from)
+ dst_release(rt->dst.from);
+
+ rt->rt6i_flags |= RTF_EXPIRES;
+ rt->dst.expires = expires;
+}
+
+static inline void rt6_update_expires(struct rt6_info *rt, int timeout)
+{
+ if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+ if (rt->dst.from)
+ dst_release(rt->dst.from);
+ /* dst_set_expires relies on expires == 0
+ * if it has not been set previously.
+ */
+ rt->dst.expires = 0;
+ }
+
+ dst_set_expires(&rt->dst, timeout);
+ rt->rt6i_flags |= RTF_EXPIRES;
+}
+
+static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
+{
+ struct dst_entry *new = (struct dst_entry *) from;
+
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) {
+ if (new == rt->dst.from)
+ return;
+ dst_release(rt->dst.from);
+ }
+
+ rt->rt6i_flags &= ~RTF_EXPIRES;
+ rt->dst.from = new;
+ dst_hold(new);
+}
+
struct fib6_walker_t {
struct list_head lh;
struct fib6_node *root, *node;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 2bdee51..72522f0 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -393,7 +393,7 @@
void (*exit)(struct ip_vs_protocol *pp);
- void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
+ int (*init_netns)(struct net *net, struct ip_vs_proto_data *pd);
void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd);
@@ -1203,6 +1203,8 @@
extern int ip_vs_use_count_inc(void);
extern void ip_vs_use_count_dec(void);
+extern int ip_vs_register_nl_ioctl(void);
+extern void ip_vs_unregister_nl_ioctl(void);
extern int ip_vs_control_init(void);
extern void ip_vs_control_cleanup(void);
extern struct ip_vs_dest *
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 87d203f..9210bdc 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1327,7 +1327,7 @@
ieee80211_get_tx_rate(const struct ieee80211_hw *hw,
const struct ieee80211_tx_info *c)
{
- if (WARN_ON(c->control.rates[0].idx < 0))
+ if (WARN_ON_ONCE(c->control.rates[0].idx < 0))
return NULL;
return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx];
}
diff --git a/include/net/netfilter/xt_log.h b/include/net/netfilter/xt_log.h
index 7e1544e..9d9756c 100644
--- a/include/net/netfilter/xt_log.h
+++ b/include/net/netfilter/xt_log.h
@@ -47,7 +47,7 @@
if (likely(m != &emergency))
kfree(m);
else {
- xchg(&emergency_ptr, m);
+ emergency_ptr = m;
local_bh_enable();
}
}
diff --git a/include/net/red.h b/include/net/red.h
index 77d4c37..ef46058 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -245,7 +245,7 @@
*
* dummy packets as a burst after idle time, i.e.
*
- * p->qavg *= (1-W)^m
+ * v->qavg *= (1-W)^m
*
* This is an apparently overcomplicated solution (f.e. we have to
* precompute a table to make this calculation in reasonable time)
@@ -279,7 +279,7 @@
unsigned int backlog)
{
/*
- * NOTE: p->qavg is fixed point number with point at Wlog.
+ * NOTE: v->qavg is fixed point number with point at Wlog.
* The formula below is equvalent to floating point
* version:
*
@@ -390,7 +390,7 @@
if (red_is_idling(v))
qavg = red_calc_qavg_from_idle_time(p, v);
- /* p->qavg is fixed point number with point at Wlog */
+ /* v->qavg is fixed point number with point at Wlog */
qavg >>= p->Wlog;
if (qavg > p->target_max && p->max_P <= MAX_P_MAX)
diff --git a/include/net/sock.h b/include/net/sock.h
index a6ba1f8..5a0a58a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -246,6 +246,7 @@
* @sk_user_data: RPC layer private data
* @sk_sndmsg_page: cached page for sendmsg
* @sk_sndmsg_off: cached offset for sendmsg
+ * @sk_peek_off: current peek_offset value
* @sk_send_head: front of stuff to transmit
* @sk_security: used by security modules
* @sk_mark: generic packet mark
@@ -1128,9 +1129,9 @@
struct proto *prot = sk->sk_prot;
if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
- return percpu_counter_sum_positive(sk->sk_cgrp->sockets_allocated);
+ return percpu_counter_read_positive(sk->sk_cgrp->sockets_allocated);
- return percpu_counter_sum_positive(prot->sockets_allocated);
+ return percpu_counter_read_positive(prot->sockets_allocated);
}
static inline int
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 5f5ed1b..f4f1c96 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -217,11 +217,29 @@
struct kref kref;
};
-struct sas_discovery_event {
+struct sas_work {
+ struct list_head drain_node;
struct work_struct work;
+};
+
+static inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *))
+{
+ INIT_WORK(&sw->work, fn);
+ INIT_LIST_HEAD(&sw->drain_node);
+}
+
+struct sas_discovery_event {
+ struct sas_work work;
struct asd_sas_port *port;
};
+static inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work)
+{
+ struct sas_discovery_event *ev = container_of(work, typeof(*ev), work.work);
+
+ return ev;
+}
+
struct sas_discovery {
struct sas_discovery_event disc_work[DISC_NUM_EVENTS];
unsigned long pending;
@@ -244,7 +262,7 @@
struct list_head destroy_list;
enum sas_linkrate linkrate;
- struct work_struct work;
+ struct sas_work work;
/* public: */
int id;
@@ -270,10 +288,17 @@
};
struct asd_sas_event {
- struct work_struct work;
+ struct sas_work work;
struct asd_sas_phy *phy;
};
+static inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work)
+{
+ struct asd_sas_event *ev = container_of(work, typeof(*ev), work.work);
+
+ return ev;
+}
+
/* The phy pretty much is controlled by the LLDD.
* The class only reads those fields.
*/
@@ -333,10 +358,17 @@
};
struct sas_ha_event {
- struct work_struct work;
+ struct sas_work work;
struct sas_ha_struct *ha;
};
+static inline struct sas_ha_event *to_sas_ha_event(struct work_struct *work)
+{
+ struct sas_ha_event *ev = container_of(work, typeof(*ev), work.work);
+
+ return ev;
+}
+
enum sas_ha_state {
SAS_HA_REGISTERED,
SAS_HA_DRAINING,
diff --git a/include/scsi/sas_ata.h b/include/scsi/sas_ata.h
index cdccd2e..77670e8 100644
--- a/include/scsi/sas_ata.h
+++ b/include/scsi/sas_ata.h
@@ -37,7 +37,7 @@
}
int sas_get_ata_info(struct domain_device *dev, struct ex_phy *phy);
-int sas_ata_init_host_and_port(struct domain_device *found_dev);
+int sas_ata_init(struct domain_device *dev);
void sas_ata_task_abort(struct sas_task *task);
void sas_ata_strategy_handler(struct Scsi_Host *shost);
void sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
@@ -52,7 +52,7 @@
{
return 0;
}
-static inline int sas_ata_init_host_and_port(struct domain_device *found_dev)
+static inline int sas_ata_init(struct domain_device *dev)
{
return 0;
}
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index 377df4a..1e11985 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -134,6 +134,9 @@
static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd)
{
+ if (!cmd->request->rq_disk)
+ return NULL;
+
return *(struct scsi_driver **)cmd->request->rq_disk->private_data;
}
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index fbc7b1a..ea7a203 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -295,7 +295,7 @@
TP_fast_assign(
__assign_str(filename, bprm->filename);
__entry->pid = p->pid;
- __entry->old_pid = p->pid;
+ __entry->old_pid = old_pid;
),
TP_printk("filename=%s pid=%d old_pid=%d", __get_str(filename),
diff --git a/include/xen/swiotlb-xen.h b/include/xen/swiotlb-xen.h
index 2ea2fdc..4f4d449 100644
--- a/include/xen/swiotlb-xen.h
+++ b/include/xen/swiotlb-xen.h
@@ -7,11 +7,13 @@
extern void
*xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags);
+ dma_addr_t *dma_handle, gfp_t flags,
+ struct dma_attrs *attrs);
extern void
xen_swiotlb_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs);
extern dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
diff --git a/init/Kconfig b/init/Kconfig
index 72f33fa..6cfd71d 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1414,8 +1414,8 @@
config INIT_ALL_POSSIBLE
bool
help
- Back when each arch used to define their own cpu_online_map and
- cpu_possible_map, some of them chose to initialize cpu_possible_map
+ Back when each arch used to define their own cpu_online_mask and
+ cpu_possible_mask, some of them chose to initialize cpu_possible_mask
with all 1s, and others with all 0s. When they were centralised,
it was better to provide this option than to break all the archs
and have several arch maintainers pursuing me down dark alleys.
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 0e93f92..42b0707 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -472,7 +472,7 @@
void __init mount_root(void)
{
#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (ROOT_DEV == Root_NFS) {
if (mount_nfs_root())
return;
diff --git a/init/main.c b/init/main.c
index 9d454f0..44b2433 100644
--- a/init/main.c
+++ b/init/main.c
@@ -225,13 +225,9 @@
early_param("loglevel", loglevel);
-/*
- * Unknown boot options get handed to init, unless they look like
- * unused parameters (modprobe will find them in /proc/cmdline).
- */
-static int __init unknown_bootoption(char *param, char *val)
+/* Change NUL term back to "=", to make "param" the whole string. */
+static int __init repair_env_string(char *param, char *val)
{
- /* Change NUL term back to "=", to make "param" the whole string. */
if (val) {
/* param=val or param="val"? */
if (val == param+strlen(param)+1)
@@ -243,6 +239,16 @@
} else
BUG();
}
+ return 0;
+}
+
+/*
+ * Unknown boot options get handed to init, unless they look like
+ * unused parameters (modprobe will find them in /proc/cmdline).
+ */
+static int __init unknown_bootoption(char *param, char *val)
+{
+ repair_env_string(param, val);
/* Handle obsolete-style parameters */
if (obsolete_checksetup(param))
@@ -732,11 +738,6 @@
"late parameters",
};
-static int __init ignore_unknown_bootoption(char *param, char *val)
-{
- return 0;
-}
-
static void __init do_initcall_level(int level)
{
extern const struct kernel_param __start___param[], __stop___param[];
@@ -747,7 +748,7 @@
static_command_line, __start___param,
__stop___param - __start___param,
level, level,
- ignore_unknown_bootoption);
+ repair_env_string);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
do_one_initcall(*fn);
diff --git a/kernel/compat.c b/kernel/compat.c
index 74ff849..d2c67aa 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -372,25 +372,54 @@
#ifdef __ARCH_WANT_SYS_SIGPROCMASK
-asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
- compat_old_sigset_t __user *oset)
+/*
+ * sys_sigprocmask SIG_SETMASK sets the first (compat) word of the
+ * blocked set of signals to the supplied signal set
+ */
+static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set)
{
- old_sigset_t s;
- long ret;
- mm_segment_t old_fs;
+ memcpy(blocked->sig, &set, sizeof(set));
+}
- if (set && get_user(s, set))
- return -EFAULT;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_sigprocmask(how,
- set ? (old_sigset_t __user *) &s : NULL,
- oset ? (old_sigset_t __user *) &s : NULL);
- set_fs(old_fs);
- if (ret == 0)
- if (oset)
- ret = put_user(s, oset);
- return ret;
+asmlinkage long compat_sys_sigprocmask(int how,
+ compat_old_sigset_t __user *nset,
+ compat_old_sigset_t __user *oset)
+{
+ old_sigset_t old_set, new_set;
+ sigset_t new_blocked;
+
+ old_set = current->blocked.sig[0];
+
+ if (nset) {
+ if (get_user(new_set, nset))
+ return -EFAULT;
+ new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
+
+ new_blocked = current->blocked;
+
+ switch (how) {
+ case SIG_BLOCK:
+ sigaddsetmask(&new_blocked, new_set);
+ break;
+ case SIG_UNBLOCK:
+ sigdelsetmask(&new_blocked, new_set);
+ break;
+ case SIG_SETMASK:
+ compat_sig_setmask(&new_blocked, new_set);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ set_current_blocked(&new_blocked);
+ }
+
+ if (oset) {
+ if (put_user(old_set, oset))
+ return -EFAULT;
+ }
+
+ return 0;
}
#endif
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index b96ad75..14f7070 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -270,11 +270,11 @@
* are online. If none are online, walk up the cpuset hierarchy
* until we find one that does have some online cpus. If we get
* all the way to the top and still haven't found any online cpus,
- * return cpu_online_map. Or if passed a NULL cs from an exit'ing
- * task, return cpu_online_map.
+ * return cpu_online_mask. Or if passed a NULL cs from an exit'ing
+ * task, return cpu_online_mask.
*
* One way or another, we guarantee to return some non-empty subset
- * of cpu_online_map.
+ * of cpu_online_mask.
*
* Call with callback_mutex held.
*/
@@ -867,7 +867,7 @@
int retval;
int is_load_balanced;
- /* top_cpuset.cpus_allowed tracks cpu_online_map; it's read-only */
+ /* top_cpuset.cpus_allowed tracks cpu_online_mask; it's read-only */
if (cs == &top_cpuset)
return -EACCES;
@@ -2149,7 +2149,7 @@
*
* Description: Returns the cpumask_var_t cpus_allowed of the cpuset
* attached to the specified @tsk. Guaranteed to return some non-empty
- * subset of cpu_online_map, even if this means going outside the
+ * subset of cpu_online_mask, even if this means going outside the
* tasks cpuset.
**/
diff --git a/kernel/cred.c b/kernel/cred.c
index 97b36ee..e70683d 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -386,6 +386,8 @@
struct cred *new;
int ret;
+ p->replacement_session_keyring = NULL;
+
if (
#ifdef CONFIG_KEYS
!p->cred->thread_keyring &&
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 1dc53ba..0557f24 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -160,37 +160,39 @@
* Weak aliases for breakpoint management,
* can be overriden by architectures when needed:
*/
-int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
{
int err;
- err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
+ err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+ BREAK_INSTR_SIZE);
if (err)
return err;
-
- return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
- BREAK_INSTR_SIZE);
+ err = probe_kernel_write((char *)bpt->bpt_addr,
+ arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+ return err;
}
-int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{
- return probe_kernel_write((char *)addr,
- (char *)bundle, BREAK_INSTR_SIZE);
+ return probe_kernel_write((char *)bpt->bpt_addr,
+ (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
}
int __weak kgdb_validate_break_address(unsigned long addr)
{
- char tmp_variable[BREAK_INSTR_SIZE];
+ struct kgdb_bkpt tmp;
int err;
- /* Validate setting the breakpoint and then removing it. In the
+ /* Validate setting the breakpoint and then removing it. If the
* remove fails, the kernel needs to emit a bad message because we
* are deep trouble not being able to put things back the way we
* found them.
*/
- err = kgdb_arch_set_breakpoint(addr, tmp_variable);
+ tmp.bpt_addr = addr;
+ err = kgdb_arch_set_breakpoint(&tmp);
if (err)
return err;
- err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
+ err = kgdb_arch_remove_breakpoint(&tmp);
if (err)
printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
"memory destroyed at: %lx", addr);
@@ -234,7 +236,6 @@
*/
int dbg_activate_sw_breakpoints(void)
{
- unsigned long addr;
int error;
int ret = 0;
int i;
@@ -243,16 +244,15 @@
if (kgdb_break[i].state != BP_SET)
continue;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_set_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
if (error) {
ret = error;
- printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
+ printk(KERN_INFO "KGDB: BP install failed: %lx",
+ kgdb_break[i].bpt_addr);
continue;
}
- kgdb_flush_swbreak_addr(addr);
+ kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
kgdb_break[i].state = BP_ACTIVE;
}
return ret;
@@ -301,7 +301,6 @@
int dbg_deactivate_sw_breakpoints(void)
{
- unsigned long addr;
int error;
int ret = 0;
int i;
@@ -309,15 +308,14 @@
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
if (kgdb_break[i].state != BP_ACTIVE)
continue;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_remove_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
if (error) {
- printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
+ printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
+ kgdb_break[i].bpt_addr);
ret = error;
}
- kgdb_flush_swbreak_addr(addr);
+ kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
kgdb_break[i].state = BP_SET;
}
return ret;
@@ -351,7 +349,6 @@
int dbg_remove_all_break(void)
{
- unsigned long addr;
int error;
int i;
@@ -359,12 +356,10 @@
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
if (kgdb_break[i].state != BP_ACTIVE)
goto setundefined;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_remove_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
if (error)
printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
- addr);
+ kgdb_break[i].bpt_addr);
setundefined:
kgdb_break[i].state = BP_UNDEFINED;
}
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 9b5f17d..bb9520f 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -743,7 +743,7 @@
kdb_input_flush();
c = console_drivers;
- if (!dbg_io_ops->is_console) {
+ if (dbg_io_ops && !dbg_io_ops->is_console) {
len = strlen(moreprompt);
cp = moreprompt;
while (len--) {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a6a9ec4..fd126f8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3183,7 +3183,7 @@
perf_event_for_each_child(event, func);
func(event);
list_for_each_entry(sibling, &event->sibling_list, group_entry)
- perf_event_for_each_child(event, func);
+ perf_event_for_each_child(sibling, func);
mutex_unlock(&ctx->mutex);
}
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index cf1a4a6..d1a758b 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -62,7 +62,7 @@
help
This option will show the mapping relationship between hardware irq
numbers and Linux irq numbers. The mapping is exposed via debugfs
- in the file "virq_mapping".
+ in the file "irq_domain_mapping".
If you don't know what this means you don't need it.
diff --git a/kernel/irq/debug.h b/kernel/irq/debug.h
index 97a8bfa..e75e29e 100644
--- a/kernel/irq/debug.h
+++ b/kernel/irq/debug.h
@@ -4,10 +4,10 @@
#include <linux/kallsyms.h>
-#define P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
-#define PS(f) if (desc->istate & f) printk("%14s set\n", #f)
+#define ___P(f) if (desc->status_use_accessors & f) printk("%14s set\n", #f)
+#define ___PS(f) if (desc->istate & f) printk("%14s set\n", #f)
/* FIXME */
-#define PD(f) do { } while (0)
+#define ___PD(f) do { } while (0)
static inline void print_irq_desc(unsigned int irq, struct irq_desc *desc)
{
@@ -23,23 +23,23 @@
print_symbol("%s\n", (unsigned long)desc->action->handler);
}
- P(IRQ_LEVEL);
- P(IRQ_PER_CPU);
- P(IRQ_NOPROBE);
- P(IRQ_NOREQUEST);
- P(IRQ_NOTHREAD);
- P(IRQ_NOAUTOEN);
+ ___P(IRQ_LEVEL);
+ ___P(IRQ_PER_CPU);
+ ___P(IRQ_NOPROBE);
+ ___P(IRQ_NOREQUEST);
+ ___P(IRQ_NOTHREAD);
+ ___P(IRQ_NOAUTOEN);
- PS(IRQS_AUTODETECT);
- PS(IRQS_REPLAY);
- PS(IRQS_WAITING);
- PS(IRQS_PENDING);
+ ___PS(IRQS_AUTODETECT);
+ ___PS(IRQS_REPLAY);
+ ___PS(IRQS_WAITING);
+ ___PS(IRQS_PENDING);
- PD(IRQS_INPROGRESS);
- PD(IRQS_DISABLED);
- PD(IRQS_MASKED);
+ ___PD(IRQS_INPROGRESS);
+ ___PD(IRQS_DISABLED);
+ ___PD(IRQS_MASKED);
}
-#undef P
-#undef PS
-#undef PD
+#undef ___P
+#undef ___PS
+#undef ___PD
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 3601f3f..0e0ba5f 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -23,7 +23,6 @@
static DEFINE_MUTEX(irq_domain_mutex);
static DEFINE_MUTEX(revmap_trees_mutex);
-static unsigned int irq_virq_count = NR_IRQS;
static struct irq_domain *irq_default_domain;
/**
@@ -184,13 +183,16 @@
}
struct irq_domain *irq_domain_add_nomap(struct device_node *of_node,
+ unsigned int max_irq,
const struct irq_domain_ops *ops,
void *host_data)
{
struct irq_domain *domain = irq_domain_alloc(of_node,
IRQ_DOMAIN_MAP_NOMAP, ops, host_data);
- if (domain)
+ if (domain) {
+ domain->revmap_data.nomap.max_irq = max_irq ? max_irq : ~0;
irq_domain_add(domain);
+ }
return domain;
}
@@ -262,22 +264,6 @@
irq_default_domain = domain;
}
-/**
- * irq_set_virq_count() - Set the maximum number of linux irqs
- * @count: number of linux irqs, capped with NR_IRQS
- *
- * This is mainly for use by platforms like iSeries who want to program
- * the virtual irq number in the controller to avoid the reverse mapping
- */
-void irq_set_virq_count(unsigned int count)
-{
- pr_debug("irq: Trying to set virq count to %d\n", count);
-
- BUG_ON(count < NUM_ISA_INTERRUPTS);
- if (count < NR_IRQS)
- irq_virq_count = count;
-}
-
static int irq_setup_virq(struct irq_domain *domain, unsigned int virq,
irq_hw_number_t hwirq)
{
@@ -320,13 +306,12 @@
pr_debug("irq: create_direct virq allocation failed\n");
return 0;
}
- if (virq >= irq_virq_count) {
+ if (virq >= domain->revmap_data.nomap.max_irq) {
pr_err("ERROR: no free irqs available below %i maximum\n",
- irq_virq_count);
+ domain->revmap_data.nomap.max_irq);
irq_free_desc(virq);
return 0;
}
-
pr_debug("irq: create_direct obtained virq %d\n", virq);
if (irq_setup_virq(domain, virq, virq)) {
@@ -350,7 +335,8 @@
unsigned int irq_create_mapping(struct irq_domain *domain,
irq_hw_number_t hwirq)
{
- unsigned int virq, hint;
+ unsigned int hint;
+ int virq;
pr_debug("irq: irq_create_mapping(0x%p, 0x%lx)\n", domain, hwirq);
@@ -377,13 +363,13 @@
return irq_domain_legacy_revmap(domain, hwirq);
/* Allocate a virtual interrupt number */
- hint = hwirq % irq_virq_count;
+ hint = hwirq % nr_irqs;
if (hint == 0)
hint++;
virq = irq_alloc_desc_from(hint, 0);
- if (!virq)
+ if (virq <= 0)
virq = irq_alloc_desc_from(1, 0);
- if (!virq) {
+ if (virq <= 0) {
pr_debug("irq: -> virq allocation failed\n");
return 0;
}
@@ -515,7 +501,7 @@
irq_hw_number_t hwirq)
{
unsigned int i;
- unsigned int hint = hwirq % irq_virq_count;
+ unsigned int hint = hwirq % nr_irqs;
/* Look for default domain if nececssary */
if (domain == NULL)
@@ -536,7 +522,7 @@
if (data && (data->domain == domain) && (data->hwirq == hwirq))
return i;
i++;
- if (i >= irq_virq_count)
+ if (i >= nr_irqs)
i = 1;
} while(i != hint);
return 0;
@@ -642,8 +628,9 @@
void *data;
int i;
- seq_printf(m, "%-5s %-7s %-15s %-18s %s\n", "virq", "hwirq",
- "chip name", "chip data", "domain name");
+ seq_printf(m, "%-5s %-7s %-15s %-*s %s\n", "irq", "hwirq",
+ "chip name", (int)(2 * sizeof(void *) + 2), "chip data",
+ "domain name");
for (i = 1; i < nr_irqs; i++) {
desc = irq_to_desc(i);
@@ -666,7 +653,7 @@
seq_printf(m, "%-15s ", p);
data = irq_desc_get_chip_data(desc);
- seq_printf(m, "0x%16p ", data);
+ seq_printf(m, data ? "0x%p " : " %p ", data);
if (desc->irq_data.domain && desc->irq_data.domain->of_node)
p = desc->irq_data.domain->of_node->full_name;
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index c3c46c7..1588e3b 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -5,11 +5,13 @@
* context. The enqueueing is NMI-safe.
*/
+#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/irq_work.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
+#include <linux/irqflags.h>
#include <asm/processor.h>
/*
diff --git a/kernel/itimer.c b/kernel/itimer.c
index 22000c3..8d262b4 100644
--- a/kernel/itimer.c
+++ b/kernel/itimer.c
@@ -284,8 +284,12 @@
if (value) {
if(copy_from_user(&set_buffer, value, sizeof(set_buffer)))
return -EFAULT;
- } else
- memset((char *) &set_buffer, 0, sizeof(set_buffer));
+ } else {
+ memset(&set_buffer, 0, sizeof(set_buffer));
+ printk_once(KERN_WARNING "%s calls setitimer() with new_value NULL pointer."
+ " Misfeature support will be removed\n",
+ current->comm);
+ }
error = do_setitimer(which, &set_buffer, ovalue ? &get_buffer : NULL);
if (error || !ovalue)
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 957a7aa..05698a7 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -322,7 +322,7 @@
* land has been frozen during a system-wide hibernation or suspend operation).
* Should always be manipulated under umhelper_sem acquired for write.
*/
-static int usermodehelper_disabled = 1;
+static enum umh_disable_depth usermodehelper_disabled = UMH_DISABLED;
/* Number of helpers running */
static atomic_t running_helpers = ATOMIC_INIT(0);
@@ -334,32 +334,110 @@
static DECLARE_WAIT_QUEUE_HEAD(running_helpers_waitq);
/*
+ * Used by usermodehelper_read_lock_wait() to wait for usermodehelper_disabled
+ * to become 'false'.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(usermodehelper_disabled_waitq);
+
+/*
* Time to wait for running_helpers to become zero before the setting of
* usermodehelper_disabled in usermodehelper_disable() fails
*/
#define RUNNING_HELPERS_TIMEOUT (5 * HZ)
-void read_lock_usermodehelper(void)
+int usermodehelper_read_trylock(void)
{
- down_read(&umhelper_sem);
-}
-EXPORT_SYMBOL_GPL(read_lock_usermodehelper);
+ DEFINE_WAIT(wait);
+ int ret = 0;
-void read_unlock_usermodehelper(void)
+ down_read(&umhelper_sem);
+ for (;;) {
+ prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+ TASK_INTERRUPTIBLE);
+ if (!usermodehelper_disabled)
+ break;
+
+ if (usermodehelper_disabled == UMH_DISABLED)
+ ret = -EAGAIN;
+
+ up_read(&umhelper_sem);
+
+ if (ret)
+ break;
+
+ schedule();
+ try_to_freeze();
+
+ down_read(&umhelper_sem);
+ }
+ finish_wait(&usermodehelper_disabled_waitq, &wait);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_read_trylock);
+
+long usermodehelper_read_lock_wait(long timeout)
+{
+ DEFINE_WAIT(wait);
+
+ if (timeout < 0)
+ return -EINVAL;
+
+ down_read(&umhelper_sem);
+ for (;;) {
+ prepare_to_wait(&usermodehelper_disabled_waitq, &wait,
+ TASK_UNINTERRUPTIBLE);
+ if (!usermodehelper_disabled)
+ break;
+
+ up_read(&umhelper_sem);
+
+ timeout = schedule_timeout(timeout);
+ if (!timeout)
+ break;
+
+ down_read(&umhelper_sem);
+ }
+ finish_wait(&usermodehelper_disabled_waitq, &wait);
+ return timeout;
+}
+EXPORT_SYMBOL_GPL(usermodehelper_read_lock_wait);
+
+void usermodehelper_read_unlock(void)
{
up_read(&umhelper_sem);
}
-EXPORT_SYMBOL_GPL(read_unlock_usermodehelper);
+EXPORT_SYMBOL_GPL(usermodehelper_read_unlock);
/**
- * usermodehelper_disable - prevent new helpers from being started
+ * __usermodehelper_set_disable_depth - Modify usermodehelper_disabled.
+ * depth: New value to assign to usermodehelper_disabled.
+ *
+ * Change the value of usermodehelper_disabled (under umhelper_sem locked for
+ * writing) and wakeup tasks waiting for it to change.
*/
-int usermodehelper_disable(void)
+void __usermodehelper_set_disable_depth(enum umh_disable_depth depth)
+{
+ down_write(&umhelper_sem);
+ usermodehelper_disabled = depth;
+ wake_up(&usermodehelper_disabled_waitq);
+ up_write(&umhelper_sem);
+}
+
+/**
+ * __usermodehelper_disable - Prevent new helpers from being started.
+ * @depth: New value to assign to usermodehelper_disabled.
+ *
+ * Set usermodehelper_disabled to @depth and wait for running helpers to exit.
+ */
+int __usermodehelper_disable(enum umh_disable_depth depth)
{
long retval;
+ if (!depth)
+ return -EINVAL;
+
down_write(&umhelper_sem);
- usermodehelper_disabled = 1;
+ usermodehelper_disabled = depth;
up_write(&umhelper_sem);
/*
@@ -374,31 +452,10 @@
if (retval)
return 0;
- down_write(&umhelper_sem);
- usermodehelper_disabled = 0;
- up_write(&umhelper_sem);
+ __usermodehelper_set_disable_depth(UMH_ENABLED);
return -EAGAIN;
}
-/**
- * usermodehelper_enable - allow new helpers to be started again
- */
-void usermodehelper_enable(void)
-{
- down_write(&umhelper_sem);
- usermodehelper_disabled = 0;
- up_write(&umhelper_sem);
-}
-
-/**
- * usermodehelper_is_disabled - check if new helpers are allowed to be started
- */
-bool usermodehelper_is_disabled(void)
-{
- return usermodehelper_disabled;
-}
-EXPORT_SYMBOL_GPL(usermodehelper_is_disabled);
-
static void helper_lock(void)
{
atomic_inc(&running_helpers);
diff --git a/kernel/padata.c b/kernel/padata.c
index 6f10eb2..89fe3d1 100644
--- a/kernel/padata.c
+++ b/kernel/padata.c
@@ -1,6 +1,8 @@
/*
* padata.c - generic interface to process data streams in parallel
*
+ * See Documentation/padata.txt for an api documentation.
+ *
* Copyright (C) 2008, 2009 secunet Security Networks AG
* Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com>
*
@@ -354,13 +356,13 @@
if (!alloc_cpumask_var(&pd->cpumask.pcpu, GFP_KERNEL))
return -ENOMEM;
- cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_active_mask);
+ cpumask_and(pd->cpumask.pcpu, pcpumask, cpu_online_mask);
if (!alloc_cpumask_var(&pd->cpumask.cbcpu, GFP_KERNEL)) {
free_cpumask_var(pd->cpumask.cbcpu);
return -ENOMEM;
}
- cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_active_mask);
+ cpumask_and(pd->cpumask.cbcpu, cbcpumask, cpu_online_mask);
return 0;
}
@@ -564,7 +566,7 @@
static bool padata_validate_cpumask(struct padata_instance *pinst,
const struct cpumask *cpumask)
{
- if (!cpumask_intersects(cpumask, cpu_active_mask)) {
+ if (!cpumask_intersects(cpumask, cpu_online_mask)) {
pinst->flags |= PADATA_INVALID;
return false;
}
@@ -678,7 +680,7 @@
{
struct parallel_data *pd;
- if (cpumask_test_cpu(cpu, cpu_active_mask)) {
+ if (cpumask_test_cpu(cpu, cpu_online_mask)) {
pd = padata_alloc_pd(pinst, pinst->cpumask.pcpu,
pinst->cpumask.cbcpu);
if (!pd)
@@ -746,6 +748,9 @@
return -ENOMEM;
padata_replace(pinst, pd);
+
+ cpumask_clear_cpu(cpu, pd->cpumask.cbcpu);
+ cpumask_clear_cpu(cpu, pd->cpumask.pcpu);
}
return 0;
diff --git a/kernel/panic.c b/kernel/panic.c
index 80aed44..8ed89a1 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -97,7 +97,7 @@
/*
* Avoid nested stack-dumping if a panic occurs during oops processing
*/
- if (!oops_in_progress)
+ if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)
dump_stack();
#endif
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 0a186cf..e09dfbf 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -16,7 +16,6 @@
#include <linux/string.h>
#include <linux/device.h>
#include <linux/async.h>
-#include <linux/kmod.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/mount.h>
@@ -611,14 +610,10 @@
if (error)
goto Exit;
- error = usermodehelper_disable();
- if (error)
- goto Exit;
-
/* Allocate memory management structures */
error = create_basic_memory_bitmaps();
if (error)
- goto Enable_umh;
+ goto Exit;
printk(KERN_INFO "PM: Syncing filesystems ... ");
sys_sync();
@@ -661,8 +656,6 @@
Free_bitmaps:
free_basic_memory_bitmaps();
- Enable_umh:
- usermodehelper_enable();
Exit:
pm_notifier_call_chain(PM_POST_HIBERNATION);
pm_restore_console();
@@ -777,16 +770,10 @@
if (error)
goto close_finish;
- error = usermodehelper_disable();
+ error = create_basic_memory_bitmaps();
if (error)
goto close_finish;
- error = create_basic_memory_bitmaps();
- if (error) {
- usermodehelper_enable();
- goto close_finish;
- }
-
pr_debug("PM: Preparing processes for restore.\n");
error = freeze_processes();
if (error) {
@@ -806,7 +793,6 @@
thaw_processes();
Done:
free_basic_memory_bitmaps();
- usermodehelper_enable();
Finish:
pm_notifier_call_chain(PM_POST_RESTORE);
pm_restore_console();
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 0d2aeb2..19db29f 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -16,6 +16,7 @@
#include <linux/freezer.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
+#include <linux/kmod.h>
/*
* Timeout for stopping processes
@@ -122,6 +123,10 @@
{
int error;
+ error = __usermodehelper_disable(UMH_FREEZING);
+ if (error)
+ return error;
+
if (!pm_freezing)
atomic_inc(&system_freezing_cnt);
@@ -130,6 +135,7 @@
error = try_to_freeze_tasks(true);
if (!error) {
printk("done.");
+ __usermodehelper_set_disable_depth(UMH_DISABLED);
oom_killer_disable();
}
printk("\n");
@@ -187,6 +193,8 @@
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
+ usermodehelper_enable();
+
schedule();
printk("done.\n");
}
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index d6d6dbd..6a031e6 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -230,6 +230,21 @@
EXPORT_SYMBOL_GPL(pm_qos_request_active);
/**
+ * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout
+ * @work: work struct for the delayed work (timeout)
+ *
+ * This cancels the timeout request by falling back to the default at timeout.
+ */
+static void pm_qos_work_fn(struct work_struct *work)
+{
+ struct pm_qos_request *req = container_of(to_delayed_work(work),
+ struct pm_qos_request,
+ work);
+
+ pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
+}
+
+/**
* pm_qos_add_request - inserts new qos request into the list
* @req: pointer to a preallocated handle
* @pm_qos_class: identifies which list of qos request to use
@@ -253,6 +268,7 @@
return;
}
req->pm_qos_class = pm_qos_class;
+ INIT_DELAYED_WORK(&req->work, pm_qos_work_fn);
pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
&req->node, PM_QOS_ADD_REQ, value);
}
@@ -279,6 +295,9 @@
return;
}
+ if (delayed_work_pending(&req->work))
+ cancel_delayed_work_sync(&req->work);
+
if (new_value != req->node.prio)
pm_qos_update_target(
pm_qos_array[req->pm_qos_class]->constraints,
@@ -287,6 +306,34 @@
EXPORT_SYMBOL_GPL(pm_qos_update_request);
/**
+ * pm_qos_update_request_timeout - modifies an existing qos request temporarily.
+ * @req : handle to list element holding a pm_qos request to use
+ * @new_value: defines the temporal qos request
+ * @timeout_us: the effective duration of this qos request in usecs.
+ *
+ * After timeout_us, this qos request is cancelled automatically.
+ */
+void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value,
+ unsigned long timeout_us)
+{
+ if (!req)
+ return;
+ if (WARN(!pm_qos_request_active(req),
+ "%s called for unknown object.", __func__))
+ return;
+
+ if (delayed_work_pending(&req->work))
+ cancel_delayed_work_sync(&req->work);
+
+ if (new_value != req->node.prio)
+ pm_qos_update_target(
+ pm_qos_array[req->pm_qos_class]->constraints,
+ &req->node, PM_QOS_UPDATE_REQ, new_value);
+
+ schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us));
+}
+
+/**
* pm_qos_remove_request - modifies an existing qos request
* @req: handle to request list element
*
@@ -305,6 +352,9 @@
return;
}
+ if (delayed_work_pending(&req->work))
+ cancel_delayed_work_sync(&req->work);
+
pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
&req->node, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 88e5c967..396d262 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -12,7 +12,6 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
-#include <linux/kmod.h>
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
@@ -102,17 +101,12 @@
if (error)
goto Finish;
- error = usermodehelper_disable();
- if (error)
- goto Finish;
-
error = suspend_freeze_processes();
if (!error)
return 0;
suspend_stats.failed_freeze++;
dpm_save_failed_step(SUSPEND_FREEZE);
- usermodehelper_enable();
Finish:
pm_notifier_call_chain(PM_POST_SUSPEND);
pm_restore_console();
@@ -259,7 +253,6 @@
static void suspend_finish(void)
{
suspend_thaw_processes();
- usermodehelper_enable();
pm_notifier_call_chain(PM_POST_SUSPEND);
pm_restore_console();
}
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 8742fd0..eef311a 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -51,6 +51,23 @@
#define MAP_PAGE_ENTRIES (PAGE_SIZE / sizeof(sector_t) - 1)
+/*
+ * Number of free pages that are not high.
+ */
+static inline unsigned long low_free_pages(void)
+{
+ return nr_free_pages() - nr_free_highpages();
+}
+
+/*
+ * Number of pages required to be kept free while writing the image. Always
+ * half of all available low pages before the writing starts.
+ */
+static inline unsigned long reqd_free_pages(void)
+{
+ return low_free_pages() / 2;
+}
+
struct swap_map_page {
sector_t entries[MAP_PAGE_ENTRIES];
sector_t next_swap;
@@ -72,7 +89,7 @@
sector_t cur_swap;
sector_t first_sector;
unsigned int k;
- unsigned long nr_free_pages, written;
+ unsigned long reqd_free_pages;
u32 crc32;
};
@@ -316,8 +333,7 @@
goto err_rel;
}
handle->k = 0;
- handle->nr_free_pages = nr_free_pages() >> 1;
- handle->written = 0;
+ handle->reqd_free_pages = reqd_free_pages();
handle->first_sector = handle->cur_swap;
return 0;
err_rel:
@@ -352,11 +368,11 @@
handle->cur_swap = offset;
handle->k = 0;
}
- if (bio_chain && ++handle->written > handle->nr_free_pages) {
+ if (bio_chain && low_free_pages() <= handle->reqd_free_pages) {
error = hib_wait_on_bio_chain(bio_chain);
if (error)
goto out;
- handle->written = 0;
+ handle->reqd_free_pages = reqd_free_pages();
}
out:
return error;
@@ -618,7 +634,7 @@
* Adjust number of free pages after all allocations have been done.
* We don't want to run out of pages when writing.
*/
- handle->nr_free_pages = nr_free_pages() >> 1;
+ handle->reqd_free_pages = reqd_free_pages();
/*
* Start the CRC32 thread.
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 33c4329..91b0fd0 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -12,7 +12,6 @@
#include <linux/suspend.h>
#include <linux/syscalls.h>
#include <linux/reboot.h>
-#include <linux/kmod.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
@@ -222,14 +221,8 @@
sys_sync();
printk("done.\n");
- error = usermodehelper_disable();
- if (error)
- break;
-
error = freeze_processes();
- if (error)
- usermodehelper_enable();
- else
+ if (!error)
data->frozen = 1;
break;
@@ -238,7 +231,6 @@
break;
pm_restore_gfp_mask();
thaw_processes();
- usermodehelper_enable();
data->frozen = 0;
break;
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 1050d6d..d0c5baf 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1820,7 +1820,6 @@
* a quiescent state betweentimes.
*/
local_irq_save(flags);
- WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
rdp = this_cpu_ptr(rsp->rda);
/* Add the callback to our list. */
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 4603b9d..0533a68 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6405,16 +6405,26 @@
struct sd_data *sdd = &tl->data;
for_each_cpu(j, cpu_map) {
- struct sched_domain *sd = *per_cpu_ptr(sdd->sd, j);
- if (sd && (sd->flags & SD_OVERLAP))
- free_sched_groups(sd->groups, 0);
- kfree(*per_cpu_ptr(sdd->sd, j));
- kfree(*per_cpu_ptr(sdd->sg, j));
- kfree(*per_cpu_ptr(sdd->sgp, j));
+ struct sched_domain *sd;
+
+ if (sdd->sd) {
+ sd = *per_cpu_ptr(sdd->sd, j);
+ if (sd && (sd->flags & SD_OVERLAP))
+ free_sched_groups(sd->groups, 0);
+ kfree(*per_cpu_ptr(sdd->sd, j));
+ }
+
+ if (sdd->sg)
+ kfree(*per_cpu_ptr(sdd->sg, j));
+ if (sdd->sgp)
+ kfree(*per_cpu_ptr(sdd->sgp, j));
}
free_percpu(sdd->sd);
+ sdd->sd = NULL;
free_percpu(sdd->sg);
+ sdd->sg = NULL;
free_percpu(sdd->sgp);
+ sdd->sgp = NULL;
}
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 0d97ebd..e955364 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -784,7 +784,7 @@
update_load_add(&rq_of(cfs_rq)->load, se->load.weight);
#ifdef CONFIG_SMP
if (entity_is_task(se))
- list_add_tail(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
+ list_add(&se->group_node, &rq_of(cfs_rq)->cfs_tasks);
#endif
cfs_rq->nr_running++;
}
@@ -3215,6 +3215,8 @@
static unsigned long task_h_load(struct task_struct *p);
+static const unsigned int sched_nr_migrate_break = 32;
+
/*
* move_tasks tries to move up to load_move weighted load from busiest to
* this_rq, as part of a balancing operation within domain "sd".
@@ -3242,7 +3244,7 @@
/* take a breather every nr_migrate tasks */
if (env->loop > env->loop_break) {
- env->loop_break += sysctl_sched_nr_migrate;
+ env->loop_break += sched_nr_migrate_break;
env->flags |= LBF_NEED_BREAK;
break;
}
@@ -3252,7 +3254,7 @@
load = task_h_load(p);
- if (load < 16 && !env->sd->nr_balance_failed)
+ if (sched_feat(LB_MIN) && load < 16 && !env->sd->nr_balance_failed)
goto next;
if ((load / 2) > env->load_move)
@@ -4407,7 +4409,7 @@
.dst_cpu = this_cpu,
.dst_rq = this_rq,
.idle = idle,
- .loop_break = sysctl_sched_nr_migrate,
+ .loop_break = sched_nr_migrate_break,
};
cpumask_copy(cpus, cpu_active_mask);
@@ -4445,10 +4447,10 @@
* correctly treated as an imbalance.
*/
env.flags |= LBF_ALL_PINNED;
- env.load_move = imbalance;
- env.src_cpu = busiest->cpu;
- env.src_rq = busiest;
- env.loop_max = busiest->nr_running;
+ env.load_move = imbalance;
+ env.src_cpu = busiest->cpu;
+ env.src_rq = busiest;
+ env.loop_max = min_t(unsigned long, sysctl_sched_nr_migrate, busiest->nr_running);
more_balance:
local_irq_save(flags);
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index e61fd73..de00a48 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -68,3 +68,4 @@
SCHED_FEAT(FORCE_SD_OVERLAP, false)
SCHED_FEAT(RT_RUNTIME_SHARE, true)
+SCHED_FEAT(LB_MIN, false)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 52b3a06..4ab1187 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -170,7 +170,7 @@
#endif
#ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
@@ -703,7 +703,7 @@
.data = &dmesg_restrict,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
.extra1 = &zero,
.extra2 = &one,
},
@@ -712,7 +712,7 @@
.data = &kptr_restrict,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dmesg_restrict,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
.extra1 = &zero,
.extra2 = &two,
},
@@ -1943,7 +1943,7 @@
}
#ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
if (write && !capable(CAP_SYS_ADMIN))
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index 2cf9cc7..a20dc8a 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -1,6 +1,10 @@
#
# Timer subsystem related configuration options
#
+
+# Core internal switch. Selected by NO_HZ / HIGH_RES_TIMERS. This is
+# only related to the tick functionality. Oneshot clockevent devices
+# are supported independ of this.
config TICK_ONESHOT
bool
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index e883f57..f113755 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -346,7 +346,8 @@
tick_get_broadcast_mask());
break;
case TICKDEV_MODE_ONESHOT:
- broadcast = tick_resume_broadcast_oneshot(bc);
+ if (!cpumask_empty(tick_get_broadcast_mask()))
+ broadcast = tick_resume_broadcast_oneshot(bc);
break;
}
}
@@ -373,6 +374,9 @@
{
struct clock_event_device *bc = tick_broadcast_device.evtdev;
+ if (bc->mode != CLOCK_EVT_MODE_ONESHOT)
+ clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
+
return clockevents_program_event(bc, expires, force);
}
@@ -531,7 +535,6 @@
int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC;
bc->event_handler = tick_handle_oneshot_broadcast;
- clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
/* Take the do_timer update */
tick_do_timer_cpu = cpu;
@@ -549,6 +552,7 @@
to_cpumask(tmpmask));
if (was_periodic && !cpumask_empty(to_cpumask(tmpmask))) {
+ clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT);
tick_broadcast_init_next_event(to_cpumask(tmpmask),
tick_next_period);
tick_broadcast_set_event(tick_next_period, 1);
@@ -575,15 +579,12 @@
unsigned long flags;
raw_spin_lock_irqsave(&tick_broadcast_lock, flags);
- if (cpumask_empty(tick_get_broadcast_mask()))
- goto end;
tick_broadcast_device.mode = TICKDEV_MODE_ONESHOT;
bc = tick_broadcast_device.evtdev;
if (bc)
tick_broadcast_setup_oneshot(bc);
-end:
raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
}
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 3526038..6a3a5b9 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -534,9 +534,9 @@
hrtimer_get_expires(&ts->sched_timer), 0))
break;
}
- /* Update jiffies and reread time */
- tick_do_update_jiffies64(now);
+ /* Reread time and update jiffies */
now = ktime_get();
+ tick_do_update_jiffies64(now);
}
}
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index cdea7b5..c0bd030 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -311,13 +311,6 @@
}
EXPORT_SYMBOL_GPL(blk_trace_remove);
-static int blk_dropped_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t blk_dropped_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -331,18 +324,11 @@
static const struct file_operations blk_dropped_fops = {
.owner = THIS_MODULE,
- .open = blk_dropped_open,
+ .open = simple_open,
.read = blk_dropped_read,
.llseek = default_llseek,
};
-static int blk_msg_open(struct inode *inode, struct file *filp)
-{
- filp->private_data = inode->i_private;
-
- return 0;
-}
-
static ssize_t blk_msg_write(struct file *filp, const char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -371,7 +357,7 @@
static const struct file_operations blk_msg_fops = {
.owner = THIS_MODULE,
- .open = blk_msg_open,
+ .open = simple_open,
.write = blk_msg_write,
.llseek = noop_llseek,
};
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ed7b5d1..2a22255 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4629,7 +4629,8 @@
rb_simple_read(struct file *filp, char __user *ubuf,
size_t cnt, loff_t *ppos)
{
- struct ring_buffer *buffer = filp->private_data;
+ struct trace_array *tr = filp->private_data;
+ struct ring_buffer *buffer = tr->buffer;
char buf[64];
int r;
@@ -4647,7 +4648,8 @@
rb_simple_write(struct file *filp, const char __user *ubuf,
size_t cnt, loff_t *ppos)
{
- struct ring_buffer *buffer = filp->private_data;
+ struct trace_array *tr = filp->private_data;
+ struct ring_buffer *buffer = tr->buffer;
unsigned long val;
int ret;
@@ -4734,7 +4736,7 @@
&trace_clock_fops);
trace_create_file("tracing_on", 0644, d_tracer,
- global_trace.buffer, &rb_simple_fops);
+ &global_trace, &rb_simple_fops);
#ifdef CONFIG_DYNAMIC_FTRACE
trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 95059f0..f95d65d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -836,11 +836,11 @@
filter)
#include "trace_entries.h"
-#ifdef CONFIG_FUNCTION_TRACER
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_FUNCTION_TRACER)
int perf_ftrace_event_register(struct ftrace_event_call *call,
enum trace_reg type, void *data);
#else
#define perf_ftrace_event_register NULL
-#endif /* CONFIG_FUNCTION_TRACER */
+#endif
#endif /* _LINUX_KERNEL_TRACE_H */
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index 859fae6b..df611a0 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -652,6 +652,8 @@
{
u64 next_ts;
int ret;
+ /* trace_find_next_entry will reset ent_size */
+ int ent_size = iter->ent_size;
struct trace_seq *s = &iter->seq;
struct trace_entry *entry = iter->ent,
*next_entry = trace_find_next_entry(iter, NULL,
@@ -660,6 +662,9 @@
unsigned long abs_usecs = ns2usecs(iter->ts - iter->tr->time_start);
unsigned long rel_usecs;
+ /* Restore the original ent_size */
+ iter->ent_size = ent_size;
+
if (!next_entry)
next_ts = iter->ts;
rel_usecs = ns2usecs(next_ts - iter->ts);
diff --git a/lib/kobject.c b/lib/kobject.c
index 21dee7c..aeefa8b 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -192,14 +192,14 @@
/* be noisy on error issues */
if (error == -EEXIST)
- printk(KERN_ERR "%s failed for %s with "
- "-EEXIST, don't try to register things with "
- "the same name in the same directory.\n",
- __func__, kobject_name(kobj));
+ WARN(1, "%s failed for %s with "
+ "-EEXIST, don't try to register things with "
+ "the same name in the same directory.\n",
+ __func__, kobject_name(kobj));
else
- printk(KERN_ERR "%s failed for %s (%d)\n",
- __func__, kobject_name(kobj), error);
- dump_stack();
+ WARN(1, "%s failed for %s (error: %d parent: %s)\n",
+ __func__, kobject_name(kobj), error,
+ parent ? kobject_name(parent) : "'none'");
} else
kobj->state_in_sysfs = 1;
diff --git a/lib/mpi/mpi-bit.c b/lib/mpi/mpi-bit.c
index 2f52662..0c50536 100644
--- a/lib/mpi/mpi-bit.c
+++ b/lib/mpi/mpi-bit.c
@@ -177,8 +177,8 @@
*/
int mpi_lshift_limbs(MPI a, unsigned int count)
{
- mpi_ptr_t ap = a->d;
- int n = a->nlimbs;
+ const int n = a->nlimbs;
+ mpi_ptr_t ap;
int i;
if (!count || !n)
@@ -187,6 +187,7 @@
if (RESIZE_IF_NEEDED(a, n + count) < 0)
return -ENOMEM;
+ ap = a->d;
for (i = n - 1; i >= 0; i--)
ap[i + count] = ap[i];
for (i = 0; i < count; i++)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index b8ce6f4..5a16423 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -532,7 +532,7 @@
struct vm_area_struct *vma,
unsigned long address, int avoid_reserve)
{
- struct page *page;
+ struct page *page = NULL;
struct mempolicy *mpol;
nodemask_t *nodemask;
struct zonelist *zonelist;
@@ -2791,6 +2791,7 @@
* so no worry about deadlock.
*/
page = pte_page(entry);
+ get_page(page);
if (page != pagecache_page)
lock_page(page);
@@ -2822,6 +2823,7 @@
}
if (page != pagecache_page)
unlock_page(page);
+ put_page(page);
out_mutex:
mutex_unlock(&hugetlb_instantiation_mutex);
diff --git a/mm/memblock.c b/mm/memblock.c
index 99f2855..a44eab3 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -330,6 +330,9 @@
phys_addr_t end = base + memblock_cap_size(base, &size);
int i, nr_new;
+ if (!size)
+ return 0;
+
/* special case for empty array */
if (type->regions[0].size == 0) {
WARN_ON(type->cnt != 1 || type->total_size);
@@ -430,6 +433,9 @@
*start_rgn = *end_rgn = 0;
+ if (!size)
+ return 0;
+
/* we'll create at most two more regions */
while (type->cnt + 2 > type->max)
if (memblock_double_array(type) < 0)
@@ -514,7 +520,6 @@
(unsigned long long)base,
(unsigned long long)base + size,
(void *)_RET_IP_);
- BUG_ON(0 == size);
return memblock_add_region(_rgn, base, size, MAX_NUMNODES);
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 7d698df..31ab9c3 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2165,7 +2165,7 @@
if (action == CPU_ONLINE)
return NOTIFY_OK;
- if ((action != CPU_DEAD) || action != CPU_DEAD_FROZEN)
+ if (action != CPU_DEAD && action != CPU_DEAD_FROZEN)
return NOTIFY_OK;
for_each_mem_cgroup(iter)
@@ -2476,10 +2476,10 @@
static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg,
struct page *page,
unsigned int nr_pages,
- struct page_cgroup *pc,
enum charge_type ctype,
bool lrucare)
{
+ struct page_cgroup *pc = lookup_page_cgroup(page);
struct zone *uninitialized_var(zone);
bool was_on_lru = false;
bool anon;
@@ -2716,7 +2716,6 @@
{
struct mem_cgroup *memcg = NULL;
unsigned int nr_pages = 1;
- struct page_cgroup *pc;
bool oom = true;
int ret;
@@ -2730,11 +2729,10 @@
oom = false;
}
- pc = lookup_page_cgroup(page);
ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom);
if (ret == -ENOMEM)
return ret;
- __mem_cgroup_commit_charge(memcg, page, nr_pages, pc, ctype, false);
+ __mem_cgroup_commit_charge(memcg, page, nr_pages, ctype, false);
return 0;
}
@@ -2831,16 +2829,13 @@
__mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg,
enum charge_type ctype)
{
- struct page_cgroup *pc;
-
if (mem_cgroup_disabled())
return;
if (!memcg)
return;
cgroup_exclude_rmdir(&memcg->css);
- pc = lookup_page_cgroup(page);
- __mem_cgroup_commit_charge(memcg, page, 1, pc, ctype, true);
+ __mem_cgroup_commit_charge(memcg, page, 1, ctype, true);
/*
* Now swap is on-memory. This means this page may be
* counted both as mem and swap....double count.
@@ -3298,14 +3293,13 @@
* page. In the case new page is migrated but not remapped, new page's
* mapcount will be finally 0 and we call uncharge in end_migration().
*/
- pc = lookup_page_cgroup(newpage);
if (PageAnon(page))
ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
else if (page_is_file_cache(page))
ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
else
ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
- __mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype, false);
+ __mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false);
return ret;
}
@@ -3392,7 +3386,7 @@
* the newpage may be on LRU(or pagevec for LRU) already. We lock
* LRU while we overwrite pc->mem_cgroup.
*/
- __mem_cgroup_commit_charge(memcg, newpage, 1, pc, type, true);
+ __mem_cgroup_commit_charge(memcg, newpage, 1, type, true);
}
#ifdef CONFIG_DEBUG_VM
@@ -3763,7 +3757,7 @@
goto try_to_free;
cond_resched();
/* "ret" should also be checked to ensure all lists are empty. */
- } while (memcg->res.usage > 0 || ret);
+ } while (res_counter_read_u64(&memcg->res, RES_USAGE) > 0 || ret);
out:
css_put(&memcg->css);
return ret;
@@ -3778,7 +3772,7 @@
lru_add_drain_all();
/* try to free all pages in this cgroup */
shrink = 1;
- while (nr_retries && memcg->res.usage > 0) {
+ while (nr_retries && res_counter_read_u64(&memcg->res, RES_USAGE) > 0) {
int progress;
if (signal_pending(current)) {
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index cfb6c86..b195691 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1361,11 +1361,14 @@
mm = get_task_mm(task);
put_task_struct(task);
- if (mm)
- err = do_migrate_pages(mm, old, new,
- capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
- else
+
+ if (!mm) {
err = -EINVAL;
+ goto out;
+ }
+
+ err = do_migrate_pages(mm, old, new,
+ capable(CAP_SYS_NICE) ? MPOL_MF_MOVE_ALL : MPOL_MF_MOVE);
mmput(mm);
out:
diff --git a/mm/migrate.c b/mm/migrate.c
index 51c08a0..1107238 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1388,14 +1388,14 @@
mm = get_task_mm(task);
put_task_struct(task);
- if (mm) {
- if (nodes)
- err = do_pages_move(mm, task_nodes, nr_pages, pages,
- nodes, status, flags);
- else
- err = do_pages_stat(mm, nr_pages, pages, status);
- } else
- err = -EINVAL;
+ if (!mm)
+ return -EINVAL;
+
+ if (nodes)
+ err = do_pages_move(mm, task_nodes, nr_pages, pages,
+ nodes, status, flags);
+ else
+ err = do_pages_stat(mm, nr_pages, pages, status);
mmput(mm);
return err;
diff --git a/mm/mmap.c b/mm/mmap.c
index a7bf6a3..848ef52 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -240,6 +240,8 @@
return next;
}
+static unsigned long do_brk(unsigned long addr, unsigned long len);
+
SYSCALL_DEFINE1(brk, unsigned long, brk)
{
unsigned long rlim, retval;
@@ -951,7 +953,7 @@
* The caller must hold down_write(¤t->mm->mmap_sem).
*/
-unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
+static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flags, unsigned long pgoff)
{
@@ -1087,7 +1089,32 @@
return mmap_region(file, addr, len, flags, vm_flags, pgoff);
}
-EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long do_mmap(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long offset)
+{
+ if (unlikely(offset + PAGE_ALIGN(len) < offset))
+ return -EINVAL;
+ if (unlikely(offset & ~PAGE_MASK))
+ return -EINVAL;
+ return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(do_mmap);
+
+unsigned long vm_mmap(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long offset)
+{
+ unsigned long ret;
+ struct mm_struct *mm = current->mm;
+
+ down_write(&mm->mmap_sem);
+ ret = do_mmap(file, addr, len, prot, flag, offset);
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+EXPORT_SYMBOL(vm_mmap);
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
@@ -2105,21 +2132,25 @@
return 0;
}
-
EXPORT_SYMBOL(do_munmap);
-SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+int vm_munmap(unsigned long start, size_t len)
{
int ret;
struct mm_struct *mm = current->mm;
- profile_munmap(addr);
-
down_write(&mm->mmap_sem);
- ret = do_munmap(mm, addr, len);
+ ret = do_munmap(mm, start, len);
up_write(&mm->mmap_sem);
return ret;
}
+EXPORT_SYMBOL(vm_munmap);
+
+SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+{
+ profile_munmap(addr);
+ return vm_munmap(addr, len);
+}
static inline void verify_mm_writelocked(struct mm_struct *mm)
{
@@ -2136,7 +2167,7 @@
* anonymous maps. eventually we may be able to do some
* brk-specific accounting here.
*/
-unsigned long do_brk(unsigned long addr, unsigned long len)
+static unsigned long do_brk(unsigned long addr, unsigned long len)
{
struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev;
@@ -2232,7 +2263,17 @@
return addr;
}
-EXPORT_SYMBOL(do_brk);
+unsigned long vm_brk(unsigned long addr, unsigned long len)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long ret;
+
+ down_write(&mm->mmap_sem);
+ ret = do_brk(addr, len);
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+EXPORT_SYMBOL(vm_brk);
/* Release all mmaps. */
void exit_mmap(struct mm_struct *mm)
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index 24f0fc1..e53bb8a 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -298,13 +298,19 @@
if (WARN_ON_ONCE(slab_is_available()))
return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id);
+again:
ptr = __alloc_memory_core_early(pgdat->node_id, size, align,
goal, -1ULL);
if (ptr)
return ptr;
- return __alloc_memory_core_early(MAX_NUMNODES, size, align,
- goal, -1ULL);
+ ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align,
+ goal, -1ULL);
+ if (!ptr && goal) {
+ goal = 0;
+ goto again;
+ }
+ return ptr;
}
void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size,
diff --git a/mm/nommu.c b/mm/nommu.c
index f59e170..bb8f4f0 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1233,7 +1233,7 @@
/*
* handle mapping creation for uClinux
*/
-unsigned long do_mmap_pgoff(struct file *file,
+static unsigned long do_mmap_pgoff(struct file *file,
unsigned long addr,
unsigned long len,
unsigned long prot,
@@ -1470,7 +1470,32 @@
show_free_areas(0);
return -ENOMEM;
}
-EXPORT_SYMBOL(do_mmap_pgoff);
+
+unsigned long do_mmap(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long offset)
+{
+ if (unlikely(offset + PAGE_ALIGN(len) < offset))
+ return -EINVAL;
+ if (unlikely(offset & ~PAGE_MASK))
+ return -EINVAL;
+ return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+}
+EXPORT_SYMBOL(do_mmap);
+
+unsigned long vm_mmap(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flag, unsigned long offset)
+{
+ unsigned long ret;
+ struct mm_struct *mm = current->mm;
+
+ down_write(&mm->mmap_sem);
+ ret = do_mmap(file, addr, len, prot, flag, offset);
+ up_write(&mm->mmap_sem);
+ return ret;
+}
+EXPORT_SYMBOL(vm_mmap);
SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
unsigned long, prot, unsigned long, flags,
@@ -1709,16 +1734,22 @@
}
EXPORT_SYMBOL(do_munmap);
-SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+int vm_munmap(unsigned long addr, size_t len)
{
- int ret;
struct mm_struct *mm = current->mm;
+ int ret;
down_write(&mm->mmap_sem);
ret = do_munmap(mm, addr, len);
up_write(&mm->mmap_sem);
return ret;
}
+EXPORT_SYMBOL(vm_munmap);
+
+SYSCALL_DEFINE2(munmap, unsigned long, addr, size_t, len)
+{
+ return vm_munmap(addr, len);
+}
/*
* release all the mappings made in a process's VM space
@@ -1744,7 +1775,7 @@
kleave("");
}
-unsigned long do_brk(unsigned long addr, unsigned long len)
+unsigned long vm_brk(unsigned long addr, unsigned long len)
{
return -ENOMEM;
}
diff --git a/mm/percpu.c b/mm/percpu.c
index f47af91..f921fdf 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1132,20 +1132,20 @@
for (alloc_end += gi->nr_units / upa;
alloc < alloc_end; alloc++) {
if (!(alloc % apl)) {
- printk("\n");
+ printk(KERN_CONT "\n");
printk("%spcpu-alloc: ", lvl);
}
- printk("[%0*d] ", group_width, group);
+ printk(KERN_CONT "[%0*d] ", group_width, group);
for (unit_end += upa; unit < unit_end; unit++)
if (gi->cpu_map[unit] != NR_CPUS)
- printk("%0*d ", cpu_width,
+ printk(KERN_CONT "%0*d ", cpu_width,
gi->cpu_map[unit]);
else
- printk("%s ", empty_str);
+ printk(KERN_CONT "%s ", empty_str);
}
}
- printk("\n");
+ printk(KERN_CONT "\n");
}
/**
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 9d3dd37..4c5ff7f 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -26,7 +26,7 @@
*/
static const struct address_space_operations swap_aops = {
.writepage = swap_writepage,
- .set_page_dirty = __set_page_dirty_nobuffers,
+ .set_page_dirty = __set_page_dirty_no_writeback,
.migratepage = migrate_page,
};
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 33c332b..33dc256 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1568,9 +1568,14 @@
reclaim_stat->recent_scanned[0] += nr_anon;
reclaim_stat->recent_scanned[1] += nr_file;
- if (current_is_kswapd())
- __count_vm_events(KSWAPD_STEAL, nr_reclaimed);
- __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed);
+ if (global_reclaim(sc)) {
+ if (current_is_kswapd())
+ __count_zone_vm_events(PGSTEAL_KSWAPD, zone,
+ nr_reclaimed);
+ else
+ __count_zone_vm_events(PGSTEAL_DIRECT, zone,
+ nr_reclaimed);
+ }
putback_inactive_pages(mz, &page_list);
@@ -2107,12 +2112,7 @@
* with multiple processes reclaiming pages, the total
* freeing target can get unreasonably large.
*/
- if (nr_reclaimed >= nr_to_reclaim)
- nr_to_reclaim = 0;
- else
- nr_to_reclaim -= nr_reclaimed;
-
- if (!nr_to_reclaim && priority < DEF_PRIORITY)
+ if (nr_reclaimed >= nr_to_reclaim && priority < DEF_PRIORITY)
break;
}
blk_finish_plug(&plug);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index f600557..7db1b9b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -738,7 +738,8 @@
"pgmajfault",
TEXTS_FOR_ZONES("pgrefill")
- TEXTS_FOR_ZONES("pgsteal")
+ TEXTS_FOR_ZONES("pgsteal_kswapd")
+ TEXTS_FOR_ZONES("pgsteal_direct")
TEXTS_FOR_ZONES("pgscan_kswapd")
TEXTS_FOR_ZONES("pgscan_direct")
@@ -747,7 +748,6 @@
#endif
"pginodesteal",
"slabs_scanned",
- "kswapd_steal",
"kswapd_inodesteal",
"kswapd_low_wmark_hit_quickly",
"kswapd_high_wmark_hit_quickly",
diff --git a/net/802/garp.c b/net/802/garp.c
index 8e21b6d..a5c2248 100644
--- a/net/802/garp.c
+++ b/net/802/garp.c
@@ -167,7 +167,8 @@
return NULL;
}
-static void garp_attr_insert(struct garp_applicant *app, struct garp_attr *new)
+static struct garp_attr *garp_attr_create(struct garp_applicant *app,
+ const void *data, u8 len, u8 type)
{
struct rb_node *parent = NULL, **p = &app->gid.rb_node;
struct garp_attr *attr;
@@ -176,21 +177,16 @@
while (*p) {
parent = *p;
attr = rb_entry(parent, struct garp_attr, node);
- d = garp_attr_cmp(attr, new->data, new->dlen, new->type);
+ d = garp_attr_cmp(attr, data, len, type);
if (d < 0)
p = &parent->rb_left;
else if (d > 0)
p = &parent->rb_right;
+ else {
+ /* The attribute already exists; re-use it. */
+ return attr;
+ }
}
- rb_link_node(&new->node, parent, p);
- rb_insert_color(&new->node, &app->gid);
-}
-
-static struct garp_attr *garp_attr_create(struct garp_applicant *app,
- const void *data, u8 len, u8 type)
-{
- struct garp_attr *attr;
-
attr = kmalloc(sizeof(*attr) + len, GFP_ATOMIC);
if (!attr)
return attr;
@@ -198,7 +194,9 @@
attr->type = type;
attr->dlen = len;
memcpy(attr->data, data, len);
- garp_attr_insert(app, attr);
+
+ rb_link_node(&attr->node, parent, p);
+ rb_insert_color(&attr->node, &app->gid);
return attr;
}
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 0906c19..9d9a6a3 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -2011,16 +2011,17 @@
proc_net_remove(&init_net, "ax25_route");
proc_net_remove(&init_net, "ax25");
proc_net_remove(&init_net, "ax25_calls");
- ax25_rt_free();
- ax25_uid_free();
- ax25_dev_free();
- ax25_unregister_sysctl();
unregister_netdevice_notifier(&ax25_dev_notifier);
+ ax25_unregister_sysctl();
dev_remove_pack(&ax25_packet_type);
sock_unregister(PF_AX25);
proto_unregister(&ax25_proto);
+
+ ax25_rt_free();
+ ax25_uid_free();
+ ax25_dev_free();
}
module_exit(ax25_exit);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index e33af63..edfd61a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -665,6 +665,11 @@
hci_req_lock(hdev);
+ if (test_bit(HCI_UNREGISTER, &hdev->dev_flags)) {
+ ret = -ENODEV;
+ goto done;
+ }
+
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
@@ -1210,40 +1215,40 @@
return NULL;
}
-static int hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
+static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn,
u8 key_type, u8 old_key_type)
{
/* Legacy key */
if (key_type < 0x03)
- return 1;
+ return true;
/* Debug keys are insecure so don't store them persistently */
if (key_type == HCI_LK_DEBUG_COMBINATION)
- return 0;
+ return false;
/* Changed combination key and there's no previous one */
if (key_type == HCI_LK_CHANGED_COMBINATION && old_key_type == 0xff)
- return 0;
+ return false;
/* Security mode 3 case */
if (!conn)
- return 1;
+ return true;
/* Neither local nor remote side had no-bonding as requirement */
if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
- return 1;
+ return true;
/* Local side had dedicated bonding as requirement */
if (conn->auth_type == 0x02 || conn->auth_type == 0x03)
- return 1;
+ return true;
/* Remote side had dedicated bonding as requirement */
if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03)
- return 1;
+ return true;
/* If none of the above criteria match, then don't store the key
* persistently */
- return 0;
+ return false;
}
struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8])
@@ -1280,7 +1285,8 @@
bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len)
{
struct link_key *key, *old_key;
- u8 old_key_type, persistent;
+ u8 old_key_type;
+ bool persistent;
old_key = hci_find_link_key(hdev, bdaddr);
if (old_key) {
@@ -1323,10 +1329,8 @@
mgmt_new_link_key(hdev, key, persistent);
- if (!persistent) {
- list_del(&key->list);
- kfree(key);
- }
+ if (conn)
+ conn->flush_key = !persistent;
return 0;
}
@@ -1849,6 +1853,8 @@
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
+ set_bit(HCI_UNREGISTER, &hdev->dev_flags);
+
write_lock(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock(&hci_dev_list_lock);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index b375310..6c06525 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1901,6 +1901,8 @@
}
if (ev->status == 0) {
+ if (conn->type == ACL_LINK && conn->flush_key)
+ hci_remove_link_key(hdev, &conn->dst);
hci_proto_disconn_cfm(conn, ev->reason);
hci_conn_del(conn);
}
@@ -2311,6 +2313,7 @@
case HCI_OP_USER_PASSKEY_NEG_REPLY:
hci_cc_user_passkey_neg_reply(hdev, skb);
+ break;
case HCI_OP_LE_SET_SCAN_PARAM:
hci_cc_le_set_scan_param(hdev, skb);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index b8e17e4..94552b3 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1308,6 +1308,7 @@
if (chan->retry_count >= chan->remote_max_tx) {
l2cap_send_disconn_req(chan->conn, chan, ECONNABORTED);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
return;
}
@@ -1316,6 +1317,7 @@
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
}
static void l2cap_retrans_timeout(struct work_struct *work)
@@ -1335,6 +1337,7 @@
l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
l2cap_chan_unlock(chan);
+ l2cap_chan_put(chan);
}
static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index c4fe583..29122ed 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -82,7 +82,7 @@
}
if (la.l2_cid)
- err = l2cap_add_scid(chan, la.l2_cid);
+ err = l2cap_add_scid(chan, __le16_to_cpu(la.l2_cid));
else
err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm);
@@ -123,7 +123,8 @@
if (la.l2_cid && la.l2_psm)
return -EINVAL;
- err = l2cap_chan_connect(chan, la.l2_psm, la.l2_cid, &la.l2_bdaddr);
+ err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
+ &la.l2_bdaddr);
if (err)
return err;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7fcff88..4bb03b1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2523,13 +2523,18 @@
if (cp->val) {
type = PAGE_SCAN_TYPE_INTERLACED;
- acp.interval = 0x0024; /* 22.5 msec page scan interval */
+
+ /* 22.5 msec page scan interval */
+ acp.interval = __constant_cpu_to_le16(0x0024);
} else {
type = PAGE_SCAN_TYPE_STANDARD; /* default */
- acp.interval = 0x0800; /* default 1.28 sec page scan */
+
+ /* default 1.28 sec page scan */
+ acp.interval = __constant_cpu_to_le16(0x0800);
}
- acp.window = 0x0012; /* default 11.25 msec page scan window */
+ /* default 11.25 msec page scan window */
+ acp.window = __constant_cpu_to_le16(0x0012);
err = hci_send_cmd(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp),
&acp);
@@ -2879,7 +2884,7 @@
return 0;
}
-int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, u8 persistent)
+int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent)
{
struct mgmt_ev_new_link_key ev;
@@ -2936,7 +2941,7 @@
name, name_len);
if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
- eir_len = eir_append_data(&ev->eir[eir_len], eir_len,
+ eir_len = eir_append_data(ev->eir, eir_len,
EIR_CLASS_OF_DEV, dev_class, 3);
put_unaligned_le16(eir_len, &ev->eir_len);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 61f6534..a2098e3 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -47,6 +47,7 @@
kfree_skb(skb);
} else {
skb_push(skb, ETH_HLEN);
+ br_drop_fake_rtable(skb);
dev_queue_xmit(skb);
}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 702a1ae..27ca25e 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -241,7 +241,6 @@
hlist_del_rcu(&mp->hlist[mdb->ver]);
mdb->size--;
- del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group);
out:
@@ -271,7 +270,6 @@
rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist);
del_timer(&p->timer);
- del_timer(&p->query_timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg);
if (!mp->ports && !mp->mglist &&
@@ -507,74 +505,6 @@
return NULL;
}
-static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp)
-{
- struct net_bridge *br = mp->br;
- struct sk_buff *skb;
-
- skb = br_multicast_alloc_query(br, &mp->addr);
- if (!skb)
- goto timer;
-
- netif_rx(skb);
-
-timer:
- if (++mp->queries_sent < br->multicast_last_member_count)
- mod_timer(&mp->query_timer,
- jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_group_query_expired(unsigned long data)
-{
- struct net_bridge_mdb_entry *mp = (void *)data;
- struct net_bridge *br = mp->br;
-
- spin_lock(&br->multicast_lock);
- if (!netif_running(br->dev) || !mp->mglist ||
- mp->queries_sent >= br->multicast_last_member_count)
- goto out;
-
- br_multicast_send_group_query(mp);
-
-out:
- spin_unlock(&br->multicast_lock);
-}
-
-static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg)
-{
- struct net_bridge_port *port = pg->port;
- struct net_bridge *br = port->br;
- struct sk_buff *skb;
-
- skb = br_multicast_alloc_query(br, &pg->addr);
- if (!skb)
- goto timer;
-
- br_deliver(port, skb);
-
-timer:
- if (++pg->queries_sent < br->multicast_last_member_count)
- mod_timer(&pg->query_timer,
- jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_port_group_query_expired(unsigned long data)
-{
- struct net_bridge_port_group *pg = (void *)data;
- struct net_bridge_port *port = pg->port;
- struct net_bridge *br = port->br;
-
- spin_lock(&br->multicast_lock);
- if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) ||
- pg->queries_sent >= br->multicast_last_member_count)
- goto out;
-
- br_multicast_send_port_group_query(pg);
-
-out:
- spin_unlock(&br->multicast_lock);
-}
-
static struct net_bridge_mdb_entry *br_multicast_get_group(
struct net_bridge *br, struct net_bridge_port *port,
struct br_ip *group, int hash)
@@ -690,8 +620,6 @@
mp->addr = *group;
setup_timer(&mp->timer, br_multicast_group_expired,
(unsigned long)mp);
- setup_timer(&mp->query_timer, br_multicast_group_query_expired,
- (unsigned long)mp);
hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
mdb->size++;
@@ -746,8 +674,6 @@
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
- setup_timer(&p->query_timer, br_multicast_port_group_query_expired,
- (unsigned long)p);
rcu_assign_pointer(*pp, p);
@@ -1291,9 +1217,6 @@
time_after(mp->timer.expires, time) :
try_to_del_timer_sync(&mp->timer) >= 0)) {
mod_timer(&mp->timer, time);
-
- mp->queries_sent = 0;
- mod_timer(&mp->query_timer, now);
}
goto out;
@@ -1310,9 +1233,6 @@
time_after(p->timer.expires, time) :
try_to_del_timer_sync(&p->timer) >= 0)) {
mod_timer(&p->timer, time);
-
- p->queries_sent = 0;
- mod_timer(&p->query_timer, now);
}
break;
@@ -1681,7 +1601,6 @@
hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i],
hlist[ver]) {
del_timer(&mp->timer);
- del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group);
}
}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index dec4f38..d7f49b6 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -156,7 +156,7 @@
rt->dst.dev = br->dev;
rt->dst.path = &rt->dst;
dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
- rt->dst.flags = DST_NOXFRM | DST_NOPEER;
+ rt->dst.flags = DST_NOXFRM | DST_NOPEER | DST_FAKE_RTABLE;
rt->dst.ops = &fake_dst_ops;
}
@@ -694,11 +694,7 @@
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
- struct rtable *rt = skb_rtable(skb);
-
- if (rt && rt == bridge_parent_rtable(in))
- skb_dst_drop(skb);
-
+ br_drop_fake_rtable(skb);
return NF_ACCEPT;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0b67a63..e1d8822 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -82,9 +82,7 @@
struct hlist_node mglist;
struct rcu_head rcu;
struct timer_list timer;
- struct timer_list query_timer;
struct br_ip addr;
- u32 queries_sent;
};
struct net_bridge_mdb_entry
@@ -94,10 +92,8 @@
struct net_bridge_port_group __rcu *ports;
struct rcu_head rcu;
struct timer_list timer;
- struct timer_list query_timer;
struct br_ip addr;
bool mglist;
- u32 queries_sent;
};
struct net_bridge_mdb_htable
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c
index 20618dd..d09340e 100644
--- a/net/caif/chnl_net.c
+++ b/net/caif/chnl_net.c
@@ -103,6 +103,7 @@
skb->protocol = htons(ETH_P_IPV6);
break;
default:
+ kfree_skb(skb);
priv->netdev->stats.rx_errors++;
return -EINVAL;
}
@@ -220,14 +221,16 @@
if (skb->len > priv->netdev->mtu) {
pr_warn("Size of skb exceeded MTU\n");
+ kfree_skb(skb);
dev->stats.tx_errors++;
- return -ENOSPC;
+ return NETDEV_TX_OK;
}
if (!priv->flowenabled) {
pr_debug("dropping packets flow off\n");
+ kfree_skb(skb);
dev->stats.tx_dropped++;
- return NETDEV_TX_BUSY;
+ return NETDEV_TX_OK;
}
if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP)
@@ -242,7 +245,7 @@
result = priv->chnl.dn->transmit(priv->chnl.dn, pkt);
if (result) {
dev->stats.tx_dropped++;
- return result;
+ return NETDEV_TX_OK;
}
/* Update statistics. */
diff --git a/net/core/dev.c b/net/core/dev.c
index 5d59155..9bb8f87 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1409,14 +1409,34 @@
* register_netdevice_notifier(). The notifier is unlinked into the
* kernel structures and may then be reused. A negative errno code
* is returned on a failure.
+ *
+ * After unregistering unregister and down device events are synthesized
+ * for all devices on the device list to the removed notifier to remove
+ * the need for special case cleanup code.
*/
int unregister_netdevice_notifier(struct notifier_block *nb)
{
+ struct net_device *dev;
+ struct net *net;
int err;
rtnl_lock();
err = raw_notifier_chain_unregister(&netdev_chain, nb);
+ if (err)
+ goto unlock;
+
+ for_each_net(net) {
+ for_each_netdev(net, dev) {
+ if (dev->flags & IFF_UP) {
+ nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+ nb->notifier_call(nb, NETDEV_DOWN, dev);
+ }
+ nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+ nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
+ }
+ }
+unlock:
rtnl_unlock();
return err;
}
@@ -1596,6 +1616,7 @@
kfree_skb(skb);
return NET_RX_DROP;
}
+ skb->skb_iif = 0;
skb_set_dev(skb, dev);
skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
@@ -4027,54 +4048,41 @@
#ifdef CONFIG_PROC_FS
-#define BUCKET_SPACE (32 - NETDEV_HASHBITS)
-
-struct dev_iter_state {
- struct seq_net_private p;
- unsigned int pos; /* bucket << BUCKET_SPACE + offset */
-};
+#define BUCKET_SPACE (32 - NETDEV_HASHBITS - 1)
#define get_bucket(x) ((x) >> BUCKET_SPACE)
#define get_offset(x) ((x) & ((1 << BUCKET_SPACE) - 1))
#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o))
-static inline struct net_device *dev_from_same_bucket(struct seq_file *seq)
+static inline struct net_device *dev_from_same_bucket(struct seq_file *seq, loff_t *pos)
{
- struct dev_iter_state *state = seq->private;
struct net *net = seq_file_net(seq);
struct net_device *dev;
struct hlist_node *p;
struct hlist_head *h;
- unsigned int count, bucket, offset;
+ unsigned int count = 0, offset = get_offset(*pos);
- bucket = get_bucket(state->pos);
- offset = get_offset(state->pos);
- h = &net->dev_name_head[bucket];
- count = 0;
+ h = &net->dev_name_head[get_bucket(*pos)];
hlist_for_each_entry_rcu(dev, p, h, name_hlist) {
- if (count++ == offset) {
- state->pos = set_bucket_offset(bucket, count);
+ if (++count == offset)
return dev;
- }
}
return NULL;
}
-static inline struct net_device *dev_from_new_bucket(struct seq_file *seq)
+static inline struct net_device *dev_from_bucket(struct seq_file *seq, loff_t *pos)
{
- struct dev_iter_state *state = seq->private;
struct net_device *dev;
unsigned int bucket;
- bucket = get_bucket(state->pos);
do {
- dev = dev_from_same_bucket(seq);
+ dev = dev_from_same_bucket(seq, pos);
if (dev)
return dev;
- bucket++;
- state->pos = set_bucket_offset(bucket, 0);
+ bucket = get_bucket(*pos) + 1;
+ *pos = set_bucket_offset(bucket, 1);
} while (bucket < NETDEV_HASHENTRIES);
return NULL;
@@ -4087,33 +4095,20 @@
void *dev_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{
- struct dev_iter_state *state = seq->private;
-
rcu_read_lock();
if (!*pos)
return SEQ_START_TOKEN;
- /* check for end of the hash */
- if (state->pos == 0 && *pos > 1)
+ if (get_bucket(*pos) >= NETDEV_HASHENTRIES)
return NULL;
- return dev_from_new_bucket(seq);
+ return dev_from_bucket(seq, pos);
}
void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct net_device *dev;
-
++*pos;
-
- if (v == SEQ_START_TOKEN)
- return dev_from_new_bucket(seq);
-
- dev = dev_from_same_bucket(seq);
- if (dev)
- return dev;
-
- return dev_from_new_bucket(seq);
+ return dev_from_bucket(seq, pos);
}
void dev_seq_stop(struct seq_file *seq, void *v)
@@ -4212,13 +4207,7 @@
static int dev_seq_open(struct inode *inode, struct file *file)
{
return seq_open_net(inode, file, &dev_seq_ops,
- sizeof(struct dev_iter_state));
-}
-
-int dev_seq_open_ops(struct inode *inode, struct file *file,
- const struct seq_operations *ops)
-{
- return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
+ sizeof(struct seq_net_private));
}
static const struct file_operations dev_seq_fops = {
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 29c07fe..626698f 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -696,7 +696,8 @@
static int dev_mc_seq_open(struct inode *inode, struct file *file)
{
- return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
+ return seq_open_net(inode, file, &dev_mc_seq_ops,
+ sizeof(struct seq_net_private));
}
static const struct file_operations dev_mc_seq_fops = {
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
index 7f36b38..a7cad74 100644
--- a/net/core/drop_monitor.c
+++ b/net/core/drop_monitor.c
@@ -42,13 +42,14 @@
* netlink alerts
*/
static int trace_state = TRACE_OFF;
-static DEFINE_SPINLOCK(trace_state_lock);
+static DEFINE_MUTEX(trace_state_mutex);
struct per_cpu_dm_data {
struct work_struct dm_alert_work;
- struct sk_buff *skb;
+ struct sk_buff __rcu *skb;
atomic_t dm_hit_count;
struct timer_list send_timer;
+ int cpu;
};
struct dm_hw_stat_delta {
@@ -79,29 +80,53 @@
size_t al;
struct net_dm_alert_msg *msg;
struct nlattr *nla;
+ struct sk_buff *skb;
+ struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1);
al = sizeof(struct net_dm_alert_msg);
al += dm_hit_limit * sizeof(struct net_dm_drop_point);
al += sizeof(struct nlattr);
- data->skb = genlmsg_new(al, GFP_KERNEL);
- genlmsg_put(data->skb, 0, 0, &net_drop_monitor_family,
- 0, NET_DM_CMD_ALERT);
- nla = nla_reserve(data->skb, NLA_UNSPEC, sizeof(struct net_dm_alert_msg));
- msg = nla_data(nla);
- memset(msg, 0, al);
- atomic_set(&data->dm_hit_count, dm_hit_limit);
+ skb = genlmsg_new(al, GFP_KERNEL);
+
+ if (skb) {
+ genlmsg_put(skb, 0, 0, &net_drop_monitor_family,
+ 0, NET_DM_CMD_ALERT);
+ nla = nla_reserve(skb, NLA_UNSPEC,
+ sizeof(struct net_dm_alert_msg));
+ msg = nla_data(nla);
+ memset(msg, 0, al);
+ } else
+ schedule_work_on(data->cpu, &data->dm_alert_work);
+
+ /*
+ * Don't need to lock this, since we are guaranteed to only
+ * run this on a single cpu at a time.
+ * Note also that we only update data->skb if the old and new skb
+ * pointers don't match. This ensures that we don't continually call
+ * synchornize_rcu if we repeatedly fail to alloc a new netlink message.
+ */
+ if (skb != oskb) {
+ rcu_assign_pointer(data->skb, skb);
+
+ synchronize_rcu();
+
+ atomic_set(&data->dm_hit_count, dm_hit_limit);
+ }
+
}
static void send_dm_alert(struct work_struct *unused)
{
struct sk_buff *skb;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+
+ WARN_ON_ONCE(data->cpu != smp_processor_id());
/*
* Grab the skb we're about to send
*/
- skb = data->skb;
+ skb = rcu_dereference_protected(data->skb, 1);
/*
* Replace it with a new one
@@ -111,8 +136,10 @@
/*
* Ship it!
*/
- genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ if (skb)
+ genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL);
+ put_cpu_var(dm_cpu_data);
}
/*
@@ -123,9 +150,11 @@
*/
static void sched_send_work(unsigned long unused)
{
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
- schedule_work(&data->dm_alert_work);
+ schedule_work_on(smp_processor_id(), &data->dm_alert_work);
+
+ put_cpu_var(dm_cpu_data);
}
static void trace_drop_common(struct sk_buff *skb, void *location)
@@ -134,9 +163,16 @@
struct nlmsghdr *nlh;
struct nlattr *nla;
int i;
- struct per_cpu_dm_data *data = &__get_cpu_var(dm_cpu_data);
+ struct sk_buff *dskb;
+ struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data);
+ rcu_read_lock();
+ dskb = rcu_dereference(data->skb);
+
+ if (!dskb)
+ goto out;
+
if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) {
/*
* we're already at zero, discard this hit
@@ -144,12 +180,13 @@
goto out;
}
- nlh = (struct nlmsghdr *)data->skb->data;
+ nlh = (struct nlmsghdr *)dskb->data;
nla = genlmsg_data(nlmsg_data(nlh));
msg = nla_data(nla);
for (i = 0; i < msg->entries; i++) {
if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
msg->points[i].count++;
+ atomic_inc(&data->dm_hit_count);
goto out;
}
}
@@ -157,7 +194,7 @@
/*
* We need to create a new entry
*/
- __nla_reserve_nohdr(data->skb, sizeof(struct net_dm_drop_point));
+ __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
msg->points[msg->entries].count = 1;
@@ -169,6 +206,8 @@
}
out:
+ rcu_read_unlock();
+ put_cpu_var(dm_cpu_data);
return;
}
@@ -213,7 +252,7 @@
struct dm_hw_stat_delta *new_stat = NULL;
struct dm_hw_stat_delta *temp;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
if (state == trace_state) {
rc = -EAGAIN;
@@ -252,7 +291,7 @@
rc = -EINPROGRESS;
out_unlock:
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
return rc;
}
@@ -295,12 +334,12 @@
new_stat->dev = dev;
new_stat->last_rx = jiffies;
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_add_rcu(&new_stat->list, &hw_stats_list);
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
case NETDEV_UNREGISTER:
- spin_lock(&trace_state_lock);
+ mutex_lock(&trace_state_mutex);
list_for_each_entry_safe(new_stat, tmp, &hw_stats_list, list) {
if (new_stat->dev == dev) {
new_stat->dev = NULL;
@@ -311,7 +350,7 @@
}
}
}
- spin_unlock(&trace_state_lock);
+ mutex_unlock(&trace_state_mutex);
break;
}
out:
@@ -367,13 +406,15 @@
for_each_present_cpu(cpu) {
data = &per_cpu(dm_cpu_data, cpu);
- reset_per_cpu_data(data);
+ data->cpu = cpu;
INIT_WORK(&data->dm_alert_work, send_dm_alert);
init_timer(&data->send_timer);
data->send_timer.data = cpu;
data->send_timer.function = sched_send_work;
+ reset_per_cpu_data(data);
}
+
goto out;
out_unreg:
diff --git a/net/core/filter.c b/net/core/filter.c
index cf4989a..6f755cc 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -39,8 +39,11 @@
#include <linux/reciprocal_div.h>
#include <linux/ratelimit.h>
-/* No hurry in this branch */
-static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
+/* No hurry in this branch
+ *
+ * Exported for the bpf jit load helper.
+ */
+void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size)
{
u8 *ptr = NULL;
@@ -59,7 +62,7 @@
{
if (k >= 0)
return skb_header_pointer(skb, k, size, buffer);
- return __load_pointer(skb, k, size);
+ return bpf_internal_load_pointer_neg_helper(skb, k, size);
}
/**
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 0e950fd..31a5ae5 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -83,21 +83,29 @@
static int ops_init(const struct pernet_operations *ops, struct net *net)
{
- int err;
+ int err = -ENOMEM;
+ void *data = NULL;
+
if (ops->id && ops->size) {
- void *data = kzalloc(ops->size, GFP_KERNEL);
+ data = kzalloc(ops->size, GFP_KERNEL);
if (!data)
- return -ENOMEM;
+ goto out;
err = net_assign_generic(net, *ops->id, data);
- if (err) {
- kfree(data);
- return err;
- }
+ if (err)
+ goto cleanup;
}
+ err = 0;
if (ops->init)
- return ops->init(net);
- return 0;
+ err = ops->init(net);
+ if (!err)
+ return 0;
+
+cleanup:
+ kfree(data);
+
+out:
+ return err;
}
static void ops_free(const struct pernet_operations *ops, struct net *net)
@@ -448,12 +456,7 @@
static int __register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
{
- int err = 0;
- err = ops_init(ops, &init_net);
- if (err)
- ops_free(ops, &init_net);
- return err;
-
+ return ops_init(ops, &init_net);
}
static void __unregister_pernet_operations(struct pernet_operations *ops)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f223cdc..e598400 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -952,9 +952,11 @@
goto adjust_others;
}
- data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+ data = kmalloc(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
+ gfp_mask);
if (!data)
goto nodata;
+ size = SKB_WITH_OVERHEAD(ksize(data));
/* Copy only real data... and, alas, header. This should be
* optimized for the cases when header is void.
@@ -3161,6 +3163,8 @@
*/
int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{
+ int len = skb->len;
+
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned)sk->sk_rcvbuf)
return -ENOMEM;
@@ -3175,7 +3179,7 @@
skb_queue_tail(&sk->sk_error_queue, skb);
if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb->len);
+ sk->sk_data_ready(sk, len);
return 0;
}
EXPORT_SYMBOL(sock_queue_err_skb);
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 3685158..840821b 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1044,6 +1044,24 @@
free_netdev(dev);
}
+static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
+{
+ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+ return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
+}
+
+static u16 lowpan_get_pan_id(const struct net_device *dev)
+{
+ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+ return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev);
+}
+
+static u16 lowpan_get_short_addr(const struct net_device *dev)
+{
+ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+ return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev);
+}
+
static struct header_ops lowpan_header_ops = {
.create = lowpan_header_create,
};
@@ -1053,6 +1071,12 @@
.ndo_set_mac_address = eth_mac_addr,
};
+static struct ieee802154_mlme_ops lowpan_mlme = {
+ .get_pan_id = lowpan_get_pan_id,
+ .get_phy = lowpan_get_phy,
+ .get_short_addr = lowpan_get_short_addr,
+};
+
static void lowpan_setup(struct net_device *dev)
{
pr_debug("(%s)\n", __func__);
@@ -1070,6 +1094,7 @@
dev->netdev_ops = &lowpan_netdev_ops;
dev->header_ops = &lowpan_header_ops;
+ dev->ml_priv = &lowpan_mlme;
dev->destructor = lowpan_dev_free;
}
@@ -1143,6 +1168,8 @@
list_add_tail(&entry->list, &lowpan_devices);
mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
+ spin_lock_init(&flist_lock);
+
register_netdevice(dev);
return 0;
@@ -1152,11 +1179,20 @@
{
struct lowpan_dev_info *lowpan_dev = lowpan_dev_info(dev);
struct net_device *real_dev = lowpan_dev->real_dev;
- struct lowpan_dev_record *entry;
- struct lowpan_dev_record *tmp;
+ struct lowpan_dev_record *entry, *tmp;
+ struct lowpan_fragment *frame, *tframe;
ASSERT_RTNL();
+ spin_lock(&flist_lock);
+ list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) {
+ del_timer(&frame->timer);
+ list_del(&frame->list);
+ dev_kfree_skb(frame->skb);
+ kfree(frame);
+ }
+ spin_unlock(&flist_lock);
+
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
if (entry->ldev == dev) {
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 8d25a1c..8f8db72 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -141,7 +141,7 @@
goto rtattr_failure;
if (icsk == NULL) {
- r->idiag_rqueue = r->idiag_wqueue = 0;
+ handler->idiag_get_info(sk, r, NULL);
goto out;
}
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index de9da21..cf73cc7 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -74,16 +74,24 @@
iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
if (iph == NULL)
- return -NF_DROP;
+ return -NF_ACCEPT;
/* Conntrack defragments packets, we might still see fragments
* inside ICMP packets though. */
if (iph->frag_off & htons(IP_OFFSET))
- return -NF_DROP;
+ return -NF_ACCEPT;
*dataoff = nhoff + (iph->ihl << 2);
*protonum = iph->protocol;
+ /* Check bogus IP headers */
+ if (*dataoff > skb->len) {
+ pr_debug("nf_conntrack_ipv4: bogus IPv4 packet: "
+ "nhoff %u, ihl %u, skblen %u\n",
+ nhoff, iph->ihl << 2, skb->len);
+ return -NF_ACCEPT;
+ }
+
return NF_ACCEPT;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 4dc1c10..167ea10 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2041,7 +2041,7 @@
if (err < 0)
goto e_err;
}
- rth = rt_dst_alloc(init_net.loopback_dev,
+ rth = rt_dst_alloc(dev_net(dev)->loopback_dev,
IN_DEV_CONF_GET(in_dev, NOPOLICY), false);
if (!rth)
goto e_nobufs;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index cfd7edd..1272a88 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -701,11 +701,12 @@
skb = alloc_skb_fclone(size + sk->sk_prot->max_header, gfp);
if (skb) {
if (sk_wmem_schedule(sk, skb->truesize)) {
+ skb_reserve(skb, sk->sk_prot->max_header);
/*
* Make sure that we have exactly size bytes
* available to the caller, no more, no less.
*/
- skb_reserve(skb, skb_tailroom(skb) - size);
+ skb->avail_size = size;
return skb;
}
__kfree_skb(skb);
@@ -860,7 +861,7 @@
}
out:
- if (copied)
+ if (copied && !(flags & MSG_SENDPAGE_NOTLAST))
tcp_push(sk, flags, mss_now, tp->nonagle);
return copied;
@@ -995,10 +996,9 @@
copy = seglen;
/* Where to copy to? */
- if (skb_tailroom(skb) > 0) {
+ if (skb_availroom(skb) > 0) {
/* We have some space in skb head. Superb! */
- if (copy > skb_tailroom(skb))
- copy = skb_tailroom(skb);
+ copy = min_t(int, copy, skb_availroom(skb));
err = skb_add_data_nocache(sk, skb, from, copy);
if (err)
goto do_fault;
@@ -1452,7 +1452,7 @@
if ((available < target) &&
(len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
!sysctl_tcp_low_latency &&
- dma_find_channel(DMA_MEMCPY)) {
+ net_dma_find_channel()) {
preempt_enable_no_resched();
tp->ucopy.pinned_list =
dma_pin_iovec_pages(msg->msg_iov, len);
@@ -1667,7 +1667,7 @@
if (!(flags & MSG_TRUNC)) {
#ifdef CONFIG_NET_DMA
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
- tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+ tp->ucopy.dma_chan = net_dma_find_channel();
if (tp->ucopy.dma_chan) {
tp->ucopy.dma_cookie = dma_skb_copy_datagram_iovec(
@@ -3243,7 +3243,7 @@
{
struct sk_buff *skb = NULL;
unsigned long limit;
- int max_share, cnt;
+ int max_rshare, max_wshare, cnt;
unsigned int i;
unsigned long jiffy = jiffies;
@@ -3302,17 +3302,17 @@
tcp_init_mem(&init_net);
/* Set per-socket limits to no more than 1/128 the pressure threshold */
- limit = nr_free_buffer_pages() << (PAGE_SHIFT - 10);
- limit = max(limit, 128UL);
- max_share = min(4UL*1024*1024, limit);
+ limit = nr_free_buffer_pages() << (PAGE_SHIFT - 7);
+ max_wshare = min(4UL*1024*1024, limit);
+ max_rshare = min(6UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_wmem[1] = 16*1024;
- sysctl_tcp_wmem[2] = max(64*1024, max_share);
+ sysctl_tcp_wmem[2] = max(64*1024, max_wshare);
sysctl_tcp_rmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_rmem[1] = 87380;
- sysctl_tcp_rmem[2] = max(87380, max_share);
+ sysctl_tcp_rmem[2] = max(87380, max_rshare);
pr_info("Hash tables configured (established %u bind %u)\n",
tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index e886e2f..257b617 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -85,7 +85,7 @@
EXPORT_SYMBOL(sysctl_tcp_ecn);
int sysctl_tcp_dsack __read_mostly = 1;
int sysctl_tcp_app_win __read_mostly = 31;
-int sysctl_tcp_adv_win_scale __read_mostly = 2;
+int sysctl_tcp_adv_win_scale __read_mostly = 1;
EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
int sysctl_tcp_stdurg __read_mostly;
@@ -335,6 +335,7 @@
incr = __tcp_grow_window(sk, skb);
if (incr) {
+ incr = max_t(int, incr, 2 * skb->len);
tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr,
tp->window_clamp);
inet_csk(sk)->icsk_ack.quick |= 1;
@@ -474,8 +475,11 @@
if (!win_dep) {
m -= (new_sample >> 3);
new_sample += m;
- } else if (m < new_sample)
- new_sample = m << 3;
+ } else {
+ m <<= 3;
+ if (m < new_sample)
+ new_sample = m;
+ }
} else {
/* No previous measure. */
new_sample = m << 3;
@@ -491,7 +495,7 @@
goto new_measure;
if (before(tp->rcv_nxt, tp->rcv_rtt_est.seq))
return;
- tcp_rcv_rtt_update(tp, jiffies - tp->rcv_rtt_est.time, 1);
+ tcp_rcv_rtt_update(tp, tcp_time_stamp - tp->rcv_rtt_est.time, 1);
new_measure:
tp->rcv_rtt_est.seq = tp->rcv_nxt + tp->rcv_wnd;
@@ -2864,11 +2868,14 @@
/* Do not moderate cwnd if it's already undone in cwr or recovery. */
if (tp->undo_marker) {
- if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR)
+ if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR) {
tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
- else /* PRR */
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ } else if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH) {
+ /* PRR algorithm. */
tp->snd_cwnd = tp->snd_ssthresh;
- tp->snd_cwnd_stamp = tcp_time_stamp;
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+ }
}
tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR);
}
@@ -5225,7 +5232,7 @@
return 0;
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
- tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+ tp->ucopy.dma_chan = net_dma_find_channel();
if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3a25cf7..0cb86ce 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1730,7 +1730,7 @@
#ifdef CONFIG_NET_DMA
struct tcp_sock *tp = tcp_sk(sk);
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
- tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+ tp->ucopy.dma_chan = net_dma_find_channel();
if (tp->ucopy.dma_chan)
ret = tcp_v4_do_rcv(sk, skb);
else
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 364784a..7ac6423 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1096,6 +1096,7 @@
eat = min_t(int, len, skb_headlen(skb));
if (eat) {
__skb_pull(skb, eat);
+ skb->avail_size -= eat;
len -= eat;
if (!len)
return;
@@ -2060,7 +2061,7 @@
/* Punt if not enough space exists in the first SKB for
* the data in the second
*/
- if (skb->len > skb_tailroom(to))
+ if (skb->len > skb_availroom(to))
break;
if (after(TCP_SKB_CB(skb)->end_seq, tcp_wnd_end(tp)))
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 8a949f1..a7f86a3 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -146,9 +146,17 @@
return udp_dump_one(&udp_table, in_skb, nlh, req);
}
+static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
+ void *info)
+{
+ r->idiag_rqueue = sk_rmem_alloc_get(sk);
+ r->idiag_wqueue = sk_wmem_alloc_get(sk);
+}
+
static const struct inet_diag_handler udp_diag_handler = {
.dump = udp_diag_dump,
.dump_one = udp_diag_dump_one,
+ .idiag_get_info = udp_diag_get_info,
.idiag_type = IPPROTO_UDP,
};
@@ -167,6 +175,7 @@
static const struct inet_diag_handler udplite_diag_handler = {
.dump = udplite_diag_dump,
.dump_one = udplite_diag_dump_one,
+ .idiag_get_info = udp_diag_get_info,
.idiag_type = IPPROTO_UDPLITE,
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6a3bb60..7d5cb97 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -803,8 +803,7 @@
ip6_del_rt(rt);
rt = NULL;
} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
- rt->dst.expires = expires;
- rt->rt6i_flags |= RTF_EXPIRES;
+ rt6_set_expires(rt, expires);
}
}
dst_release(&rt->dst);
@@ -1887,11 +1886,9 @@
rt = NULL;
} else if (addrconf_finite_timeout(rt_expires)) {
/* not infinity */
- rt->dst.expires = jiffies + rt_expires;
- rt->rt6i_flags |= RTF_EXPIRES;
+ rt6_set_expires(rt, jiffies + rt_expires);
} else {
- rt->rt6i_flags &= ~RTF_EXPIRES;
- rt->dst.expires = 0;
+ rt6_clean_expires(rt);
}
} else if (valid_lft) {
clock_t expires = 0;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 5b27fbc..9371743 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -673,11 +673,10 @@
&rt->rt6i_gateway)) {
if (!(iter->rt6i_flags & RTF_EXPIRES))
return -EEXIST;
- iter->dst.expires = rt->dst.expires;
- if (!(rt->rt6i_flags & RTF_EXPIRES)) {
- iter->rt6i_flags &= ~RTF_EXPIRES;
- iter->dst.expires = 0;
- }
+ if (!(rt->rt6i_flags & RTF_EXPIRES))
+ rt6_clean_expires(iter);
+ else
+ rt6_set_expires(iter, rt->dst.expires);
return -EEXIST;
}
}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 16c33e3..b2869ca 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -2044,7 +2044,7 @@
if (!delta)
pmc->mca_sfcount[sfmode]--;
for (j=0; j<i; j++)
- (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
+ ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
} else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
struct ip6_sf_list *psf;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 3dcdb81..176b469 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1264,8 +1264,7 @@
}
if (rt)
- rt->dst.expires = jiffies + (HZ * lifetime);
-
+ rt6_set_expires(rt, jiffies + (HZ * lifetime));
if (ra_msg->icmph.icmp6_hop_limit) {
in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
if (rt)
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 94874b0..9d4e155 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -78,19 +78,6 @@
Hence the start of any table is given by get_table() below. */
-/* Check for an extension */
-int
-ip6t_ext_hdr(u8 nexthdr)
-{
- return (nexthdr == IPPROTO_HOPOPTS) ||
- (nexthdr == IPPROTO_ROUTING) ||
- (nexthdr == IPPROTO_FRAGMENT) ||
- (nexthdr == IPPROTO_ESP) ||
- (nexthdr == IPPROTO_AH) ||
- (nexthdr == IPPROTO_NONE) ||
- (nexthdr == IPPROTO_DSTOPTS);
-}
-
/* Returns whether matches rule or not. */
/* Performance critical - called for every packet */
static inline bool
@@ -2366,7 +2353,6 @@
EXPORT_SYMBOL(ip6t_register_table);
EXPORT_SYMBOL(ip6t_unregister_table);
EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ip6t_ext_hdr);
EXPORT_SYMBOL(ipv6_find_hdr);
module_init(ip6_tables_init);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 496b627..bc4888d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -62,7 +62,7 @@
#include <linux/sysctl.h>
#endif
-static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
const struct in6_addr *dest);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
@@ -285,6 +285,10 @@
rt->rt6i_idev = NULL;
in6_dev_put(idev);
}
+
+ if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from)
+ dst_release(dst->from);
+
if (peer) {
rt->rt6i_peer = NULL;
inet_putpeer(peer);
@@ -329,8 +333,17 @@
static __inline__ int rt6_check_expired(const struct rt6_info *rt)
{
- return (rt->rt6i_flags & RTF_EXPIRES) &&
- time_after(jiffies, rt->dst.expires);
+ struct rt6_info *ort = NULL;
+
+ if (rt->rt6i_flags & RTF_EXPIRES) {
+ if (time_after(jiffies, rt->dst.expires))
+ return 1;
+ } else if (rt->dst.from) {
+ ort = (struct rt6_info *) rt->dst.from;
+ return (ort->rt6i_flags & RTF_EXPIRES) &&
+ time_after(jiffies, ort->dst.expires);
+ }
+ return 0;
}
static inline int rt6_need_strict(const struct in6_addr *daddr)
@@ -620,12 +633,11 @@
(rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
if (rt) {
- if (!addrconf_finite_timeout(lifetime)) {
- rt->rt6i_flags &= ~RTF_EXPIRES;
- } else {
- rt->dst.expires = jiffies + HZ * lifetime;
- rt->rt6i_flags |= RTF_EXPIRES;
- }
+ if (!addrconf_finite_timeout(lifetime))
+ rt6_clean_expires(rt);
+ else
+ rt6_set_expires(rt, jiffies + HZ * lifetime);
+
dst_release(&rt->dst);
}
return 0;
@@ -730,7 +742,7 @@
return __ip6_ins_rt(rt, &info);
}
-static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
+static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{
@@ -881,6 +893,16 @@
return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
}
+static struct dst_entry *ip6_route_input_lookup(struct net *net,
+ struct net_device *dev,
+ struct flowi6 *fl6, int flags)
+{
+ if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
+ flags |= RT6_LOOKUP_F_IFACE;
+
+ return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
+}
+
void ip6_route_input(struct sk_buff *skb)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -895,10 +917,7 @@
.flowi6_proto = iph->nexthdr,
};
- if (rt6_need_strict(&iph->daddr) && skb->dev->type != ARPHRD_PIMREG)
- flags |= RT6_LOOKUP_F_IFACE;
-
- skb_dst_set(skb, fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_input));
+ skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
}
static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
@@ -947,10 +966,10 @@
rt->rt6i_idev = ort->rt6i_idev;
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
- rt->dst.expires = 0;
rt->rt6i_gateway = ort->rt6i_gateway;
- rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+ rt->rt6i_flags = ort->rt6i_flags;
+ rt6_clean_expires(rt);
rt->rt6i_metric = 0;
memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
@@ -1012,10 +1031,9 @@
rt = (struct rt6_info *) skb_dst(skb);
if (rt) {
- if (rt->rt6i_flags & RTF_CACHE) {
- dst_set_expires(&rt->dst, 0);
- rt->rt6i_flags |= RTF_EXPIRES;
- } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
+ if (rt->rt6i_flags & RTF_CACHE)
+ rt6_update_expires(rt, 0);
+ else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT))
rt->rt6i_node->fn_sernum = -1;
}
}
@@ -1282,9 +1300,12 @@
}
rt->dst.obsolete = -1;
- rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ?
- jiffies + clock_t_to_jiffies(cfg->fc_expires) :
- 0;
+
+ if (cfg->fc_flags & RTF_EXPIRES)
+ rt6_set_expires(rt, jiffies +
+ clock_t_to_jiffies(cfg->fc_expires));
+ else
+ rt6_clean_expires(rt);
if (cfg->fc_protocol == RTPROT_UNSPEC)
cfg->fc_protocol = RTPROT_BOOT;
@@ -1729,8 +1750,8 @@
features |= RTAX_FEATURE_ALLFRAG;
dst_metric_set(&rt->dst, RTAX_FEATURES, features);
}
- dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
- rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
+ rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ rt->rt6i_flags |= RTF_MODIFIED;
goto out;
}
@@ -1758,9 +1779,8 @@
* which is 10 mins. After 10 mins the decreased pmtu is expired
* and detecting PMTU increase will be automatically happened.
*/
- dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires);
- nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES;
-
+ rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires);
+ nrt->rt6i_flags |= RTF_DYNAMIC;
ip6_ins_rt(nrt);
}
out:
@@ -1792,7 +1812,7 @@
* Misc support functions
*/
-static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
+static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
const struct in6_addr *dest)
{
struct net *net = dev_net(ort->dst.dev);
@@ -1812,10 +1832,14 @@
if (rt->rt6i_idev)
in6_dev_hold(rt->rt6i_idev);
rt->dst.lastuse = jiffies;
- rt->dst.expires = 0;
rt->rt6i_gateway = ort->rt6i_gateway;
- rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
+ rt->rt6i_flags = ort->rt6i_flags;
+ if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ==
+ (RTF_DEFAULT | RTF_ADDRCONF))
+ rt6_set_from(rt, ort);
+ else
+ rt6_clean_expires(rt);
rt->rt6i_metric = 0;
#ifdef CONFIG_IPV6_SUBTREES
@@ -2537,7 +2561,7 @@
struct sk_buff *skb;
struct rtmsg *rtm;
struct flowi6 fl6;
- int err, iif = 0;
+ int err, iif = 0, oif = 0;
err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
if (err < 0)
@@ -2564,15 +2588,29 @@
iif = nla_get_u32(tb[RTA_IIF]);
if (tb[RTA_OIF])
- fl6.flowi6_oif = nla_get_u32(tb[RTA_OIF]);
+ oif = nla_get_u32(tb[RTA_OIF]);
if (iif) {
struct net_device *dev;
+ int flags = 0;
+
dev = __dev_get_by_index(net, iif);
if (!dev) {
err = -ENODEV;
goto errout;
}
+
+ fl6.flowi6_iif = iif;
+
+ if (!ipv6_addr_any(&fl6.saddr))
+ flags |= RT6_LOOKUP_F_HAS_SADDR;
+
+ rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
+ flags);
+ } else {
+ fl6.flowi6_oif = oif;
+
+ rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
}
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -2587,7 +2625,6 @@
skb_reset_mac_header(skb);
skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
- rt = (struct rt6_info*) ip6_route_output(net, NULL, &fl6);
skb_dst_set(skb, &rt->dst);
err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 12c6ece..98256cf 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1383,6 +1383,10 @@
tcp_mtup_init(newsk);
tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric_advmss(dst);
+ if (tcp_sk(sk)->rx_opt.user_mss &&
+ tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
+ newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
+
tcp_initialize_rcv_mss(newsk);
if (tcp_rsk(req)->snt_synack)
tcp_valid_rtt_meas(newsk,
@@ -1645,7 +1649,7 @@
#ifdef CONFIG_NET_DMA
struct tcp_sock *tp = tcp_sk(sk);
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
- tp->ucopy.dma_chan = dma_find_channel(DMA_MEMCPY);
+ tp->ucopy.dma_chan = net_dma_find_channel();
if (tp->ucopy.dma_chan)
ret = tcp_v6_do_rcv(sk, skb);
else
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 11dbb22..7e5d927 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -3480,7 +3480,7 @@
/* Addresses to be used by KM for negotiation, if ext is available */
if (k != NULL && (set_sadb_kmaddress(skb, k) < 0))
- return -EINVAL;
+ goto err;
/* selector src */
set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 55670ec..6274f0b 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -232,7 +232,7 @@
{
write_lock_bh(&l2tp_ip_lock);
hlist_del_init(&sk->sk_bind_node);
- hlist_del_init(&sk->sk_node);
+ sk_del_node_init(sk);
write_unlock_bh(&l2tp_ip_lock);
sk_common_release(sk);
}
@@ -271,7 +271,8 @@
chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
goto out;
- inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
+ if (addr->l2tp_addr.s_addr)
+ inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
inet->inet_saddr = 0; /* Use device */
sk_dst_reset(sk);
@@ -441,8 +442,9 @@
daddr = lip->l2tp_addr.s_addr;
} else {
+ rc = -EDESTADDRREQ;
if (sk->sk_state != TCP_ESTABLISHED)
- return -EDESTADDRREQ;
+ goto out;
daddr = inet->inet_daddr;
connected = 1;
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 1068f66..64d3ce5 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -49,6 +49,8 @@
container_of(h, struct tid_ampdu_rx, rcu_head);
int i;
+ del_timer_sync(&tid_rx->reorder_timer);
+
for (i = 0; i < tid_rx->buf_size; i++)
dev_kfree_skb(tid_rx->reorder_buf[i]);
kfree(tid_rx->reorder_buf);
@@ -91,7 +93,6 @@
tid, WLAN_BACK_RECIPIENT, reason);
del_timer_sync(&tid_rx->session_timer);
- del_timer_sync(&tid_rx->reorder_timer);
call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
}
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index cc5b7a6..778e591 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -15,12 +15,6 @@
#include "rate.h"
#include "debugfs.h"
-int mac80211_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define DEBUGFS_FORMAT_BUFFER_SIZE 100
int mac80211_format_buffer(char __user *userbuf, size_t count,
@@ -50,7 +44,7 @@
#define DEBUGFS_READONLY_FILE_OPS(name) \
static const struct file_operations name## _ops = { \
.read = name## _read, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -93,7 +87,7 @@
static const struct file_operations reset_ops = {
.write = reset_write,
- .open = mac80211_open_file_generic,
+ .open = simple_open,
.llseek = noop_llseek,
};
@@ -254,7 +248,7 @@
\
static const struct file_operations stats_ ##name## _ops = { \
.read = stats_ ##name## _read, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index 7c87529..9be4e6d 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -3,7 +3,6 @@
#ifdef CONFIG_MAC80211_DEBUGFS
extern void debugfs_hw_add(struct ieee80211_local *local);
-extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
extern int mac80211_format_buffer(char __user *userbuf, size_t count,
loff_t *ppos, char *fmt, ...);
#else
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 59edcd9..7932767 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -30,7 +30,7 @@
#define KEY_OPS(name) \
static const struct file_operations key_ ##name## _ops = { \
.read = key_##name##_read, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
}
@@ -45,7 +45,7 @@
#define KEY_CONF_OPS(name) \
static const struct file_operations key_ ##name## _ops = { \
.read = key_conf_##name##_read, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
}
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index a32eeda..30f99c3 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -135,7 +135,7 @@
static const struct file_operations name##_ops = { \
.read = ieee80211_if_read_##name, \
.write = (_write), \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
}
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 6d45804..832b2da 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -33,7 +33,7 @@
#define STA_OPS(name) \
static const struct file_operations sta_ ##name## _ops = { \
.read = sta_##name##_read, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
}
@@ -41,7 +41,7 @@
static const struct file_operations sta_ ##name## _ops = { \
.read = sta_##name##_read, \
.write = sta_##name##_write, \
- .open = mac80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 33fd8d9..cef7c29 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -457,8 +457,8 @@
* fall back to HT20 if we don't use or use
* the other extension channel
*/
- if ((channel_type == NL80211_CHAN_HT40MINUS ||
- channel_type == NL80211_CHAN_HT40PLUS) &&
+ if (!(channel_type == NL80211_CHAN_HT40MINUS ||
+ channel_type == NL80211_CHAN_HT40PLUS) ||
channel_type != sdata->u.ibss.channel_type)
sta_ht_cap_new.cap &=
~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d9798a3..db8fae5 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1210,7 +1210,7 @@
struct sk_buff *skb);
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
-void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 401c01f..c20051b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -486,6 +486,8 @@
/* free all potentially still buffered bcast frames */
local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
skb_queue_purge(&sdata->u.ap.ps_bc_buf);
+ } else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ ieee80211_mgd_stop(sdata);
}
if (going_down)
@@ -644,8 +646,6 @@
if (ieee80211_vif_is_mesh(&sdata->vif))
mesh_rmc_free(sdata);
- else if (sdata->vif.type == NL80211_IFTYPE_STATION)
- ieee80211_mgd_teardown(sdata);
flushed = sta_info_flush(local, sdata);
WARN_ON(flushed);
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b581a24..1633648 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -102,9 +102,6 @@
might_sleep();
- /* If this off-channel logic ever changes, ieee80211_on_oper_channel
- * may need to change as well.
- */
offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
if (local->scan_channel) {
chan = local->scan_channel;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 576fb25..20c680b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3387,8 +3387,7 @@
*/
printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
sdata->name, ifmgd->bssid);
- assoc_data->timeout = jiffies +
- TU_TO_EXP_TIME(req->bss->beacon_interval);
+ assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
} else {
assoc_data->have_beacon = true;
assoc_data->sent_assoc = false;
@@ -3498,7 +3497,7 @@
return 0;
}
-void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata)
+void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b4f7600..3313c11 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -145,7 +145,7 @@
static const struct file_operations rcname_ops = {
.read = rcname_read,
- .open = mac80211_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
#endif
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index bcfe8c7..d64e285 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -103,7 +103,7 @@
ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct sk_buff *skb,
struct ieee80211_rate *rate,
- int rtap_len)
+ int rtap_len, bool has_fcs)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_header *rthdr;
@@ -134,7 +134,7 @@
}
/* IEEE80211_RADIOTAP_FLAGS */
- if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
+ if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))
*pos |= IEEE80211_RADIOTAP_F_FCS;
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
*pos |= IEEE80211_RADIOTAP_F_BADFCS;
@@ -294,7 +294,8 @@
}
/* prepend radiotap information */
- ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+ true);
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2571,7 +2572,8 @@
goto out_free_skb;
/* prepend radiotap information */
- ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+ false);
skb_set_mac_header(skb, 0);
skb->ip_summed = CHECKSUM_UNNECESSARY;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 33cd169..c70e176 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -370,7 +370,7 @@
*/
drv_sw_scan_start(local);
- local->leave_oper_channel_time = 0;
+ local->leave_oper_channel_time = jiffies;
local->next_scan_state = SCAN_DECISION;
local->scan_channel_idx = 0;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 782a601..e76facc 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1158,7 +1158,8 @@
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
return TX_DROP;
- } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+ } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+ tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta)
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 2555816..00bdb1d 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1924,6 +1924,7 @@
control_fail:
ip_vs_estimator_net_cleanup(net);
estimator_fail:
+ net->ipvs = NULL;
return -ENOMEM;
}
@@ -1936,6 +1937,7 @@
ip_vs_control_net_cleanup(net);
ip_vs_estimator_net_cleanup(net);
IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen);
+ net->ipvs = NULL;
}
static void __net_exit __ip_vs_dev_cleanup(struct net *net)
@@ -1993,10 +1995,18 @@
goto cleanup_dev;
}
+ ret = ip_vs_register_nl_ioctl();
+ if (ret < 0) {
+ pr_err("can't register netlink/ioctl.\n");
+ goto cleanup_hooks;
+ }
+
pr_info("ipvs loaded.\n");
return ret;
+cleanup_hooks:
+ nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
cleanup_dev:
unregister_pernet_device(&ipvs_core_dev_ops);
cleanup_sub:
@@ -2012,6 +2022,7 @@
static void __exit ip_vs_cleanup(void)
{
+ ip_vs_unregister_nl_ioctl();
nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
unregister_pernet_device(&ipvs_core_dev_ops);
unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index b3afe18..f558998 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3680,7 +3680,7 @@
return 0;
}
-void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net)
+void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -3692,7 +3692,7 @@
#else
int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; }
-void __net_init ip_vs_control_net_cleanup_sysctl(struct net *net) { }
+void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { }
#endif
@@ -3750,21 +3750,10 @@
free_percpu(ipvs->tot_stats.cpustats);
}
-int __init ip_vs_control_init(void)
+int __init ip_vs_register_nl_ioctl(void)
{
- int idx;
int ret;
- EnterFunction(2);
-
- /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
- for(idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
- INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
- INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
- }
-
- smp_wmb(); /* Do we really need it now ? */
-
ret = nf_register_sockopt(&ip_vs_sockopts);
if (ret) {
pr_err("cannot register sockopt.\n");
@@ -3776,28 +3765,47 @@
pr_err("cannot register Generic Netlink interface.\n");
goto err_genl;
}
-
- ret = register_netdevice_notifier(&ip_vs_dst_notifier);
- if (ret < 0)
- goto err_notf;
-
- LeaveFunction(2);
return 0;
-err_notf:
- ip_vs_genl_unregister();
err_genl:
nf_unregister_sockopt(&ip_vs_sockopts);
err_sock:
return ret;
}
+void ip_vs_unregister_nl_ioctl(void)
+{
+ ip_vs_genl_unregister();
+ nf_unregister_sockopt(&ip_vs_sockopts);
+}
+
+int __init ip_vs_control_init(void)
+{
+ int idx;
+ int ret;
+
+ EnterFunction(2);
+
+ /* Initialize svc_table, ip_vs_svc_fwm_table, rs_table */
+ for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) {
+ INIT_LIST_HEAD(&ip_vs_svc_table[idx]);
+ INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]);
+ }
+
+ smp_wmb(); /* Do we really need it now ? */
+
+ ret = register_netdevice_notifier(&ip_vs_dst_notifier);
+ if (ret < 0)
+ return ret;
+
+ LeaveFunction(2);
+ return 0;
+}
+
void ip_vs_control_cleanup(void)
{
EnterFunction(2);
unregister_netdevice_notifier(&ip_vs_dst_notifier);
- ip_vs_genl_unregister();
- nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
}
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 538d74e..e39f693 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -439,6 +439,8 @@
struct ip_vs_app *app;
struct netns_ipvs *ipvs = net_ipvs(net);
+ if (!ipvs)
+ return -ENOENT;
app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL);
if (!app)
return -ENOMEM;
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 0f16283..caa4370 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -551,6 +551,9 @@
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ if (!ipvs)
+ return -ENOENT;
+
if (!net_eq(net, &init_net)) {
ipvs->lblc_ctl_table = kmemdup(vs_vars_table,
sizeof(vs_vars_table),
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index eec797f..548bf37 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -745,6 +745,9 @@
{
struct netns_ipvs *ipvs = net_ipvs(net);
+ if (!ipvs)
+ return -ENOENT;
+
if (!net_eq(net, &init_net)) {
ipvs->lblcr_ctl_table = kmemdup(vs_vars_table,
sizeof(vs_vars_table),
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index f843a88..ed835e6 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -59,9 +59,6 @@
return 0;
}
-#if defined(CONFIG_IP_VS_PROTO_TCP) || defined(CONFIG_IP_VS_PROTO_UDP) || \
- defined(CONFIG_IP_VS_PROTO_SCTP) || defined(CONFIG_IP_VS_PROTO_AH) || \
- defined(CONFIG_IP_VS_PROTO_ESP)
/*
* register an ipvs protocols netns related data
*/
@@ -81,12 +78,18 @@
ipvs->proto_data_table[hash] = pd;
atomic_set(&pd->appcnt, 0); /* Init app counter */
- if (pp->init_netns != NULL)
- pp->init_netns(net, pd);
+ if (pp->init_netns != NULL) {
+ int ret = pp->init_netns(net, pd);
+ if (ret) {
+ /* unlink an free proto data */
+ ipvs->proto_data_table[hash] = pd->next;
+ kfree(pd);
+ return ret;
+ }
+ }
return 0;
}
-#endif
/*
* unregister an ipvs protocol
@@ -316,22 +319,35 @@
*/
int __net_init ip_vs_protocol_net_init(struct net *net)
{
+ int i, ret;
+ static struct ip_vs_protocol *protos[] = {
#ifdef CONFIG_IP_VS_PROTO_TCP
- register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp);
+ &ip_vs_protocol_tcp,
#endif
#ifdef CONFIG_IP_VS_PROTO_UDP
- register_ip_vs_proto_netns(net, &ip_vs_protocol_udp);
+ &ip_vs_protocol_udp,
#endif
#ifdef CONFIG_IP_VS_PROTO_SCTP
- register_ip_vs_proto_netns(net, &ip_vs_protocol_sctp);
+ &ip_vs_protocol_sctp,
#endif
#ifdef CONFIG_IP_VS_PROTO_AH
- register_ip_vs_proto_netns(net, &ip_vs_protocol_ah);
+ &ip_vs_protocol_ah,
#endif
#ifdef CONFIG_IP_VS_PROTO_ESP
- register_ip_vs_proto_netns(net, &ip_vs_protocol_esp);
+ &ip_vs_protocol_esp,
#endif
+ };
+
+ for (i = 0; i < ARRAY_SIZE(protos); i++) {
+ ret = register_ip_vs_proto_netns(net, protos[i]);
+ if (ret < 0)
+ goto cleanup;
+ }
return 0;
+
+cleanup:
+ ip_vs_protocol_net_cleanup(net);
+ return ret;
}
void __net_exit ip_vs_protocol_net_cleanup(struct net *net)
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 1fbf7a2..9f3fb75 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -1090,7 +1090,7 @@
* timeouts is netns related now.
* ---------------------------------------------
*/
-static void __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_sctp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -1098,6 +1098,9 @@
spin_lock_init(&ipvs->sctp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)sctp_timeouts,
sizeof(sctp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
+ return 0;
}
static void __ip_vs_sctp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index ef8641f..cd609cc 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -677,7 +677,7 @@
* timeouts is netns related now.
* ---------------------------------------------
*/
-static void __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __ip_vs_tcp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -685,7 +685,10 @@
spin_lock_init(&ipvs->tcp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)tcp_timeouts,
sizeof(tcp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
pd->tcp_state_table = tcp_states;
+ return 0;
}
static void __ip_vs_tcp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c
index f4b7262..2fedb2d 100644
--- a/net/netfilter/ipvs/ip_vs_proto_udp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_udp.c
@@ -467,7 +467,7 @@
cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
}
-static void __udp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
{
struct netns_ipvs *ipvs = net_ipvs(net);
@@ -475,6 +475,9 @@
spin_lock_init(&ipvs->udp_app_lock);
pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
sizeof(udp_timeouts));
+ if (!pd->timeout_table)
+ return -ENOMEM;
+ return 0;
}
static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index cbdb754..729f157 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -735,6 +735,7 @@
#ifdef CONFIG_NF_CONNTRACK_ZONES
out_free:
+ atomic_dec(&net->ct.count);
kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
return ERR_PTR(-ENOMEM);
#endif
@@ -1591,7 +1592,7 @@
return 0;
err_timeout:
- nf_conntrack_timeout_fini(net);
+ nf_conntrack_ecache_fini(net);
err_ecache:
nf_conntrack_tstamp_fini(net);
err_tstamp:
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 361eade..0d07a1d 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -584,8 +584,8 @@
* Let's try to use the data from the packet.
*/
sender->td_end = end;
- win <<= sender->td_scale;
- sender->td_maxwin = (win == 0 ? 1 : win);
+ swin = win << sender->td_scale;
+ sender->td_maxwin = (swin == 0 ? 1 : swin);
sender->td_maxend = end + sender->td_maxwin;
/*
* We haven't seen traffic in the other direction yet
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
index 3eb348b..d98c868 100644
--- a/net/netfilter/nfnetlink_acct.c
+++ b/net/netfilter/nfnetlink_acct.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
+#include <linux/atomic.h>
#include <linux/netlink.h>
#include <linux/rculist.h>
#include <linux/slab.h>
@@ -17,7 +18,6 @@
#include <linux/errno.h>
#include <net/netlink.h>
#include <net/sock.h>
-#include <asm/atomic.h>
#include <linux/netfilter.h>
#include <linux/netfilter/nfnetlink.h>
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 0c8e438..3746d8b 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -150,6 +150,17 @@
return ret;
}
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout)
+{
+ typeof(nf_ct_timeout_put_hook) timeout_put;
+
+ timeout_put = rcu_dereference(nf_ct_timeout_put_hook);
+ if (timeout_put)
+ timeout_put(timeout);
+}
+#endif
+
static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
{
struct xt_ct_target_info_v1 *info = par->targinfo;
@@ -158,7 +169,9 @@
struct nf_conn *ct;
int ret = 0;
u8 proto;
-
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+ struct ctnl_timeout *timeout;
+#endif
if (info->flags & ~XT_CT_NOTRACK)
return -EINVAL;
@@ -214,9 +227,8 @@
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
- if (info->timeout) {
+ if (info->timeout[0]) {
typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
- struct ctnl_timeout *timeout;
struct nf_conn_timeout *timeout_ext;
rcu_read_lock();
@@ -245,7 +257,7 @@
pr_info("Timeout policy `%s' can only be "
"used by L3 protocol number %d\n",
info->timeout, timeout->l3num);
- goto err4;
+ goto err5;
}
/* Make sure the timeout policy matches any existing
* protocol tracker, otherwise default to generic.
@@ -258,13 +270,13 @@
"used by L4 protocol number %d\n",
info->timeout,
timeout->l4proto->l4proto);
- goto err4;
+ goto err5;
}
timeout_ext = nf_ct_timeout_ext_add(ct, timeout,
- GFP_KERNEL);
+ GFP_ATOMIC);
if (timeout_ext == NULL) {
ret = -ENOMEM;
- goto err4;
+ goto err5;
}
} else {
ret = -ENOENT;
@@ -281,8 +293,12 @@
info->ct = ct;
return 0;
+#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
+err5:
+ __xt_ct_tg_timeout_put(timeout);
err4:
rcu_read_unlock();
+#endif
err3:
nf_conntrack_free(ct);
err2:
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 32bb753..faa48f7 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -829,12 +829,19 @@
return 0;
}
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
{
int len = skb->len;
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);
+ return len;
+}
+
+int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+{
+ int len = __netlink_sendskb(sk, skb);
+
sock_put(sk);
return len;
}
@@ -957,8 +964,7 @@
if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
!test_bit(0, &nlk->state)) {
skb_set_owner_r(skb, sk);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ __netlink_sendskb(sk, skb);
return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
}
return -1;
@@ -1698,10 +1704,8 @@
if (sk_filter(sk, skb))
kfree_skb(skb);
- else {
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
- }
+ else
+ __netlink_sendskb(sk, skb);
return 0;
}
@@ -1715,10 +1719,8 @@
if (sk_filter(sk, skb))
kfree_skb(skb);
- else {
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
- }
+ else
+ __netlink_sendskb(sk, skb);
if (cb->done)
cb->done(cb);
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index 7b76eb7..ef10ffc 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -474,7 +474,7 @@
while (remaining_len > 0) {
- frag_len = min_t(u16, local->remote_miu, remaining_len);
+ frag_len = min_t(size_t, local->remote_miu, remaining_len);
pr_debug("Fragment %zd bytes remaining %zd",
frag_len, remaining_len);
@@ -497,7 +497,7 @@
release_sock(sk);
remaining_len -= frag_len;
- msg_ptr += len;
+ msg_ptr += frag_len;
}
kfree(msg_data);
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 9f60008..9726fe6 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1130,6 +1130,9 @@
int flags = msg->msg_flags;
int err, done;
+ if (len > USHRT_MAX)
+ return -EMSGSIZE;
+
if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
MSG_CMSG_COMPAT)) ||
!(msg->msg_flags & MSG_EOR))
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c
index 9b9a85ec..bf5cf69 100644
--- a/net/phonet/pn_dev.c
+++ b/net/phonet/pn_dev.c
@@ -331,23 +331,6 @@
static void __net_exit phonet_exit_net(struct net *net)
{
- struct phonet_net *pnn = phonet_pernet(net);
- struct net_device *dev;
- unsigned i;
-
- rtnl_lock();
- for_each_netdev(net, dev)
- phonet_device_destroy(dev);
-
- for (i = 0; i < 64; i++) {
- dev = pnn->routes.table[i];
- if (dev) {
- rtm_phonet_notify(RTM_DELROUTE, dev, i);
- dev_put(dev);
- }
- }
- rtnl_unlock();
-
proc_net_remove(net, "phonet");
}
@@ -361,7 +344,7 @@
/* Initialize Phonet devices list */
int __init phonet_device_init(void)
{
- int err = register_pernet_device(&phonet_net_ops);
+ int err = register_pernet_subsys(&phonet_net_ops);
if (err)
return err;
@@ -377,7 +360,7 @@
{
rtnl_unregister_all(PF_PHONET);
unregister_netdevice_notifier(&phonet_device_notifier);
- unregister_pernet_device(&phonet_net_ops);
+ unregister_pernet_subsys(&phonet_net_ops);
proc_net_remove(&init_net, "pnresource");
}
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 1ab8689..906cc05 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -95,11 +95,11 @@
struct sockaddr *sa = addr;
int err;
- if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+ if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
return 0;
if (dev->flags & IFF_UP) {
- err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+ err = rose_add_loopback_node((rose_address *)sa->sa_data);
if (err)
return err;
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 0b15236..8179494 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -565,11 +565,8 @@
opt.packets = q->packetsin;
opt.bytesin = q->bytesin;
- if (gred_wred_mode(table)) {
- q->vars.qidlestart =
- table->tab[table->def]->vars.qidlestart;
- q->vars.qavg = table->tab[table->def]->vars.qavg;
- }
+ if (gred_wred_mode(table))
+ gred_load_wred_set(table, q);
opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 5da548f..ebd2296 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -408,10 +408,8 @@
if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
(skb->ip_summed == CHECKSUM_PARTIAL &&
- skb_checksum_help(skb))) {
- sch->qstats.drops++;
- return NET_XMIT_DROP;
- }
+ skb_checksum_help(skb)))
+ return qdisc_drop(skb, sch);
skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
}
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 06b42b7..92ba71d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4133,9 +4133,10 @@
static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
int __user *optlen)
{
- if (len < sizeof(struct sctp_event_subscribe))
+ if (len <= 0)
return -EINVAL;
- len = sizeof(struct sctp_event_subscribe);
+ if (len > sizeof(struct sctp_event_subscribe))
+ len = sizeof(struct sctp_event_subscribe);
if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
diff --git a/net/socket.c b/net/socket.c
index 484cc69..851edcd 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -811,9 +811,9 @@
sock = file->private_data;
- flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
- if (more)
- flags |= MSG_MORE;
+ flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+ /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
+ flags |= more;
return kernel_sendpage(sock, page, offset, size, flags);
}
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 6797246..adf2990 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -176,16 +176,22 @@
return 0;
}
-static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
- struct super_block *sb)
+static inline int rpc_clnt_skip_event(struct rpc_clnt *clnt, unsigned long event)
+{
+ if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
+ ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
+ return 1;
+ return 0;
+}
+
+static int __rpc_clnt_handle_event(struct rpc_clnt *clnt, unsigned long event,
+ struct super_block *sb)
{
struct dentry *dentry;
int err = 0;
switch (event) {
case RPC_PIPEFS_MOUNT:
- if (clnt->cl_program->pipe_dir_name == NULL)
- break;
dentry = rpc_setup_pipedir_sb(sb, clnt,
clnt->cl_program->pipe_dir_name);
BUG_ON(dentry == NULL);
@@ -208,6 +214,20 @@
return err;
}
+static int __rpc_pipefs_event(struct rpc_clnt *clnt, unsigned long event,
+ struct super_block *sb)
+{
+ int error = 0;
+
+ for (;; clnt = clnt->cl_parent) {
+ if (!rpc_clnt_skip_event(clnt, event))
+ error = __rpc_clnt_handle_event(clnt, event, sb);
+ if (error || clnt == clnt->cl_parent)
+ break;
+ }
+ return error;
+}
+
static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event)
{
struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
@@ -215,10 +235,12 @@
spin_lock(&sn->rpc_client_lock);
list_for_each_entry(clnt, &sn->all_clients, cl_clients) {
- if (((event == RPC_PIPEFS_MOUNT) && clnt->cl_dentry) ||
- ((event == RPC_PIPEFS_UMOUNT) && !clnt->cl_dentry))
+ if (clnt->cl_program->pipe_dir_name == NULL)
+ break;
+ if (rpc_clnt_skip_event(clnt, event))
continue;
- atomic_inc(&clnt->cl_count);
+ if (atomic_inc_not_zero(&clnt->cl_count) == 0)
+ continue;
spin_unlock(&sn->rpc_client_lock);
return clnt;
}
@@ -257,6 +279,14 @@
return rpc_pipefs_notifier_unregister(&rpc_clients_block);
}
+static void rpc_clnt_set_nodename(struct rpc_clnt *clnt, const char *nodename)
+{
+ clnt->cl_nodelen = strlen(nodename);
+ if (clnt->cl_nodelen > UNX_MAXNODENAME)
+ clnt->cl_nodelen = UNX_MAXNODENAME;
+ memcpy(clnt->cl_nodename, nodename, clnt->cl_nodelen);
+}
+
static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, struct rpc_xprt *xprt)
{
const struct rpc_program *program = args->program;
@@ -337,10 +367,7 @@
}
/* save the nodename */
- clnt->cl_nodelen = strlen(init_utsname()->nodename);
- if (clnt->cl_nodelen > UNX_MAXNODENAME)
- clnt->cl_nodelen = UNX_MAXNODENAME;
- memcpy(clnt->cl_nodename, init_utsname()->nodename, clnt->cl_nodelen);
+ rpc_clnt_set_nodename(clnt, utsname()->nodename);
rpc_register_client(clnt);
return clnt;
@@ -499,6 +526,7 @@
err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
if (err != 0)
goto out_no_path;
+ rpc_clnt_set_nodename(new, utsname()->nodename);
if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count);
atomic_inc(&clnt->cl_count);
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index 0af37fc..3b62cf2 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1126,19 +1126,20 @@
return -ENOMEM;
dprintk("RPC: sending pipefs MOUNT notification for net %p%s\n", net,
NET_NAME(net));
+ sn->pipefs_sb = sb;
err = blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
RPC_PIPEFS_MOUNT,
sb);
if (err)
goto err_depopulate;
sb->s_fs_info = get_net(net);
- sn->pipefs_sb = sb;
return 0;
err_depopulate:
blocking_notifier_call_chain(&rpc_pipefs_notifier_list,
RPC_PIPEFS_UMOUNT,
sb);
+ sn->pipefs_sb = NULL;
__rpc_depopulate(root, files, RPCAUTH_lockd, RPCAUTH_RootEOF);
return err;
}
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index 8adfc88..3d6498a 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -75,20 +75,21 @@
static int __init
init_sunrpc(void)
{
- int err = register_rpc_pipefs();
+ int err = rpc_init_mempool();
if (err)
goto out;
- err = rpc_init_mempool();
- if (err)
- goto out2;
err = rpcauth_init_module();
if (err)
- goto out3;
+ goto out2;
cache_initialize();
err = register_pernet_subsys(&sunrpc_net_ops);
if (err)
+ goto out3;
+
+ err = register_rpc_pipefs();
+ if (err)
goto out4;
#ifdef RPC_DEBUG
rpc_register_sysctl();
@@ -98,11 +99,11 @@
return 0;
out4:
- rpcauth_remove_module();
+ unregister_pernet_subsys(&sunrpc_net_ops);
out3:
- rpc_destroy_mempool();
+ rpcauth_remove_module();
out2:
- unregister_rpc_pipefs();
+ rpc_destroy_mempool();
out:
return err;
}
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 39765bc..920cabe 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -13,12 +13,6 @@
#include "core.h"
#include "debugfs.h"
-static int cfg80211_open_file_generic(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
static ssize_t name## _read(struct file *file, char __user *userbuf, \
size_t count, loff_t *ppos) \
@@ -33,7 +27,7 @@
\
static const struct file_operations name## _ops = { \
.read = name## _read, \
- .open = cfg80211_open_file_generic, \
+ .open = simple_open, \
.llseek = generic_file_llseek, \
};
@@ -102,7 +96,7 @@
static const struct file_operations ht40allow_map_ops = {
.read = ht40allow_map_read,
- .open = cfg80211_open_file_generic,
+ .open = simple_open,
.llseek = default_llseek,
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4c1eb94..f432c57 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1294,6 +1294,11 @@
goto bad_res;
}
+ if (!netif_running(netdev)) {
+ result = -ENETDOWN;
+ goto bad_res;
+ }
+
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
rem_txq_params) {
@@ -2386,7 +2391,9 @@
}
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
- int flags, struct net_device *dev,
+ int flags,
+ struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
const u8 *mac_addr, struct station_info *sinfo)
{
void *hdr;
@@ -2425,12 +2432,18 @@
if (sinfo->filled & STATION_INFO_PLINK_STATE)
NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
sinfo->plink_state);
- if (sinfo->filled & STATION_INFO_SIGNAL)
- NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
- sinfo->signal);
- if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
- NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
- sinfo->signal_avg);
+ switch (rdev->wiphy.signal_type) {
+ case CFG80211_SIGNAL_TYPE_MBM:
+ if (sinfo->filled & STATION_INFO_SIGNAL)
+ NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+ sinfo->signal);
+ if (sinfo->filled & STATION_INFO_SIGNAL_AVG)
+ NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
+ sinfo->signal_avg);
+ break;
+ default:
+ break;
+ }
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
NL80211_STA_INFO_TX_BITRATE))
@@ -2523,7 +2536,7 @@
if (nl80211_send_station(skb,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- netdev, mac_addr,
+ dev, netdev, mac_addr,
&sinfo) < 0)
goto out;
@@ -2568,7 +2581,7 @@
return -ENOMEM;
if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
- dev, mac_addr, &sinfo) < 0) {
+ rdev, dev, mac_addr, &sinfo) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
}
@@ -6376,7 +6389,7 @@
.doit = nl80211_get_key,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6408,7 +6421,7 @@
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_set_beacon,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6416,7 +6429,7 @@
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_start_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6424,7 +6437,7 @@
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_stop_ap,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6440,7 +6453,7 @@
.doit = nl80211_set_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6456,7 +6469,7 @@
.doit = nl80211_del_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6489,7 +6502,7 @@
.doit = nl80211_del_mpath,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6497,7 +6510,7 @@
.doit = nl80211_set_bss,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6523,7 +6536,7 @@
.doit = nl80211_get_mesh_config,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6656,7 +6669,7 @@
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6664,7 +6677,7 @@
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6672,7 +6685,7 @@
.doit = nl80211_flush_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -6832,7 +6845,7 @@
.doit = nl80211_probe_client,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -7596,7 +7609,8 @@
if (!msg)
return;
- if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) {
+ if (nl80211_send_station(msg, 0, 0, 0,
+ rdev, dev, mac_addr, sinfo) < 0) {
nlmsg_free(msg);
return;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 1b7a08df..957f2562 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -989,7 +989,7 @@
if (rdev->wiphy.software_iftypes & BIT(iftype))
continue;
for (j = 0; j < c->n_limits; j++) {
- if (!(limits[j].types & iftype))
+ if (!(limits[j].types & BIT(iftype)))
continue;
if (limits[j].max < num[iftype])
goto cont;
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 0af7f54..af648e0 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -780,8 +780,10 @@
if (cmd == SIOCSIWENCODEEXT) {
struct iw_encode_ext *ee = (void *) extra;
- if (iwp->length < sizeof(*ee) + ee->key_len)
- return -EFAULT;
+ if (iwp->length < sizeof(*ee) + ee->key_len) {
+ err = -EFAULT;
+ goto out;
+ }
}
}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index de639eee..faea0ec 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1869,12 +1869,6 @@
"No space is necessary after a cast\n" . $hereprev);
}
- if ($rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
- $prevrawline =~ /^\+[ \t]*$/) {
- CHK("BLOCK_COMMENT_STYLE",
- "Don't begin block comments with only a /* line, use /* comment...\n" . $hereprev);
- }
-
# check for spaces at the beginning of a line.
# Exceptions:
# 1) within comments
diff --git a/scripts/coccinelle/api/simple_open.cocci b/scripts/coccinelle/api/simple_open.cocci
new file mode 100644
index 0000000..05962f7
--- /dev/null
+++ b/scripts/coccinelle/api/simple_open.cocci
@@ -0,0 +1,70 @@
+/// This removes an open coded simple_open() function
+/// and replaces file operations references to the function
+/// with simple_open() instead.
+///
+// Confidence: High
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual report
+
+@ open depends on patch @
+identifier open_f != simple_open;
+identifier i, f;
+@@
+-int open_f(struct inode *i, struct file *f)
+-{
+(
+-if (i->i_private)
+-f->private_data = i->i_private;
+|
+-f->private_data = i->i_private;
+)
+-return 0;
+-}
+
+@ has_open depends on open @
+identifier fops;
+identifier open.open_f;
+@@
+struct file_operations fops = {
+...,
+-.open = open_f,
++.open = simple_open,
+...
+};
+
+@ openr depends on report @
+identifier open_f != simple_open;
+identifier i, f;
+position p;
+@@
+int open_f@p(struct inode *i, struct file *f)
+{
+(
+if (i->i_private)
+f->private_data = i->i_private;
+|
+f->private_data = i->i_private;
+)
+return 0;
+}
+
+@ has_openr depends on openr @
+identifier fops;
+identifier openr.open_f;
+position p;
+@@
+struct file_operations fops = {
+...,
+.open = open_f@p,
+...
+};
+
+@script:python@
+pf << openr.p;
+ps << has_openr.p;
+@@
+
+coccilib.report.print_report(pf[0],"WARNING opportunity for simple_open, see also structure on line %s"%(ps[0].line))
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 0586085..52577f0 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -540,35 +540,6 @@
};
/*
- * Generate the __enabled_CONFIG_* and __enabled_CONFIG_*_MODULE macros for
- * use by the IS_{ENABLED,BUILTIN,MODULE} macros. The _MODULE variant is
- * generated even for booleans so that the IS_ENABLED() macro works.
- */
-static void
-header_print__enabled_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg)
-{
-
- switch (sym->type) {
- case S_BOOLEAN:
- case S_TRISTATE: {
- fprintf(fp, "#define __enabled_" CONFIG_ "%s %d\n",
- sym->name, (*value == 'y'));
- fprintf(fp, "#define __enabled_" CONFIG_ "%s_MODULE %d\n",
- sym->name, (*value == 'm'));
- break;
- }
- default:
- break;
- }
-}
-
-static struct conf_printer header__enabled_printer_cb =
-{
- .print_symbol = header_print__enabled_symbol,
- .print_comment = header_print_comment,
-};
-
-/*
* Tristate printer
*
* This printer is used when generating the `include/config/tristate.conf' file.
@@ -949,16 +920,11 @@
conf_write_heading(out_h, &header_printer_cb, NULL);
for_all_symbols(i, sym) {
- if (!sym->name)
- continue;
-
sym_calc_value(sym);
-
- conf_write_symbol(out_h, sym, &header__enabled_printer_cb, NULL);
-
- if (!(sym->flags & SYMBOL_WRITE))
+ if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
continue;
+ /* write symbol to auto.conf, tristate and header files */
conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1);
conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 8e730cc..44ddaa5 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -1100,6 +1100,10 @@
if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
return;
+ /* We're looking for an object */
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+ return;
+
/* All our symbols are of form <prefix>__mod_XXX_device_table. */
name = strstr(symname, "__mod_");
if (!name)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 3f01fd9..c4e7d15 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -132,8 +132,10 @@
/* strip trailing .o */
s = strrchr(p, '.');
if (s != NULL)
- if (strcmp(s, ".o") == 0)
+ if (strcmp(s, ".o") == 0) {
*s = '\0';
+ mod->is_dot_o = 1;
+ }
/* add to list */
mod->name = p;
@@ -587,7 +589,8 @@
unsigned int crc;
enum export export;
- if (!is_vmlinux(mod->name) && strncmp(symname, "__ksymtab", 9) == 0)
+ if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+ strncmp(symname, "__ksymtab", 9) == 0)
export = export_from_secname(info, get_secindex(info, sym));
else
export = export_from_sec(info, get_secindex(info, sym));
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 2031119..51207e4 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -113,6 +113,7 @@
int has_cleanup;
struct buffer dev_table_buf;
char srcversion[25];
+ int is_dot_o;
};
struct elf_info {
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 0d6004e..cf7b12f 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -254,6 +254,6 @@
esac
# Remove structure forward declarations.
-if [ -n $remove_structs ]; then
+if [ -n "$remove_structs" ]; then
LANG=C sed -i -e '/^\([a-zA-Z_][a-zA-Z0-9_]*\)\t.*\t\/\^struct \1;.*\$\/;"\tx$/d' $1
fi
diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh
index 17a5798..7a2d372 100644
--- a/scripts/xz_wrap.sh
+++ b/scripts/xz_wrap.sh
@@ -12,8 +12,8 @@
BCJ=
LZMA2OPTS=
-case $ARCH in
- x86|x86_64) BCJ=--x86 ;;
+case $SRCARCH in
+ x86) BCJ=--x86 ;;
powerpc) BCJ=--powerpc ;;
ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;;
arm) BCJ=--arm ;;
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 5ff6777..cc3520d 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -115,23 +115,23 @@
if (aa_g_audit_header) {
audit_log_format(ab, "apparmor=");
- audit_log_string(ab, aa_audit_type[sa->aad.type]);
+ audit_log_string(ab, aa_audit_type[sa->aad->type]);
}
- if (sa->aad.op) {
+ if (sa->aad->op) {
audit_log_format(ab, " operation=");
- audit_log_string(ab, op_table[sa->aad.op]);
+ audit_log_string(ab, op_table[sa->aad->op]);
}
- if (sa->aad.info) {
+ if (sa->aad->info) {
audit_log_format(ab, " info=");
- audit_log_string(ab, sa->aad.info);
- if (sa->aad.error)
- audit_log_format(ab, " error=%d", sa->aad.error);
+ audit_log_string(ab, sa->aad->info);
+ if (sa->aad->error)
+ audit_log_format(ab, " error=%d", sa->aad->error);
}
- if (sa->aad.profile) {
- struct aa_profile *profile = sa->aad.profile;
+ if (sa->aad->profile) {
+ struct aa_profile *profile = sa->aad->profile;
pid_t pid;
rcu_read_lock();
pid = rcu_dereference(tsk->real_parent)->pid;
@@ -145,9 +145,9 @@
audit_log_untrustedstring(ab, profile->base.hname);
}
- if (sa->aad.name) {
+ if (sa->aad->name) {
audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, sa->aad.name);
+ audit_log_untrustedstring(ab, sa->aad->name);
}
}
@@ -159,10 +159,8 @@
void aa_audit_msg(int type, struct common_audit_data *sa,
void (*cb) (struct audit_buffer *, void *))
{
- sa->aad.type = type;
- sa->lsm_pre_audit = audit_pre;
- sa->lsm_post_audit = cb;
- common_lsm_audit(sa);
+ sa->aad->type = type;
+ common_lsm_audit(sa, audit_pre, cb);
}
/**
@@ -184,7 +182,7 @@
BUG_ON(!profile);
if (type == AUDIT_APPARMOR_AUTO) {
- if (likely(!sa->aad.error)) {
+ if (likely(!sa->aad->error)) {
if (AUDIT_MODE(profile) != AUDIT_ALL)
return 0;
type = AUDIT_APPARMOR_AUDIT;
@@ -196,21 +194,21 @@
if (AUDIT_MODE(profile) == AUDIT_QUIET ||
(type == AUDIT_APPARMOR_DENIED &&
AUDIT_MODE(profile) == AUDIT_QUIET))
- return sa->aad.error;
+ return sa->aad->error;
if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
type = AUDIT_APPARMOR_KILL;
if (!unconfined(profile))
- sa->aad.profile = profile;
+ sa->aad->profile = profile;
aa_audit_msg(type, sa, cb);
- if (sa->aad.type == AUDIT_APPARMOR_KILL)
+ if (sa->aad->type == AUDIT_APPARMOR_KILL)
(void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
- if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
- return complain_error(sa->aad.error);
+ if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
+ return complain_error(sa->aad->error);
- return sa->aad.error;
+ return sa->aad->error;
}
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 9982c48..088dba3 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -64,11 +64,13 @@
struct audit_cache *ent;
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, CAP);
+ sa.aad = &aad;
sa.tsk = task;
sa.u.cap = cap;
- sa.aad.op = OP_CAPABLE;
- sa.aad.error = error;
+ sa.aad->op = OP_CAPABLE;
+ sa.aad->error = error;
if (likely(!error)) {
/* test if auditing is being forced */
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 5d176f2..2f8fcba 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -67,22 +67,22 @@
struct common_audit_data *sa = va;
uid_t fsuid = current_fsuid();
- if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " requested_mask=");
- audit_file_mask(ab, sa->aad.fs.request);
+ audit_file_mask(ab, sa->aad->fs.request);
}
- if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.denied & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " denied_mask=");
- audit_file_mask(ab, sa->aad.fs.denied);
+ audit_file_mask(ab, sa->aad->fs.denied);
}
- if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
+ if (sa->aad->fs.request & AA_AUDIT_FILE_MASK) {
audit_log_format(ab, " fsuid=%d", fsuid);
- audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
+ audit_log_format(ab, " ouid=%d", sa->aad->fs.ouid);
}
- if (sa->aad.fs.target) {
+ if (sa->aad->fs.target) {
audit_log_format(ab, " target=");
- audit_log_untrustedstring(ab, sa->aad.fs.target);
+ audit_log_untrustedstring(ab, sa->aad->fs.target);
}
}
@@ -107,45 +107,47 @@
{
int type = AUDIT_APPARMOR_AUTO;
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = op,
- sa.aad.fs.request = request;
- sa.aad.name = name;
- sa.aad.fs.target = target;
- sa.aad.fs.ouid = ouid;
- sa.aad.info = info;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = op,
+ aad.fs.request = request;
+ aad.name = name;
+ aad.fs.target = target;
+ aad.fs.ouid = ouid;
+ aad.info = info;
+ aad.error = error;
- if (likely(!sa.aad.error)) {
+ if (likely(!sa.aad->error)) {
u32 mask = perms->audit;
if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
mask = 0xffff;
/* mask off perms that are not being force audited */
- sa.aad.fs.request &= mask;
+ sa.aad->fs.request &= mask;
- if (likely(!sa.aad.fs.request))
+ if (likely(!sa.aad->fs.request))
return 0;
type = AUDIT_APPARMOR_AUDIT;
} else {
/* only report permissions that were denied */
- sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
+ sa.aad->fs.request = sa.aad->fs.request & ~perms->allow;
- if (sa.aad.fs.request & perms->kill)
+ if (sa.aad->fs.request & perms->kill)
type = AUDIT_APPARMOR_KILL;
/* quiet known rejects, assumes quiet and kill do not overlap */
- if ((sa.aad.fs.request & perms->quiet) &&
+ if ((sa.aad->fs.request & perms->quiet) &&
AUDIT_MODE(profile) != AUDIT_NOQUIET &&
AUDIT_MODE(profile) != AUDIT_ALL)
- sa.aad.fs.request &= ~perms->quiet;
+ sa.aad->fs.request &= ~perms->quiet;
- if (!sa.aad.fs.request)
- return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
+ if (!sa.aad->fs.request)
+ return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
}
- sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
+ sa.aad->fs.denied = sa.aad->fs.request & ~perms->allow;
return aa_audit(type, profile, gfp, &sa, file_audit_cb);
}
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 4ba78c2..3868b1e 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -103,7 +103,33 @@
};
-/* define a short hand for apparmor_audit_data portion of common_audit_data */
+struct apparmor_audit_data {
+ int error;
+ int op;
+ int type;
+ void *profile;
+ const char *name;
+ const char *info;
+ union {
+ void *target;
+ struct {
+ long pos;
+ void *target;
+ } iface;
+ struct {
+ int rlim;
+ unsigned long max;
+ } rlim;
+ struct {
+ const char *target;
+ u32 request;
+ u32 denied;
+ uid_t ouid;
+ } fs;
+ };
+};
+
+/* define a short hand for apparmor_audit_data structure */
#define aad apparmor_audit_data
void aa_audit_msg(int type, struct common_audit_data *sa,
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index 7ee05c6..c3da93a 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -26,7 +26,7 @@
{
struct common_audit_data *sa = va;
audit_log_format(ab, " target=");
- audit_log_untrustedstring(ab, sa->aad.target);
+ audit_log_untrustedstring(ab, sa->aad->target);
}
/**
@@ -41,10 +41,12 @@
struct aa_profile *target, int error)
{
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_PTRACE;
- sa.aad.target = target;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = OP_PTRACE;
+ aad.target = target;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
audit_cb);
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 9516948..e75829b 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -65,8 +65,10 @@
{
if (audit_enabled) {
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.info = str;
+ sa.aad = &aad;
+ aad.info = str;
aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
}
printk(KERN_INFO "AppArmor: %s\n", str);
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 97ce8fa..ad05d39 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -588,10 +588,12 @@
error = aa_setprocattr_permipc(args);
} else {
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_SETPROCATTR;
- sa.aad.info = name;
- sa.aad.error = -EINVAL;
+ sa.aad = &aad;
+ aad.op = OP_SETPROCATTR;
+ aad.info = name;
+ aad.error = -EINVAL;
return aa_audit(AUDIT_APPARMOR_DENIED,
__aa_current_profile(), GFP_KERNEL,
&sa, NULL);
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 9064143..f1f7506 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -964,11 +964,13 @@
int error)
{
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = op;
- sa.aad.name = name;
- sa.aad.info = info;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = op;
+ aad.name = name;
+ aad.info = info;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
&sa, NULL);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 25fd51e..deab7c7 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -70,13 +70,13 @@
static void audit_cb(struct audit_buffer *ab, void *va)
{
struct common_audit_data *sa = va;
- if (sa->aad.iface.target) {
- struct aa_profile *name = sa->aad.iface.target;
+ if (sa->aad->iface.target) {
+ struct aa_profile *name = sa->aad->iface.target;
audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, name->base.hname);
}
- if (sa->aad.iface.pos)
- audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
+ if (sa->aad->iface.pos)
+ audit_log_format(ab, " offset=%ld", sa->aad->iface.pos);
}
/**
@@ -94,13 +94,15 @@
{
struct aa_profile *profile = __aa_current_profile();
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
+ sa.aad = &aad;
if (e)
- sa.aad.iface.pos = e->pos - e->start;
- sa.aad.iface.target = new;
- sa.aad.name = name;
- sa.aad.info = info;
- sa.aad.error = error;
+ aad.iface.pos = e->pos - e->start;
+ aad.iface.target = new;
+ aad.name = name;
+ aad.info = info;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
audit_cb);
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index 72c25a4f..2fe8613 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -34,7 +34,7 @@
struct common_audit_data *sa = va;
audit_log_format(ab, " rlimit=%s value=%lu",
- rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
+ rlim_names[sa->aad->rlim.rlim], sa->aad->rlim.max);
}
/**
@@ -50,12 +50,14 @@
unsigned long value, int error)
{
struct common_audit_data sa;
+ struct apparmor_audit_data aad = {0,};
COMMON_AUDIT_DATA_INIT(&sa, NONE);
- sa.aad.op = OP_SETRLIMIT,
- sa.aad.rlim.rlim = resource;
- sa.aad.rlim.max = value;
- sa.aad.error = error;
+ sa.aad = &aad;
+ aad.op = OP_SETRLIMIT,
+ aad.rlim.rlim = resource;
+ aad.rlim.max = value;
+ aad.error = error;
return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
audit_cb);
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 0cf4b53..71a166a 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -29,6 +29,7 @@
#include <linux/securebits.h>
#include <linux/user_namespace.h>
#include <linux/binfmts.h>
+#include <linux/personality.h>
/*
* If a non-root user executes a setuid-root binary in
@@ -505,6 +506,11 @@
}
skip:
+ /* if we have fs caps, clear dangerous personality flags */
+ if (!cap_issubset(new->cap_permitted, old->cap_permitted))
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+
+
/* Don't let someone trace a set[ug]id/setpcap binary with the revised
* credentials unless they have the appropriate permit
*/
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 8b8f090..90c129b 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -49,8 +49,8 @@
if (ih == NULL)
return -EINVAL;
- ad->u.net.v4info.saddr = ih->saddr;
- ad->u.net.v4info.daddr = ih->daddr;
+ ad->u.net->v4info.saddr = ih->saddr;
+ ad->u.net->v4info.daddr = ih->daddr;
if (proto)
*proto = ih->protocol;
@@ -64,8 +64,8 @@
if (th == NULL)
break;
- ad->u.net.sport = th->source;
- ad->u.net.dport = th->dest;
+ ad->u.net->sport = th->source;
+ ad->u.net->dport = th->dest;
break;
}
case IPPROTO_UDP: {
@@ -73,8 +73,8 @@
if (uh == NULL)
break;
- ad->u.net.sport = uh->source;
- ad->u.net.dport = uh->dest;
+ ad->u.net->sport = uh->source;
+ ad->u.net->dport = uh->dest;
break;
}
case IPPROTO_DCCP: {
@@ -82,16 +82,16 @@
if (dh == NULL)
break;
- ad->u.net.sport = dh->dccph_sport;
- ad->u.net.dport = dh->dccph_dport;
+ ad->u.net->sport = dh->dccph_sport;
+ ad->u.net->dport = dh->dccph_dport;
break;
}
case IPPROTO_SCTP: {
struct sctphdr *sh = sctp_hdr(skb);
if (sh == NULL)
break;
- ad->u.net.sport = sh->source;
- ad->u.net.dport = sh->dest;
+ ad->u.net->sport = sh->source;
+ ad->u.net->dport = sh->dest;
break;
}
default:
@@ -119,8 +119,8 @@
ip6 = ipv6_hdr(skb);
if (ip6 == NULL)
return -EINVAL;
- ad->u.net.v6info.saddr = ip6->saddr;
- ad->u.net.v6info.daddr = ip6->daddr;
+ ad->u.net->v6info.saddr = ip6->saddr;
+ ad->u.net->v6info.daddr = ip6->daddr;
ret = 0;
/* IPv6 can have several extension header before the Transport header
* skip them */
@@ -140,8 +140,8 @@
if (th == NULL)
break;
- ad->u.net.sport = th->source;
- ad->u.net.dport = th->dest;
+ ad->u.net->sport = th->source;
+ ad->u.net->dport = th->dest;
break;
}
case IPPROTO_UDP: {
@@ -151,8 +151,8 @@
if (uh == NULL)
break;
- ad->u.net.sport = uh->source;
- ad->u.net.dport = uh->dest;
+ ad->u.net->sport = uh->source;
+ ad->u.net->dport = uh->dest;
break;
}
case IPPROTO_DCCP: {
@@ -162,8 +162,8 @@
if (dh == NULL)
break;
- ad->u.net.sport = dh->dccph_sport;
- ad->u.net.dport = dh->dccph_dport;
+ ad->u.net->sport = dh->dccph_sport;
+ ad->u.net->dport = dh->dccph_dport;
break;
}
case IPPROTO_SCTP: {
@@ -172,8 +172,8 @@
sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
if (sh == NULL)
break;
- ad->u.net.sport = sh->source;
- ad->u.net.dport = sh->dest;
+ ad->u.net->sport = sh->source;
+ ad->u.net->dport = sh->dest;
break;
}
default:
@@ -281,8 +281,8 @@
}
break;
case LSM_AUDIT_DATA_NET:
- if (a->u.net.sk) {
- struct sock *sk = a->u.net.sk;
+ if (a->u.net->sk) {
+ struct sock *sk = a->u.net->sk;
struct unix_sock *u;
int len = 0;
char *p = NULL;
@@ -330,29 +330,29 @@
}
}
- switch (a->u.net.family) {
+ switch (a->u.net->family) {
case AF_INET:
- print_ipv4_addr(ab, a->u.net.v4info.saddr,
- a->u.net.sport,
+ print_ipv4_addr(ab, a->u.net->v4info.saddr,
+ a->u.net->sport,
"saddr", "src");
- print_ipv4_addr(ab, a->u.net.v4info.daddr,
- a->u.net.dport,
+ print_ipv4_addr(ab, a->u.net->v4info.daddr,
+ a->u.net->dport,
"daddr", "dest");
break;
case AF_INET6:
- print_ipv6_addr(ab, &a->u.net.v6info.saddr,
- a->u.net.sport,
+ print_ipv6_addr(ab, &a->u.net->v6info.saddr,
+ a->u.net->sport,
"saddr", "src");
- print_ipv6_addr(ab, &a->u.net.v6info.daddr,
- a->u.net.dport,
+ print_ipv6_addr(ab, &a->u.net->v6info.daddr,
+ a->u.net->dport,
"daddr", "dest");
break;
}
- if (a->u.net.netif > 0) {
+ if (a->u.net->netif > 0) {
struct net_device *dev;
/* NOTE: we always use init's namespace */
- dev = dev_get_by_index(&init_net, a->u.net.netif);
+ dev = dev_get_by_index(&init_net, a->u.net->netif);
if (dev) {
audit_log_format(ab, " netif=%s", dev->name);
dev_put(dev);
@@ -378,11 +378,15 @@
/**
* common_lsm_audit - generic LSM auditing function
* @a: auxiliary audit data
+ * @pre_audit: lsm-specific pre-audit callback
+ * @post_audit: lsm-specific post-audit callback
*
* setup the audit buffer for common security information
* uses callback to print LSM specific information
*/
-void common_lsm_audit(struct common_audit_data *a)
+void common_lsm_audit(struct common_audit_data *a,
+ void (*pre_audit)(struct audit_buffer *, void *),
+ void (*post_audit)(struct audit_buffer *, void *))
{
struct audit_buffer *ab;
@@ -394,13 +398,13 @@
if (ab == NULL)
return;
- if (a->lsm_pre_audit)
- a->lsm_pre_audit(ab, a);
+ if (pre_audit)
+ pre_audit(ab, a);
dump_common_audit_data(ab, a);
- if (a->lsm_post_audit)
- a->lsm_post_audit(ab, a);
+ if (post_audit)
+ post_audit(ab, a);
audit_log_end(ab);
}
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 1a70fa2..8ee42b2 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -436,9 +436,9 @@
{
struct common_audit_data *ad = a;
audit_log_format(ab, "avc: %s ",
- ad->selinux_audit_data.denied ? "denied" : "granted");
- avc_dump_av(ab, ad->selinux_audit_data.tclass,
- ad->selinux_audit_data.audited);
+ ad->selinux_audit_data->slad->denied ? "denied" : "granted");
+ avc_dump_av(ab, ad->selinux_audit_data->slad->tclass,
+ ad->selinux_audit_data->slad->audited);
audit_log_format(ab, " for ");
}
@@ -452,22 +452,25 @@
{
struct common_audit_data *ad = a;
audit_log_format(ab, " ");
- avc_dump_query(ab, ad->selinux_audit_data.ssid,
- ad->selinux_audit_data.tsid,
- ad->selinux_audit_data.tclass);
+ avc_dump_query(ab, ad->selinux_audit_data->slad->ssid,
+ ad->selinux_audit_data->slad->tsid,
+ ad->selinux_audit_data->slad->tclass);
}
/* This is the slow part of avc audit with big stack footprint */
static noinline int slow_avc_audit(u32 ssid, u32 tsid, u16 tclass,
u32 requested, u32 audited, u32 denied,
- struct av_decision *avd, struct common_audit_data *a,
+ struct common_audit_data *a,
unsigned flags)
{
struct common_audit_data stack_data;
+ struct selinux_audit_data sad = {0,};
+ struct selinux_late_audit_data slad;
if (!a) {
a = &stack_data;
COMMON_AUDIT_DATA_INIT(a, NONE);
+ a->selinux_audit_data = &sad;
}
/*
@@ -481,15 +484,15 @@
(flags & MAY_NOT_BLOCK))
return -ECHILD;
- a->selinux_audit_data.tclass = tclass;
- a->selinux_audit_data.requested = requested;
- a->selinux_audit_data.ssid = ssid;
- a->selinux_audit_data.tsid = tsid;
- a->selinux_audit_data.audited = audited;
- a->selinux_audit_data.denied = denied;
- a->lsm_pre_audit = avc_audit_pre_callback;
- a->lsm_post_audit = avc_audit_post_callback;
- common_lsm_audit(a);
+ slad.tclass = tclass;
+ slad.requested = requested;
+ slad.ssid = ssid;
+ slad.tsid = tsid;
+ slad.audited = audited;
+ slad.denied = denied;
+
+ a->selinux_audit_data->slad = &slad;
+ common_lsm_audit(a, avc_audit_pre_callback, avc_audit_post_callback);
return 0;
}
@@ -523,7 +526,7 @@
if (unlikely(denied)) {
audited = denied & avd->auditdeny;
/*
- * a->selinux_audit_data.auditdeny is TRICKY! Setting a bit in
+ * a->selinux_audit_data->auditdeny is TRICKY! Setting a bit in
* this field means that ANY denials should NOT be audited if
* the policy contains an explicit dontaudit rule for that
* permission. Take notice that this is unrelated to the
@@ -532,15 +535,15 @@
*
* denied == READ
* avd.auditdeny & ACCESS == 0 (not set means explicit rule)
- * selinux_audit_data.auditdeny & ACCESS == 1
+ * selinux_audit_data->auditdeny & ACCESS == 1
*
* We will NOT audit the denial even though the denied
* permission was READ and the auditdeny checks were for
* ACCESS
*/
if (a &&
- a->selinux_audit_data.auditdeny &&
- !(a->selinux_audit_data.auditdeny & avd->auditdeny))
+ a->selinux_audit_data->auditdeny &&
+ !(a->selinux_audit_data->auditdeny & avd->auditdeny))
audited = 0;
} else if (result)
audited = denied = requested;
@@ -551,7 +554,7 @@
return slow_avc_audit(ssid, tsid, tclass,
requested, audited, denied,
- avd, a, flags);
+ a, flags);
}
/**
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 28482f9..d85b793 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1420,6 +1420,7 @@
int cap, int audit)
{
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
struct av_decision avd;
u16 sclass;
u32 sid = cred_sid(cred);
@@ -1427,6 +1428,7 @@
int rc;
COMMON_AUDIT_DATA_INIT(&ad, CAP);
+ ad.selinux_audit_data = &sad;
ad.tsk = current;
ad.u.cap = cap;
@@ -1492,9 +1494,11 @@
unsigned flags)
{
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, INODE);
ad.u.inode = inode;
+ ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, perms, &ad, flags);
}
@@ -1507,9 +1511,11 @@
{
struct inode *inode = dentry->d_inode;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry;
+ ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0);
}
@@ -1522,9 +1528,11 @@
{
struct inode *inode = path->dentry->d_inode;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, PATH);
ad.u.path = *path;
+ ad.selinux_audit_data = &sad;
return inode_has_perm(cred, inode, av, &ad, 0);
}
@@ -1543,11 +1551,13 @@
struct file_security_struct *fsec = file->f_security;
struct inode *inode = file->f_path.dentry->d_inode;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = cred_sid(cred);
int rc;
COMMON_AUDIT_DATA_INIT(&ad, PATH);
ad.u.path = file->f_path;
+ ad.selinux_audit_data = &sad;
if (sid != fsec->sid) {
rc = avc_has_perm(sid, fsec->sid,
@@ -1577,6 +1587,7 @@
struct superblock_security_struct *sbsec;
u32 sid, newsid;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
int rc;
dsec = dir->i_security;
@@ -1587,6 +1598,7 @@
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry;
+ ad.selinux_audit_data = &sad;
rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
DIR__ADD_NAME | DIR__SEARCH,
@@ -1631,6 +1643,7 @@
{
struct inode_security_struct *dsec, *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
u32 av;
int rc;
@@ -1640,6 +1653,7 @@
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
ad.u.dentry = dentry;
+ ad.selinux_audit_data = &sad;
av = DIR__SEARCH;
av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1674,6 +1688,7 @@
{
struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
u32 av;
int old_is_dir, new_is_dir;
@@ -1685,6 +1700,7 @@
new_dsec = new_dir->i_security;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.selinux_audit_data = &sad;
ad.u.dentry = old_dentry;
rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
@@ -1970,6 +1986,7 @@
struct task_security_struct *new_tsec;
struct inode_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
struct inode *inode = bprm->file->f_path.dentry->d_inode;
int rc;
@@ -2009,6 +2026,7 @@
}
COMMON_AUDIT_DATA_INIT(&ad, PATH);
+ ad.selinux_audit_data = &sad;
ad.u.path = bprm->file->f_path;
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
@@ -2098,6 +2116,7 @@
struct files_struct *files)
{
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
struct file *file, *devnull = NULL;
struct tty_struct *tty;
struct fdtable *fdt;
@@ -2135,6 +2154,7 @@
/* Revalidate access to inherited open files. */
COMMON_AUDIT_DATA_INIT(&ad, INODE);
+ ad.selinux_audit_data = &sad;
spin_lock(&files->file_lock);
for (;;) {
@@ -2472,6 +2492,7 @@
{
const struct cred *cred = current_cred();
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
int rc;
rc = superblock_doinit(sb, data);
@@ -2483,6 +2504,7 @@
return 0;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.selinux_audit_data = &sad;
ad.u.dentry = sb->s_root;
return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
}
@@ -2491,8 +2513,10 @@
{
const struct cred *cred = current_cred();
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.selinux_audit_data = &sad;
ad.u.dentry = dentry->d_sb->s_root;
return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
}
@@ -2656,6 +2680,7 @@
{
const struct cred *cred = current_cred();
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 perms;
bool from_access;
unsigned flags = mask & MAY_NOT_BLOCK;
@@ -2668,10 +2693,11 @@
return 0;
COMMON_AUDIT_DATA_INIT(&ad, INODE);
+ ad.selinux_audit_data = &sad;
ad.u.inode = inode;
if (from_access)
- ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
+ ad.selinux_audit_data->auditdeny |= FILE__AUDIT_ACCESS;
perms = file_mask_to_av(inode->i_mode, mask);
@@ -2737,6 +2763,7 @@
struct inode_security_struct *isec = inode->i_security;
struct superblock_security_struct *sbsec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 newsid, sid = current_sid();
int rc = 0;
@@ -2751,6 +2778,7 @@
return -EPERM;
COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+ ad.selinux_audit_data = &sad;
ad.u.dentry = dentry;
rc = avc_has_perm(sid, isec->sid, isec->sclass,
@@ -3345,10 +3373,12 @@
{
u32 sid;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
sid = task_sid(current);
COMMON_AUDIT_DATA_INIT(&ad, KMOD);
+ ad.selinux_audit_data = &sad;
ad.u.kmod_name = kmod_name;
return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM,
@@ -3487,8 +3517,8 @@
if (ihlen < sizeof(_iph))
goto out;
- ad->u.net.v4info.saddr = ih->saddr;
- ad->u.net.v4info.daddr = ih->daddr;
+ ad->u.net->v4info.saddr = ih->saddr;
+ ad->u.net->v4info.daddr = ih->daddr;
ret = 0;
if (proto)
@@ -3506,8 +3536,8 @@
if (th == NULL)
break;
- ad->u.net.sport = th->source;
- ad->u.net.dport = th->dest;
+ ad->u.net->sport = th->source;
+ ad->u.net->dport = th->dest;
break;
}
@@ -3522,8 +3552,8 @@
if (uh == NULL)
break;
- ad->u.net.sport = uh->source;
- ad->u.net.dport = uh->dest;
+ ad->u.net->sport = uh->source;
+ ad->u.net->dport = uh->dest;
break;
}
@@ -3538,8 +3568,8 @@
if (dh == NULL)
break;
- ad->u.net.sport = dh->dccph_sport;
- ad->u.net.dport = dh->dccph_dport;
+ ad->u.net->sport = dh->dccph_sport;
+ ad->u.net->dport = dh->dccph_dport;
break;
}
@@ -3566,8 +3596,8 @@
if (ip6 == NULL)
goto out;
- ad->u.net.v6info.saddr = ip6->saddr;
- ad->u.net.v6info.daddr = ip6->daddr;
+ ad->u.net->v6info.saddr = ip6->saddr;
+ ad->u.net->v6info.daddr = ip6->daddr;
ret = 0;
nexthdr = ip6->nexthdr;
@@ -3587,8 +3617,8 @@
if (th == NULL)
break;
- ad->u.net.sport = th->source;
- ad->u.net.dport = th->dest;
+ ad->u.net->sport = th->source;
+ ad->u.net->dport = th->dest;
break;
}
@@ -3599,8 +3629,8 @@
if (uh == NULL)
break;
- ad->u.net.sport = uh->source;
- ad->u.net.dport = uh->dest;
+ ad->u.net->sport = uh->source;
+ ad->u.net->dport = uh->dest;
break;
}
@@ -3611,8 +3641,8 @@
if (dh == NULL)
break;
- ad->u.net.sport = dh->dccph_sport;
- ad->u.net.dport = dh->dccph_dport;
+ ad->u.net->sport = dh->dccph_sport;
+ ad->u.net->dport = dh->dccph_dport;
break;
}
@@ -3632,13 +3662,13 @@
char *addrp;
int ret;
- switch (ad->u.net.family) {
+ switch (ad->u.net->family) {
case PF_INET:
ret = selinux_parse_skb_ipv4(skb, ad, proto);
if (ret)
goto parse_error;
- addrp = (char *)(src ? &ad->u.net.v4info.saddr :
- &ad->u.net.v4info.daddr);
+ addrp = (char *)(src ? &ad->u.net->v4info.saddr :
+ &ad->u.net->v4info.daddr);
goto okay;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -3646,8 +3676,8 @@
ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret)
goto parse_error;
- addrp = (char *)(src ? &ad->u.net.v6info.saddr :
- &ad->u.net.v6info.daddr);
+ addrp = (char *)(src ? &ad->u.net->v6info.saddr :
+ &ad->u.net->v6info.daddr);
goto okay;
#endif /* IPV6 */
default:
@@ -3721,13 +3751,17 @@
{
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
u32 tsid = task_sid(task);
if (sksec->sid == SECINITSID_KERNEL)
return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.sk = sk;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->sk = sk;
return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad);
}
@@ -3805,6 +3839,8 @@
char *addrp;
struct sk_security_struct *sksec = sk->sk_security;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
@@ -3831,8 +3867,10 @@
if (err)
goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.sport = htons(snum);
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->sport = htons(snum);
+ ad.u.net->family = family;
err = avc_has_perm(sksec->sid, sid,
sksec->sclass,
SOCKET__NAME_BIND, &ad);
@@ -3864,13 +3902,15 @@
goto out;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.sport = htons(snum);
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->sport = htons(snum);
+ ad.u.net->family = family;
if (family == PF_INET)
- ad.u.net.v4info.saddr = addr4->sin_addr.s_addr;
+ ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
else
- ad.u.net.v6info.saddr = addr6->sin6_addr;
+ ad.u.net->v6info.saddr = addr6->sin6_addr;
err = avc_has_perm(sksec->sid, sid,
sksec->sclass, node_perm, &ad);
@@ -3897,6 +3937,8 @@
if (sksec->sclass == SECCLASS_TCP_SOCKET ||
sksec->sclass == SECCLASS_DCCP_SOCKET) {
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
struct sockaddr_in *addr4 = NULL;
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
@@ -3922,8 +3964,10 @@
TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.dport = htons(snum);
- ad.u.net.family = sk->sk_family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->dport = htons(snum);
+ ad.u.net->family = sk->sk_family;
err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
if (err)
goto out;
@@ -4012,10 +4056,14 @@
struct sk_security_struct *sksec_other = other->sk_security;
struct sk_security_struct *sksec_new = newsk->sk_security;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
int err;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.sk = other;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->sk = other;
err = avc_has_perm(sksec_sock->sid, sksec_other->sid,
sksec_other->sclass,
@@ -4042,9 +4090,13 @@
struct sk_security_struct *ssec = sock->sk->sk_security;
struct sk_security_struct *osec = other->sk->sk_security;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.sk = other->sk;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->sk = other->sk;
return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO,
&ad);
@@ -4080,11 +4132,15 @@
struct sk_security_struct *sksec = sk->sk_security;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
char *addrp;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = skb->skb_iif;
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->netif = skb->skb_iif;
+ ad.u.net->family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
if (err)
return err;
@@ -4111,6 +4167,8 @@
u16 family = sk->sk_family;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
char *addrp;
u8 secmark_active;
u8 peerlbl_active;
@@ -4135,8 +4193,10 @@
return 0;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = skb->skb_iif;
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->netif = skb->skb_iif;
+ ad.u.net->family = family;
err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
if (err)
return err;
@@ -4471,6 +4531,8 @@
char *addrp;
u32 peer_sid;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
u8 secmark_active;
u8 netlbl_active;
u8 peerlbl_active;
@@ -4488,8 +4550,10 @@
return NF_DROP;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = ifindex;
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->netif = ifindex;
+ ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
return NF_DROP;
@@ -4576,6 +4640,8 @@
struct sock *sk = skb->sk;
struct sk_security_struct *sksec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
char *addrp;
u8 proto;
@@ -4584,8 +4650,10 @@
sksec = sk->sk_security;
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = ifindex;
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->netif = ifindex;
+ ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
return NF_DROP;
@@ -4607,6 +4675,8 @@
u32 peer_sid;
struct sock *sk;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
+ struct lsm_network_audit net = {0,};
char *addrp;
u8 secmark_active;
u8 peerlbl_active;
@@ -4653,8 +4723,10 @@
}
COMMON_AUDIT_DATA_INIT(&ad, NET);
- ad.u.net.netif = ifindex;
- ad.u.net.family = family;
+ ad.selinux_audit_data = &sad;
+ ad.u.net = &net;
+ ad.u.net->netif = ifindex;
+ ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
return NF_DROP;
@@ -4769,11 +4841,13 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = ipc_perms->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = ipc_perms->key;
return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad);
@@ -4794,6 +4868,7 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -4804,6 +4879,7 @@
isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4824,11 +4900,13 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = msq->q_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ,
@@ -4868,6 +4946,7 @@
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -4889,6 +4968,7 @@
}
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key;
/* Can this process write to the queue? */
@@ -4913,6 +4993,7 @@
struct ipc_security_struct *isec;
struct msg_security_struct *msec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = task_sid(target);
int rc;
@@ -4920,6 +5001,7 @@
msec = msg->security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = msq->q_perm.key;
rc = avc_has_perm(sid, isec->sid,
@@ -4935,6 +5017,7 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -4945,6 +5028,7 @@
isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -4965,11 +5049,13 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = shp->shm_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = shp->shm_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SHM,
@@ -5027,6 +5113,7 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
int rc;
@@ -5037,6 +5124,7 @@
isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key;
rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM,
@@ -5057,11 +5145,13 @@
{
struct ipc_security_struct *isec;
struct common_audit_data ad;
+ struct selinux_audit_data sad = {0,};
u32 sid = current_sid();
isec = sma->sem_perm.security;
COMMON_AUDIT_DATA_INIT(&ad, IPC);
+ ad.selinux_audit_data = &sad;
ad.u.ipc_id = sma->sem_perm.key;
return avc_has_perm(sid, isec->sid, SECCLASS_SEM,
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 005a91b..1931370 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -47,6 +47,31 @@
};
/*
+ * We only need this data after we have decided to send an audit message.
+ */
+struct selinux_late_audit_data {
+ u32 ssid;
+ u32 tsid;
+ u16 tclass;
+ u32 requested;
+ u32 audited;
+ u32 denied;
+ int result;
+};
+
+/*
+ * We collect this at the beginning or during an selinux security operation
+ */
+struct selinux_audit_data {
+ /*
+ * auditdeny is a bit tricky and unintuitive. See the
+ * comments in avc.c for it's meaning and usage.
+ */
+ u32 auditdeny;
+ struct selinux_late_audit_data *slad;
+};
+
+/*
* AVC operations
*/
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 2ad0065..4ede719 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -185,6 +185,15 @@
*/
#define SMK_NUM_ACCESS_TYPE 5
+/* SMACK data */
+struct smack_audit_data {
+ const char *function;
+ char *subject;
+ char *object;
+ char *request;
+ int result;
+};
+
/*
* Smack audit data; is empty if CONFIG_AUDIT not set
* to save some stack
@@ -192,6 +201,7 @@
struct smk_audit_info {
#ifdef CONFIG_AUDIT
struct common_audit_data a;
+ struct smack_audit_data sad;
#endif
};
/*
@@ -311,7 +321,16 @@
{
memset(a, 0, sizeof(*a));
a->a.type = type;
- a->a.smack_audit_data.function = func;
+ a->a.smack_audit_data = &a->sad;
+ a->a.smack_audit_data->function = func;
+}
+
+static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func,
+ char type, struct lsm_network_audit *net)
+{
+ smk_ad_init(a, func, type);
+ memset(net, 0, sizeof(*net));
+ a->a.u.net = net;
}
static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a,
@@ -337,7 +356,7 @@
static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a,
struct sock *sk)
{
- a->a.u.net.sk = sk;
+ a->a.u.net->sk = sk;
}
#else /* no AUDIT */
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index cc7cb6e..c8115f7 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -275,9 +275,9 @@
static void smack_log_callback(struct audit_buffer *ab, void *a)
{
struct common_audit_data *ad = a;
- struct smack_audit_data *sad = &ad->smack_audit_data;
+ struct smack_audit_data *sad = ad->smack_audit_data;
audit_log_format(ab, "lsm=SMACK fn=%s action=%s",
- ad->smack_audit_data.function,
+ ad->smack_audit_data->function,
sad->result ? "denied" : "granted");
audit_log_format(ab, " subject=");
audit_log_untrustedstring(ab, sad->subject);
@@ -310,19 +310,19 @@
if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
return;
- if (a->smack_audit_data.function == NULL)
- a->smack_audit_data.function = "unknown";
+ sad = a->smack_audit_data;
+
+ if (sad->function == NULL)
+ sad->function = "unknown";
/* end preparing the audit data */
- sad = &a->smack_audit_data;
smack_str_from_perm(request_buffer, request);
sad->subject = subject_label;
sad->object = object_label;
sad->request = request_buffer;
sad->result = result;
- a->lsm_pre_audit = smack_log_callback;
- common_lsm_audit(a);
+ common_lsm_audit(a, smack_log_callback, NULL);
}
#else /* #ifdef CONFIG_AUDIT */
void smack_log(char *subject_label, char *object_label, int request,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cd667b4..45c32f0 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1943,13 +1943,15 @@
rcu_read_lock();
hostsp = smack_host_label(sap);
if (hostsp != NULL) {
- sk_lbl = SMACK_UNLABELED_SOCKET;
#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
- ad.a.u.net.family = sap->sin_family;
- ad.a.u.net.dport = sap->sin_port;
- ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr;
+ struct lsm_network_audit net;
+
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+ ad.a.u.net->family = sap->sin_family;
+ ad.a.u.net->dport = sap->sin_port;
+ ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
#endif
+ sk_lbl = SMACK_UNLABELED_SOCKET;
rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad);
} else {
sk_lbl = SMACK_CIPSO_SOCKET;
@@ -2810,8 +2812,12 @@
struct smk_audit_info ad;
int rc = 0;
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+#ifdef CONFIG_AUDIT
+ struct lsm_network_audit net;
+
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
smk_ad_setfield_u_net_sk(&ad, other);
+#endif
if (!capable(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@ -2842,8 +2848,12 @@
struct smk_audit_info ad;
int rc = 0;
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
+#ifdef CONFIG_AUDIT
+ struct lsm_network_audit net;
+
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
smk_ad_setfield_u_net_sk(&ad, other->sk);
+#endif
if (!capable(CAP_MAC_OVERRIDE))
rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
@@ -2990,6 +3000,9 @@
char *csp;
int rc;
struct smk_audit_info ad;
+#ifdef CONFIG_AUDIT
+ struct lsm_network_audit net;
+#endif
if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
return 0;
@@ -3007,9 +3020,9 @@
netlbl_secattr_destroy(&secattr);
#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
- ad.a.u.net.family = sk->sk_family;
- ad.a.u.net.netif = skb->skb_iif;
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+ ad.a.u.net->family = sk->sk_family;
+ ad.a.u.net->netif = skb->skb_iif;
ipv4_skb_to_auditdata(skb, &ad.a, NULL);
#endif
/*
@@ -3152,6 +3165,9 @@
char *sp;
int rc;
struct smk_audit_info ad;
+#ifdef CONFIG_AUDIT
+ struct lsm_network_audit net;
+#endif
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -3166,9 +3182,9 @@
netlbl_secattr_destroy(&secattr);
#ifdef CONFIG_AUDIT
- smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
- ad.a.u.net.family = family;
- ad.a.u.net.netif = skb->skb_iif;
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+ ad.a.u.net->family = family;
+ ad.a.u.net->netif = skb->skb_iif;
ipv4_skb_to_auditdata(skb, &ad.a, NULL);
#endif
/*
@@ -3624,8 +3640,38 @@
};
-static __init void init_smack_know_list(void)
+static __init void init_smack_known_list(void)
{
+ /*
+ * Initialize CIPSO locks
+ */
+ spin_lock_init(&smack_known_huh.smk_cipsolock);
+ spin_lock_init(&smack_known_hat.smk_cipsolock);
+ spin_lock_init(&smack_known_star.smk_cipsolock);
+ spin_lock_init(&smack_known_floor.smk_cipsolock);
+ spin_lock_init(&smack_known_invalid.smk_cipsolock);
+ spin_lock_init(&smack_known_web.smk_cipsolock);
+ /*
+ * Initialize rule list locks
+ */
+ mutex_init(&smack_known_huh.smk_rules_lock);
+ mutex_init(&smack_known_hat.smk_rules_lock);
+ mutex_init(&smack_known_floor.smk_rules_lock);
+ mutex_init(&smack_known_star.smk_rules_lock);
+ mutex_init(&smack_known_invalid.smk_rules_lock);
+ mutex_init(&smack_known_web.smk_rules_lock);
+ /*
+ * Initialize rule lists
+ */
+ INIT_LIST_HEAD(&smack_known_huh.smk_rules);
+ INIT_LIST_HEAD(&smack_known_hat.smk_rules);
+ INIT_LIST_HEAD(&smack_known_star.smk_rules);
+ INIT_LIST_HEAD(&smack_known_floor.smk_rules);
+ INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
+ INIT_LIST_HEAD(&smack_known_web.smk_rules);
+ /*
+ * Create the known labels list
+ */
list_add(&smack_known_huh.list, &smack_known_list);
list_add(&smack_known_hat.list, &smack_known_list);
list_add(&smack_known_star.list, &smack_known_list);
@@ -3660,16 +3706,8 @@
cred = (struct cred *) current->cred;
cred->security = tsp;
- /* initialize the smack_know_list */
- init_smack_know_list();
- /*
- * Initialize locks
- */
- spin_lock_init(&smack_known_huh.smk_cipsolock);
- spin_lock_init(&smack_known_hat.smk_cipsolock);
- spin_lock_init(&smack_known_star.smk_cipsolock);
- spin_lock_init(&smack_known_floor.smk_cipsolock);
- spin_lock_init(&smack_known_invalid.smk_cipsolock);
+ /* initialize the smack_known_list */
+ init_smack_known_list();
/*
* Register with LSM
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 5c32f36..038811c 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -1614,20 +1614,6 @@
smk_cipso_doi();
smk_unlbl_ambient(NULL);
- mutex_init(&smack_known_floor.smk_rules_lock);
- mutex_init(&smack_known_hat.smk_rules_lock);
- mutex_init(&smack_known_huh.smk_rules_lock);
- mutex_init(&smack_known_invalid.smk_rules_lock);
- mutex_init(&smack_known_star.smk_rules_lock);
- mutex_init(&smack_known_web.smk_rules_lock);
-
- INIT_LIST_HEAD(&smack_known_floor.smk_rules);
- INIT_LIST_HEAD(&smack_known_hat.smk_rules);
- INIT_LIST_HEAD(&smack_known_huh.smk_rules);
- INIT_LIST_HEAD(&smack_known_invalid.smk_rules);
- INIT_LIST_HEAD(&smack_known_star.smk_rules);
- INIT_LIST_HEAD(&smack_known_web.smk_rules);
-
return err;
}
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 8816804..5ca0939 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -2,8 +2,8 @@
config SND_TEA575X
tristate
- depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2
- default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2
+ depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO
+ default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO
menuconfig SND_PCI
bool "PCI sound devices"
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 6508e8b..59d8efa 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -57,7 +57,7 @@
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
select SND_SOC_TWL4030 if TWL4030_CORE
- select SND_SOC_TWL6040 if TWL4030_CORE
+ select SND_SOC_TWL6040 if TWL6040_CORE
select SND_SOC_UDA134X
select SND_SOC_UDA1380 if I2C
select SND_SOC_WL1273 if MFD_WL1273_CORE
@@ -276,7 +276,6 @@
tristate
config SND_SOC_TWL6040
- select TWL6040_CORE
tristate
config SND_SOC_UDA134X
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 2d8c6b8..dc7509b 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -26,7 +26,6 @@
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/i2c/twl.h>
#include <linux/mfd/twl6040.h>
#include <sound/core.h>
@@ -1528,7 +1527,7 @@
static int twl6040_probe(struct snd_soc_codec *codec)
{
struct twl6040_data *priv;
- struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev);
+ struct twl6040_codec_data *pdata = dev_get_platdata(codec->dev);
struct platform_device *pdev = container_of(codec->dev,
struct platform_device, dev);
int ret = 0;
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index afbabf4..3fea5a1 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -58,9 +58,9 @@
{
struct mpc8610_hpcd_data *machine_data =
container_of(card, struct mpc8610_hpcd_data, card);
- struct ccsr_guts_86xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
- guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
if (!guts) {
dev_err(card->dev, "could not map global utilities\n");
return -ENOMEM;
@@ -142,9 +142,9 @@
{
struct mpc8610_hpcd_data *machine_data =
container_of(card, struct mpc8610_hpcd_data, card);
- struct ccsr_guts_86xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
- guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
if (!guts) {
dev_err(card->dev, "could not map global utilities\n");
return -ENOMEM;
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index 4662340..982a1c9 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -46,7 +46,7 @@
* ch: The channel on the DMA controller (0, 1, 2, or 3)
* device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
*/
-static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts,
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
unsigned int co, unsigned int ch, unsigned int device)
{
unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -90,9 +90,9 @@
{
struct machine_data *mdata =
container_of(card, struct machine_data, card);
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
- guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
if (!guts) {
dev_err(card->dev, "could not map global utilities\n");
return -ENOMEM;
@@ -164,9 +164,9 @@
{
struct machine_data *mdata =
container_of(card, struct machine_data, card);
- struct ccsr_guts_85xx __iomem *guts;
+ struct ccsr_guts __iomem *guts;
- guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
+ guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
if (!guts) {
dev_err(card->dev, "could not map global utilities\n");
return -ENOMEM;
diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c
index 0fe66c3..f237003 100644
--- a/sound/soc/imx/imx-audmux.c
+++ b/sound/soc/imx/imx-audmux.c
@@ -40,12 +40,6 @@
#ifdef CONFIG_DEBUG_FS
static struct dentry *audmux_debugfs_root;
-static int audmux_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
/* There is an annoying discontinuity in the SSI numbering with regard
* to the Linux number of the devices */
static const char *audmux_port_string(int port)
@@ -145,7 +139,7 @@
}
static const struct file_operations audmux_debugfs_fops = {
- .open = audmux_open_file,
+ .open = simple_open,
.read = audmux_read_file,
.llseek = default_llseek,
};
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index e00dd0b..deafbfa 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -97,7 +97,7 @@
config SND_OMAP_SOC_OMAP_ABE_TWL6040
tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
- depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4
+ depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4
select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b390f00..c88d974 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -201,12 +201,6 @@
static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set);
#ifdef CONFIG_DEBUG_FS
-static int codec_reg_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -264,7 +258,7 @@
}
static const struct file_operations codec_reg_fops = {
- .open = codec_reg_open_file,
+ .open = simple_open,
.read = codec_reg_read_file,
.write = codec_reg_write_file,
.llseek = default_llseek,
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index dc7dbfe..1bb6d4a 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1546,12 +1546,6 @@
}
#ifdef CONFIG_DEBUG_FS
-static int dapm_widget_power_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t dapm_widget_power_read_file(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1615,17 +1609,11 @@
}
static const struct file_operations dapm_widget_power_fops = {
- .open = dapm_widget_power_open_file,
+ .open = simple_open,
.read = dapm_widget_power_read_file,
.llseek = default_llseek,
};
-static int dapm_bias_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t dapm_bias_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1656,7 +1644,7 @@
}
static const struct file_operations dapm_bias_fops = {
- .open = dapm_bias_open_file,
+ .open = simple_open,
.read = dapm_bias_read_file,
.llseek = default_llseek,
};
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 416684b..26b823b 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -19,3 +19,5 @@
cscope*
config.mak
config.mak.autogen
+*-bison.*
+*-flex.*
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 820371f..9bf3fc7 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -234,24 +234,23 @@
export PERL_PATH
-FLEX = $(CROSS_COMPILE)flex
-BISON= $(CROSS_COMPILE)bison
+FLEX = flex
+BISON= bison
-event-parser:
- $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/parse-events-flex.c: util/parse-events.l
$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
-$(OUTPUT)util/parse-events-flex.c: event-parser
-$(OUTPUT)util/parse-events-bison.c: event-parser
+$(OUTPUT)util/parse-events-bison.c: util/parse-events.y
+ $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c
-pmu-parser:
- $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
+$(OUTPUT)util/pmu-flex.c: util/pmu.l
$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
-$(OUTPUT)util/pmu-flex.c: pmu-parser
-$(OUTPUT)util/pmu-bison.c: pmu-parser
+$(OUTPUT)util/pmu-bison.c: util/pmu.y
+ $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c
-$(OUTPUT)util/parse-events.o: event-parser pmu-parser
+$(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c
+$(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c
LIB_FILE=$(OUTPUT)libperf.a
@@ -527,7 +526,7 @@
endif
ifdef NO_GTK2
- BASIC_CFLAGS += -DNO_GTK2
+ BASIC_CFLAGS += -DNO_GTK2_SUPPORT
else
FLAGS_GTK2=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS) $(shell pkg-config --libs --cflags gtk+-2.0)
ifneq ($(call try-cc,$(SOURCE_GTK2),$(FLAGS_GTK2)),y)
@@ -852,8 +851,6 @@
@echo ' html - make html documentation'
@echo ' info - make GNU info documentation (access with info <foo>)'
@echo ' pdf - make pdf documentation'
- @echo ' event-parser - make event parser code'
- @echo ' pmu-parser - make pmu format parser code'
@echo ' TAGS - use etags to make tag information for source browsing'
@echo ' tags - use ctags to make tag information for source browsing'
@echo ' cscope - use cscope to make interactive browsing database'
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 2e31743..cdae9b2 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -374,16 +374,23 @@
(kernel_map->dso->hit &&
(kernel_kmap->ref_reloc_sym == NULL ||
kernel_kmap->ref_reloc_sym->addr == 0))) {
- const struct dso *kdso = kernel_map->dso;
+ const char *desc =
+ "As no suitable kallsyms nor vmlinux was found, kernel samples\n"
+ "can't be resolved.";
+
+ if (kernel_map) {
+ const struct dso *kdso = kernel_map->dso;
+ if (!RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION])) {
+ desc = "If some relocation was applied (e.g. "
+ "kexec) symbols may be misresolved.";
+ }
+ }
ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) were restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict before running 'perf record'.\n\n%s\n\n"
"Samples in kernel modules can't be resolved as well.\n\n",
- RB_EMPTY_ROOT(&kdso->symbols[MAP__FUNCTION]) ?
-"As no suitable kallsyms nor vmlinux was found, kernel samples\n"
-"can't be resolved." :
-"If some relocation was applied (e.g. kexec) symbols may be misresolved.");
+ desc);
}
if (dump_trace) {
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index fb8b5f8..1cad3af 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -17,6 +17,7 @@
#include "util/debug.h"
#include <sys/prctl.h>
+#include <sys/resource.h>
#include <semaphore.h>
#include <pthread.h>
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1c5b980..223ffdc 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -851,6 +851,28 @@
return test__checkevent_symbolic_name(evlist);
}
+static int test__checkevent_exclude_host_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", evsel->attr.exclude_host);
+
+ return test__checkevent_symbolic_name(evlist);
+}
+
+static int test__checkevent_exclude_guest_modifier(struct perf_evlist *evlist)
+{
+ struct perf_evsel *evsel = list_entry(evlist->entries.next,
+ struct perf_evsel, node);
+
+ TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
+ TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
+
+ return test__checkevent_symbolic_name(evlist);
+}
+
static int test__checkevent_symbolic_alias_modifier(struct perf_evlist *evlist)
{
struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -1091,6 +1113,14 @@
.name = "r1,syscalls:sys_enter_open:k,1:1:hp",
.check = test__checkevent_list,
},
+ {
+ .name = "instructions:G",
+ .check = test__checkevent_exclude_host_modifier,
+ },
+ {
+ .name = "instructions:H",
+ .check = test__checkevent_exclude_guest_modifier,
+ },
};
#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e3c63ae..8ef59f8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -42,6 +42,7 @@
#include "util/debug.h"
#include <assert.h>
+#include <elf.h>
#include <fcntl.h>
#include <stdio.h>
@@ -59,6 +60,7 @@
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/uio.h>
+#include <sys/utsname.h>
#include <sys/mman.h>
#include <linux/unistd.h>
@@ -162,12 +164,40 @@
symbol__annotate_zero_histograms(sym);
}
+static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
+{
+ struct utsname uts;
+ int err = uname(&uts);
+
+ ui__warning("Out of bounds address found:\n\n"
+ "Addr: %" PRIx64 "\n"
+ "DSO: %s %c\n"
+ "Map: %" PRIx64 "-%" PRIx64 "\n"
+ "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
+ "Arch: %s\n"
+ "Kernel: %s\n"
+ "Tools: %s\n\n"
+ "Not all samples will be on the annotation output.\n\n"
+ "Please report to linux-kernel@vger.kernel.org\n",
+ ip, map->dso->long_name, dso__symtab_origin(map->dso),
+ map->start, map->end, sym->start, sym->end,
+ sym->binding == STB_GLOBAL ? 'g' :
+ sym->binding == STB_LOCAL ? 'l' : 'w', sym->name,
+ err ? "[unknown]" : uts.machine,
+ err ? "[unknown]" : uts.release, perf_version_string);
+ if (use_browser <= 0)
+ sleep(5);
+
+ map->erange_warned = true;
+}
+
static void perf_top__record_precise_ip(struct perf_top *top,
struct hist_entry *he,
int counter, u64 ip)
{
struct annotation *notes;
struct symbol *sym;
+ int err;
if (he == NULL || he->ms.sym == NULL ||
((top->sym_filter_entry == NULL ||
@@ -189,9 +219,12 @@
}
ip = he->ms.map->map_ip(he->ms.map, ip);
- symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
+ err = symbol__inc_addr_samples(sym, he->ms.map, counter, ip);
pthread_mutex_unlock(¬es->lock);
+
+ if (err == -ERANGE && !he->ms.map->erange_warned)
+ ui__warn_map_erange(he->ms.map, sym, ip);
}
static void perf_top__show_details(struct perf_top *top)
@@ -615,6 +648,7 @@
/* Tag samples to be skipped. */
static const char *skip_symbols[] = {
+ "intel_idle",
"default_idle",
"native_safe_halt",
"cpu_idle",
diff --git a/tools/perf/perf-archive.sh b/tools/perf/perf-archive.sh
index 677e59d..95b6f8b 100644
--- a/tools/perf/perf-archive.sh
+++ b/tools/perf/perf-archive.sh
@@ -29,13 +29,14 @@
fi
MANIFEST=$(mktemp /tmp/perf-archive-manifest.XXXXXX)
+PERF_BUILDID_LINKDIR=$(readlink -f $PERF_BUILDID_DIR)/
cut -d ' ' -f 1 $BUILDIDS | \
while read build_id ; do
linkname=$PERF_BUILDID_DIR.build-id/${build_id:0:2}/${build_id:2}
filename=$(readlink -f $linkname)
echo ${linkname#$PERF_BUILDID_DIR} >> $MANIFEST
- echo ${filename#$PERF_BUILDID_DIR} >> $MANIFEST
+ echo ${filename#$PERF_BUILDID_LINKDIR} >> $MANIFEST
done
tar cfj $PERF_DATA.tar.bz2 -C $PERF_BUILDID_DIR -T $MANIFEST
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 199f69e..08c6d13 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -64,8 +64,8 @@
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map->unmap_ip(map, addr));
- if (addr > sym->end)
- return 0;
+ if (addr < sym->start || addr > sym->end)
+ return -ERANGE;
offset = addr - sym->start;
h = annotation__histogram(notes, evidx);
@@ -561,16 +561,12 @@
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evidx);
- struct objdump_line *pos;
- int len = sym->end - sym->start;
+ int len = sym->end - sym->start, offset;
h->sum = 0;
-
- list_for_each_entry(pos, ¬es->src->source, node) {
- if (pos->offset != -1 && pos->offset < len) {
- h->addr[pos->offset] = h->addr[pos->offset] * 7 / 8;
- h->sum += h->addr[pos->offset];
- }
+ for (offset = 0; offset < len; ++offset) {
+ h->addr[offset] = h->addr[offset] * 7 / 8;
+ h->sum += h->addr[offset];
}
}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 2ec4b60..9f6d630 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -256,6 +256,18 @@
if (!cmp) {
he->period += period;
++he->nr_events;
+
+ /* If the map of an existing hist_entry has
+ * become out-of-date due to an exec() or
+ * similar, update it. Otherwise we will
+ * mis-adjust symbol addresses when computing
+ * the history counter to increment.
+ */
+ if (he->ms.map != entry->ms.map) {
+ he->ms.map = entry->ms.map;
+ if (he->ms.map)
+ he->ms.map->referenced = true;
+ }
goto out;
}
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index dea6d1c..35ae568 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -38,6 +38,7 @@
RB_CLEAR_NODE(&self->rb_node);
self->groups = NULL;
self->referenced = false;
+ self->erange_warned = false;
}
struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index b100c20..81371ba 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -33,6 +33,7 @@
u64 end;
u8 /* enum map_type */ type;
bool referenced;
+ bool erange_warned;
u32 priv;
u64 pgoff;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 05d766e..1fcf1bb 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -54,7 +54,7 @@
num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
name [a-zA-Z_*?][a-zA-Z0-9_*?]*
-modifier_event [ukhp]{1,5}
+modifier_event [ukhpGH]{1,8}
modifier_bp [rwx]
%%
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 9412e3b..1efd3be 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -826,8 +826,16 @@
{
const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest)
- return perf_session__find_machine(session, event->ip.pid);
+ if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
+ u32 pid;
+
+ if (event->header.type == PERF_RECORD_MMAP)
+ pid = event->mmap.pid;
+ else
+ pid = event->ip.pid;
+
+ return perf_session__find_machine(session, pid);
+ }
return perf_session__find_host_machine(session);
}
@@ -868,11 +876,11 @@
dump_sample(session, event, sample);
if (evsel == NULL) {
++session->hists.stats.nr_unknown_id;
- return -1;
+ return 0;
}
if (machine == NULL) {
++session->hists.stats.nr_unprocessable_samples;
- return -1;
+ return 0;
}
return tool->sample(tool, event, sample, evsel, machine);
case PERF_RECORD_MMAP:
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c0a028c..ab9867b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -977,8 +977,9 @@
* And always look at the original dso, not at debuginfo packages, that
* have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
*/
-static int dso__synthesize_plt_symbols(struct dso *dso, struct map *map,
- symbol_filter_t filter)
+static int
+dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
+ symbol_filter_t filter)
{
uint32_t nr_rel_entries, idx;
GElf_Sym sym;
@@ -993,10 +994,7 @@
char sympltname[1024];
Elf *elf;
int nr = 0, symidx, fd, err = 0;
- char name[PATH_MAX];
- snprintf(name, sizeof(name), "%s%s",
- symbol_conf.symfs, dso->long_name);
fd = open(name, O_RDONLY);
if (fd < 0)
goto out;
@@ -1703,8 +1701,9 @@
continue;
if (ret > 0) {
- int nr_plt = dso__synthesize_plt_symbols(dso, map,
- filter);
+ int nr_plt;
+
+ nr_plt = dso__synthesize_plt_symbols(dso, name, map, filter);
if (nr_plt > 0)
ret += nr_plt;
break;
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index d7a1c4a..2f83e5d 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -125,6 +125,9 @@
static bool map_symbol__toggle_fold(struct map_symbol *self)
{
+ if (!self)
+ return false;
+
if (!self->has_children)
return false;
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
index 95d6a6f..4915408 100755
--- a/tools/testing/ktest/ktest.pl
+++ b/tools/testing/ktest/ktest.pl
@@ -183,6 +183,9 @@
# do not force reboots on config problems
my $no_reboot = 1;
+# reboot on success
+my $reboot_success = 0;
+
my %option_map = (
"MACHINE" => \$machine,
"SSH_USER" => \$ssh_user,
@@ -2192,7 +2195,7 @@
}
# Are we looking for where it worked, not failed?
- if ($reverse_bisect) {
+ if ($reverse_bisect && $ret >= 0) {
$ret = !$ret;
}
@@ -3469,6 +3472,7 @@
# Do not reboot on failing test options
$no_reboot = 1;
+ $reboot_success = 0;
$iteration = $i;
@@ -3554,9 +3558,11 @@
die "failed to checkout $checkout";
}
+ $no_reboot = 0;
+
# A test may opt to not reboot the box
if ($reboot_on_success) {
- $no_reboot = 0;
+ $reboot_success = 1;
}
if ($test_type eq "bisect") {
@@ -3600,7 +3606,7 @@
if ($opt{"POWEROFF_ON_SUCCESS"}) {
halt;
-} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot) {
+} elsif ($opt{"REBOOT_ON_SUCCESS"} && !do_not_reboot && $reboot_success) {
reboot_to_good;
} elsif (defined($switch_to_good)) {
# still need to get to the good kernel
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index a457d21..e9fff98 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -240,9 +240,13 @@
return -ENODEV;
}
+ mutex_lock(&kvm->slots_lock);
+
kvm->arch.iommu_domain = iommu_domain_alloc(&pci_bus_type);
- if (!kvm->arch.iommu_domain)
- return -ENOMEM;
+ if (!kvm->arch.iommu_domain) {
+ r = -ENOMEM;
+ goto out_unlock;
+ }
if (!allow_unsafe_assigned_interrupts &&
!iommu_domain_has_cap(kvm->arch.iommu_domain,
@@ -253,17 +257,16 @@
" module option.\n", __func__);
iommu_domain_free(kvm->arch.iommu_domain);
kvm->arch.iommu_domain = NULL;
- return -EPERM;
+ r = -EPERM;
+ goto out_unlock;
}
r = kvm_iommu_map_memslots(kvm);
if (r)
- goto out_unmap;
+ kvm_iommu_unmap_memslots(kvm);
- return 0;
-
-out_unmap:
- kvm_iommu_unmap_memslots(kvm);
+out_unlock:
+ mutex_unlock(&kvm->slots_lock);
return r;
}
@@ -310,6 +313,11 @@
}
}
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages);
+}
+
static int kvm_iommu_unmap_memslots(struct kvm *kvm)
{
int idx;
@@ -320,7 +328,7 @@
slots = kvm_memslots(kvm);
kvm_for_each_memslot(memslot, slots)
- kvm_iommu_put_pages(kvm, memslot->base_gfn, memslot->npages);
+ kvm_iommu_unmap_pages(kvm, memslot);
srcu_read_unlock(&kvm->srcu, idx);
@@ -335,7 +343,11 @@
if (!domain)
return 0;
+ mutex_lock(&kvm->slots_lock);
kvm_iommu_unmap_memslots(kvm);
+ kvm->arch.iommu_domain = NULL;
+ mutex_unlock(&kvm->slots_lock);
+
iommu_domain_free(domain);
return 0;
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 42b7393..9739b53 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -808,12 +808,13 @@
if (r)
goto out_free;
- /* map the pages in iommu page table */
+ /* map/unmap the pages in iommu page table */
if (npages) {
r = kvm_iommu_map_pages(kvm, &new);
if (r)
goto out_free;
- }
+ } else
+ kvm_iommu_unmap_pages(kvm, &old);
r = -ENOMEM;
slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots),