Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon update from Guenter Roeck:
- New drivers for NCT6775, NCT6776, NCT6779, and LM95234.
- Added support for LTC2974, LTC3883, LM25056, TMP431, TMP432, ADT7310,
and ADT7320 to existing drivers.
- Various code cleanups and minor improvements.
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (54 commits)
hwmon: (nct6775) Fix coding style problems
hwmon: (nct6775) Constify strings
hwmon: (tmp401) Add support for TMP432
hwmon: (tmp401) Add support for update_interval attribute
hwmon: (tmp401) Reset valid flag when resetting temperature history
hwmon: (tmp401) Simplification and cleanup
hwmon: (tmp401) Use sysfs_create_group / sysfs_remove_group
hwmon: (tmp401) Drop unused defines, use BIT for bit masks
hwmon: (nct6775) Use ARRAY_SIZE for loops where possible
documentation: hwmon: Fix typo in documentation/hwmon
hwmon: (nct6775) Enable both AUXTIN and VIN3 on NCT6776
hwmon: (ad7314) use spi_get_drvdata() and spi_set_drvdata()
MAINTAINERS: Add myself as maintainer for the NCT6775 driver
hwmon: (nct6775) Expand scope of supported chips
hwmon: (gpio-fan) Use is_visible to determine if attributes should be created
hwmon: (tmp401) Fix device detection for TMP411B and TMP411C
hwmon: Add driver for LM95234
hwmon: (tmp401) Add support for TMP431
hwmon: (pmbus/lm25066) Add support for LM25056
hwmon: (pmbus/lm25066) Refactor device specific coefficients
...
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 7514dbf..c36892c 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -227,7 +227,7 @@
<chapter id="uart16x50">
<title>16x50 UART Driver</title>
!Edrivers/tty/serial/serial_core.c
-!Edrivers/tty/serial/8250/8250.c
+!Edrivers/tty/serial/8250/8250_core.c
</chapter>
<chapter id="fbdev">
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index a336287..d933af3 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -98,7 +98,7 @@
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
reg = <0x1460 0x18>;
gpio-controller;
- gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+ gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
}
@@ -107,8 +107,8 @@
Next values specify the base pin and number of pins for the range
handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
- pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
- by this gpio controller.
+ pin 29 under pinctrl1 with gpio offset 0 and pin 50 to pin 69 under
+ pinctrl2 with gpio offset 10 is handled by this gpio controller.
The pinctrl node must have "#gpio-range-cells" property to show number of
arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
index 2c81e45..08f0c3d 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt
@@ -1,7 +1,9 @@
One-register-per-pin type device tree based pinctrl driver
Required properties:
-- compatible : "pinctrl-single"
+- compatible : "pinctrl-single" or "pinconf-single".
+ "pinctrl-single" means that pinconf isn't supported.
+ "pinconf-single" means that generic pinconf is supported.
- reg : offset and length of the register set for the mux registers
@@ -14,9 +16,61 @@
- pinctrl-single,function-off : function off mode for disabled state if
available and same for all registers; if not specified, disabling of
pin functions is ignored
+
- pinctrl-single,bit-per-mux : boolean to indicate that one register controls
more than one pin
+- pinctrl-single,drive-strength : array of value that are used to configure
+ drive strength in the pinmux register. They're value of drive strength
+ current and drive strength mask.
+
+ /* drive strength current, mask */
+ pinctrl-single,power-source = <0x30 0xf0>;
+
+- pinctrl-single,bias-pullup : array of value that are used to configure the
+ input bias pullup in the pinmux register.
+
+ /* input, enabled pullup bits, disabled pullup bits, mask */
+ pinctrl-single,bias-pullup = <0 1 0 1>;
+
+- pinctrl-single,bias-pulldown : array of value that are used to configure the
+ input bias pulldown in the pinmux register.
+
+ /* input, enabled pulldown bits, disabled pulldown bits, mask */
+ pinctrl-single,bias-pulldown = <2 2 0 2>;
+
+ * Two bits to control input bias pullup and pulldown: User should use
+ pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. One bit means
+ pullup, and the other one bit means pulldown.
+ * Three bits to control input bias enable, pullup and pulldown. User should
+ use pinctrl-single,bias-pullup & pinctrl-single,bias-pulldown. Input bias
+ enable bit should be included in pullup or pulldown bits.
+ * Although driver could set PIN_CONFIG_BIAS_DISABLE, there's no property as
+ pinctrl-single,bias-disable. Because pinctrl single driver could implement
+ it by calling pulldown, pullup disabled.
+
+- pinctrl-single,input-schmitt : array of value that are used to configure
+ input schmitt in the pinmux register. In some silicons, there're two input
+ schmitt value (rising-edge & falling-edge) in the pinmux register.
+
+ /* input schmitt value, mask */
+ pinctrl-single,input-schmitt = <0x30 0x70>;
+
+- pinctrl-single,input-schmitt-enable : array of value that are used to
+ configure input schmitt enable or disable in the pinmux register.
+
+ /* input, enable bits, disable bits, mask */
+ pinctrl-single,input-schmitt-enable = <0x30 0x40 0 0x70>;
+
+- pinctrl-single,gpio-range : list of value that are used to configure a GPIO
+ range. They're value of subnode phandle, pin base in pinctrl device, pin
+ number in this range, GPIO function value of this GPIO range.
+ The number of parameters is depend on #pinctrl-single,gpio-range-cells
+ property.
+
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1>;
+
This driver assumes that there is only one register for each pin (unless the
pinctrl-single,bit-per-mux is set), and uses the common pinctrl bindings as
specified in the pinctrl-bindings.txt document in this directory.
@@ -42,6 +96,20 @@
device pinctrl register, 0x18 is the desired value, and 0xff is the sub mask to
be used when applying this change to the register.
+
+Optional sub-node: In case some pins could be configured as GPIO in the pinmux
+register, those pins could be defined as a GPIO range. This sub-node is required
+by pinctrl-single,gpio-range property.
+
+Required properties in sub-node:
+- #pinctrl-single,gpio-range-cells : the number of parameters after phandle in
+ pinctrl-single,gpio-range property.
+
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+
+
Example:
/* SoC common file */
@@ -58,7 +126,7 @@
/* second controller instance for pins in wkup domain */
pmx_wkup: pinmux@4a31e040 {
- compatible = "pinctrl-single;
+ compatible = "pinctrl-single";
reg = <0x4a31e040 0x0038>;
#address-cells = <1>;
#size-cells = <0>;
@@ -76,6 +144,29 @@
pinctrl-single,function-mask = <0x5F>;
};
+/* third controller instance for pins in gpio domain */
+pmx_gpio: pinmux@d401e000 {
+ compatible = "pinconf-single";
+ reg = <0xd401e000 0x0330>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <7>;
+
+ /* sparse GPIO range could be supported */
+ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
+ &range 12 1 0 &range 13 29 1
+ &range 43 1 0 &range 44 49 1
+ &range 94 1 1 &range 96 2 1>;
+
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+};
+
+
/* board specific .dts file */
&pmx_core {
@@ -96,6 +187,15 @@
>;
};
+ uart0_pins: pinmux_uart0_pins {
+ pinctrl-single,pins = <
+ 0x208 0 /* UART0_RXD (IOCFG138) */
+ 0x20c 0 /* UART0_TXD (IOCFG139) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ };
+
/* map uart2 pins */
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
@@ -122,6 +222,11 @@
};
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+};
+
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 4598a47..c70fca1 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -7,6 +7,7 @@
Required Properties:
- compatible: should be one of the following.
+ - "samsung,s3c64xx-pinctrl": for S3C64xx-compatible pin-controller,
- "samsung,exynos4210-pinctrl": for Exynos4210 compatible pin-controller.
- "samsung,exynos4x12-pinctrl": for Exynos4x12 compatible pin-controller.
- "samsung,exynos5250-pinctrl": for Exynos5250 compatible pin-controller.
@@ -105,6 +106,8 @@
- compatible: identifies the type of the external wakeup interrupt controller
The possible values are:
+ - samsung,s3c64xx-wakeup-eint: represents wakeup interrupt controller
+ found on Samsung S3C64xx SoCs,
- samsung,exynos4210-wakeup-eint: represents wakeup interrupt controller
found on Samsung Exynos4210 SoC.
- interrupt-parent: phandle of the interrupt parent to which the external
diff --git a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
index c870b64..2871e21 100644
--- a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+++ b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
@@ -5,58 +5,32 @@
- compatible : "via,vt8500-fb"
- reg : Should contain 1 register ranges(address and length)
- interrupts : framebuffer controller interrupt
-- display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
-Required nodes:
-- display: a display node is required to initialize the lcd panel
- This should be in the board dts.
-- default-mode: a videomode within the display with timing parameters
- as specified below.
+Required subnodes:
+- display-timings: see display-timing.txt for information
Example:
- fb@d800e400 {
+ fb@d8050800 {
compatible = "via,vt8500-fb";
reg = <0xd800e400 0x400>;
interrupts = <12>;
- display = <&display>;
- default-mode = <&mode0>;
- };
+ bits-per-pixel = <16>;
-VIA VT8500 Display
------------------------------------------------------
-Required properties (as per of_videomode_helper):
-
- - hactive, vactive: Display resolution
- - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
- in pixels
- vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
- lines
- - clock: displayclock in Hz
- - bpp: lcd panel bit-depth.
- <16> for RGB565, <32> for RGB888
-
-Optional properties (as per of_videomode_helper):
- - width-mm, height-mm: Display dimensions in mm
- - hsync-active-high (bool): Hsync pulse is active high
- - vsync-active-high (bool): Vsync pulse is active high
- - interlaced (bool): This is an interlaced mode
- - doublescan (bool): This is a doublescan mode
-
-Example:
- display: display@0 {
- modes {
- mode0: mode@0 {
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
hactive = <800>;
vactive = <480>;
- hback-porch = <88>;
hfront-porch = <40>;
+ hback-porch = <88>;
hsync-len = <0>;
vback-porch = <32>;
vfront-porch = <11>;
vsync-len = <1>;
- clock = <0>; /* unused but required */
- bpp = <16>; /* non-standard but required */
};
};
};
+
diff --git a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
index 3d325e1..0bcadb2 100644
--- a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
+++ b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
@@ -4,20 +4,30 @@
Required properties:
- compatible : "wm,wm8505-fb"
- reg : Should contain 1 register ranges(address and length)
-- via,display: a phandle pointing to the display node
+- bits-per-pixel : bit depth of framebuffer (16 or 32)
-Required nodes:
-- display: a display node is required to initialize the lcd panel
- This should be in the board dts. See definition in
- Documentation/devicetree/bindings/video/via,vt8500-fb.txt
-- default-mode: a videomode node as specified in
- Documentation/devicetree/bindings/video/via,vt8500-fb.txt
+Required subnodes:
+- display-timings: see display-timing.txt for information
Example:
- fb@d8050800 {
+ fb@d8051700 {
compatible = "wm,wm8505-fb";
- reg = <0xd8050800 0x200>;
- display = <&display>;
- default-mode = <&mode0>;
+ reg = <0xd8051700 0x200>;
+ bits-per-pixel = <16>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <0>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <1>;
+ };
+ };
};
diff --git a/Documentation/ia64/err_inject.txt b/Documentation/ia64/err_inject.txt
index 223e4f0..9f651c1 100644
--- a/Documentation/ia64/err_inject.txt
+++ b/Documentation/ia64/err_inject.txt
@@ -882,7 +882,7 @@
cpu=parameters[i].cpu;
k = cpu%64;
j = cpu/64;
- mask[j]=1<<k;
+ mask[j] = 1UL << k;
if (sched_setaffinity(0, MASK_SIZE*8, mask)==-1) {
perror("Error sched_setaffinity:");
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
index 13f1aa0..9c7fd988 100644
--- a/Documentation/kdump/kdump.txt
+++ b/Documentation/kdump/kdump.txt
@@ -297,6 +297,7 @@
On ia64, 256M@256M is a generous value that typically works.
The region may be automatically placed on ia64, see the
dump-capture kernel config option notes above.
+ If use sparse memory, the size should be rounded to GRANULE boundaries.
On s390x, typically use "crashkernel=xxM". The value of xx is dependent
on the memory consumption of the kdump system. In general this is not
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4609e81..8ccbf27 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -596,9 +596,6 @@
is selected automatically. Check
Documentation/kdump/kdump.txt for further details.
- crashkernel_low=size[KMG]
- [KNL, x86] parts under 4G.
-
crashkernel=range1:size1[,range2:size2,...][@offset]
[KNL] Same as above, but depends on the memory
in the running system. The syntax of range is
@@ -606,6 +603,26 @@
a memory unit (amount[KMG]). See also
Documentation/kdump/kdump.txt for an example.
+ crashkernel=size[KMG],high
+ [KNL, x86_64] range could be above 4G. Allow kernel
+ to allocate physical memory region from top, so could
+ be above 4G if system have more than 4G ram installed.
+ Otherwise memory region will be allocated below 4G, if
+ available.
+ It will be ignored if crashkernel=X is specified.
+ crashkernel=size[KMG],low
+ [KNL, x86_64] range under 4G. When crashkernel=X,high
+ is passed, kernel could allocate physical memory region
+ above 4G, that cause second kernel crash on system
+ that require some amount of low memory, e.g. swiotlb
+ requires at least 64M+32K low memory. Kernel would
+ try to allocate 72M below 4G automatically.
+ This one let user to specify own low range under 4G
+ for second kernel instead.
+ 0: to disable low allocation.
+ It will be ignored when crashkernel=X,high is not used
+ or memory reserved is below 4G.
+
cs89x0_dma= [HW,NET]
Format: <dma>
@@ -788,6 +805,12 @@
edd= [EDD]
Format: {"off" | "on" | "skip[mbr]"}
+ efi_no_storage_paranoia [EFI; X86]
+ Using this parameter you can use more than 50% of
+ your efi variable storage. Use this parameter only if
+ you are really sure that your UEFI does sane gc and
+ fulfills the spec otherwise your board may brick.
+
eisa_irq_edge= [PARISC,HW]
See header of drivers/parisc/eisa.c.
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index a2b57e0..447fd4c 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -736,6 +736,13 @@
Pin control interaction with the GPIO subsystem
===============================================
+Note that the following implies that the use case is to use a certain pin
+from the Linux kernel using the API in <linux/gpio.h> with gpio_request()
+and similar functions. There are cases where you may be using something
+that your datasheet calls "GPIO mode" but actually is just an electrical
+configuration for a certain device. See the section below named
+"GPIO mode pitfalls" for more details on this scenario.
+
The public pinmux API contains two functions named pinctrl_request_gpio()
and pinctrl_free_gpio(). These two functions shall *ONLY* be called from
gpiolib-based drivers as part of their gpio_request() and
@@ -774,6 +781,111 @@
special GPIO-handler is registered.
+GPIO mode pitfalls
+==================
+
+Sometime the developer may be confused by a datasheet talking about a pin
+being possible to set into "GPIO mode". It appears that what hardware
+engineers mean with "GPIO mode" is not necessarily the use case that is
+implied in the kernel interface <linux/gpio.h>: a pin that you grab from
+kernel code and then either listen for input or drive high/low to
+assert/deassert some external line.
+
+Rather hardware engineers think that "GPIO mode" means that you can
+software-control a few electrical properties of the pin that you would
+not be able to control if the pin was in some other mode, such as muxed in
+for a device.
+
+Example: a pin is usually muxed in to be used as a UART TX line. But during
+system sleep, we need to put this pin into "GPIO mode" and ground it.
+
+If you make a 1-to-1 map to the GPIO subsystem for this pin, you may start
+to think that you need to come up with something real complex, that the
+pin shall be used for UART TX and GPIO at the same time, that you will grab
+a pin control handle and set it to a certain state to enable UART TX to be
+muxed in, then twist it over to GPIO mode and use gpio_direction_output()
+to drive it low during sleep, then mux it over to UART TX again when you
+wake up and maybe even gpio_request/gpio_free as part of this cycle. This
+all gets very complicated.
+
+The solution is to not think that what the datasheet calls "GPIO mode"
+has to be handled by the <linux/gpio.h> interface. Instead view this as
+a certain pin config setting. Look in e.g. <linux/pinctrl/pinconf-generic.h>
+and you find this in the documentation:
+
+ PIN_CONFIG_OUTPUT: this will configure the pin in output, use argument
+ 1 to indicate high level, argument 0 to indicate low level.
+
+So it is perfectly possible to push a pin into "GPIO mode" and drive the
+line low as part of the usual pin control map. So for example your UART
+driver may look like this:
+
+#include <linux/pinctrl/consumer.h>
+
+struct pinctrl *pinctrl;
+struct pinctrl_state *pins_default;
+struct pinctrl_state *pins_sleep;
+
+pins_default = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_DEFAULT);
+pins_sleep = pinctrl_lookup_state(uap->pinctrl, PINCTRL_STATE_SLEEP);
+
+/* Normal mode */
+retval = pinctrl_select_state(pinctrl, pins_default);
+/* Sleep mode */
+retval = pinctrl_select_state(pinctrl, pins_sleep);
+
+And your machine configuration may look like this:
+--------------------------------------------------
+
+static unsigned long uart_default_mode[] = {
+ PIN_CONF_PACKED(PIN_CONFIG_DRIVE_PUSH_PULL, 0),
+};
+
+static unsigned long uart_sleep_mode[] = {
+ PIN_CONF_PACKED(PIN_CONFIG_OUTPUT, 0),
+};
+
+static struct pinctrl_map __initdata pinmap[] = {
+ PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
+ "u0_group", "u0"),
+ PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_DEFAULT, "pinctrl-foo",
+ "UART_TX_PIN", uart_default_mode),
+ PIN_MAP_MUX_GROUP("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
+ "u0_group", "gpio-mode"),
+ PIN_MAP_CONFIGS_PIN("uart", PINCTRL_STATE_SLEEP, "pinctrl-foo",
+ "UART_TX_PIN", uart_sleep_mode),
+};
+
+foo_init(void) {
+ pinctrl_register_mappings(pinmap, ARRAY_SIZE(pinmap));
+}
+
+Here the pins we want to control are in the "u0_group" and there is some
+function called "u0" that can be enabled on this group of pins, and then
+everything is UART business as usual. But there is also some function
+named "gpio-mode" that can be mapped onto the same pins to move them into
+GPIO mode.
+
+This will give the desired effect without any bogus interaction with the
+GPIO subsystem. It is just an electrical configuration used by that device
+when going to sleep, it might imply that the pin is set into something the
+datasheet calls "GPIO mode" but that is not the point: it is still used
+by that UART device to control the pins that pertain to that very UART
+driver, putting them into modes needed by the UART. GPIO in the Linux
+kernel sense are just some 1-bit line, and is a different use case.
+
+How the registers are poked to attain the push/pull and output low
+configuration and the muxing of the "u0" or "gpio-mode" group onto these
+pins is a question for the driver.
+
+Some datasheets will be more helpful and refer to the "GPIO mode" as
+"low power mode" rather than anything to do with GPIO. This often means
+the same thing electrically speaking, but in this latter case the
+software engineers will usually quickly identify that this is some
+specific muxing/configuration rather than anything related to the GPIO
+API.
+
+
Board/machine configuration
==================================
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index ae66f9b..fcaf0b4 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -143,7 +143,8 @@
Return Value: none
-Description: frees memory for a debug log
+Description: frees memory for a debug log and removes all registered debug
+ views.
Must not be called within an interrupt handler
---------------------------------------------------------------------------
diff --git a/Documentation/scsi/LICENSE.qla2xxx b/Documentation/scsi/LICENSE.qla2xxx
index 27a91cf..5020b7b 100644
--- a/Documentation/scsi/LICENSE.qla2xxx
+++ b/Documentation/scsi/LICENSE.qla2xxx
@@ -1,4 +1,4 @@
-Copyright (c) 2003-2012 QLogic Corporation
+Copyright (c) 2003-2013 QLogic Corporation
QLogic Linux FC-FCoE Driver
This program includes a device driver for Linux 3.x.
diff --git a/MAINTAINERS b/MAINTAINERS
index 6abd5ae..fb2fc30 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4941,6 +4941,12 @@
S: Maintained
F: fs/logfs/
+LPC32XX MACHINE SUPPORT
+M: Roland Stigge <stigge@antcom.de>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-lpc32xx/
+
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
M: Nagalakshmi Nandigama <Nagalakshmi.Nandigama@lsi.com>
M: Sreekanth Reddy <Sreekanth.Reddy@lsi.com>
@@ -6632,7 +6638,7 @@
F: fs/reiserfs/
REGISTER MAP ABSTRACTION
-M: Mark Brown <broonie@opensource.wolfsonmicro.com>
+M: Mark Brown <broonie@kernel.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regmap.git
S: Supported
F: drivers/base/regmap/
@@ -6958,7 +6964,6 @@
SCTP PROTOCOL
M: Vlad Yasevich <vyasevich@gmail.com>
-M: Sridhar Samudrala <sri@us.ibm.com>
M: Neil Horman <nhorman@tuxdriver.com>
L: linux-sctp@vger.kernel.org
W: http://lksctp.sourceforge.net
@@ -7381,7 +7386,7 @@
SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
M: Liam Girdwood <lgirdwood@gmail.com>
-M: Mark Brown <broonie@opensource.wolfsonmicro.com>
+M: Mark Brown <broonie@kernel.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://alsa-project.org/main/index.php/ASoC
@@ -7470,7 +7475,7 @@
SPI SUBSYSTEM
M: Grant Likely <grant.likely@secretlab.ca>
-M: Mark Brown <broonie@opensource.wolfsonmicro.com>
+M: Mark Brown <broonie@kernel.org>
L: spi-devel-general@lists.sourceforge.net
Q: http://patchwork.kernel.org/project/spi-devel-general/list/
T: git git://git.secretlab.ca/git/linux-2.6.git
@@ -8715,7 +8720,7 @@
VOLTAGE AND CURRENT REGULATOR FRAMEWORK
M: Liam Girdwood <lrg@ti.com>
-M: Mark Brown <broonie@opensource.wolfsonmicro.com>
+M: Mark Brown <broonie@kernel.org>
W: http://opensource.wolfsonmicro.com/node/15
W: http://www.slimlogic.co.uk/?p=48
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lrg/regulator.git
diff --git a/Makefile b/Makefile
index 6db672b..8fe6991 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 9
SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION =
NAME = Unicycling Gorilla
# *DOCUMENTATION*
@@ -513,7 +513,8 @@
# Carefully list dependencies so we do not try to build scripts twice
# in parallel
PHONY += scripts
-scripts: scripts_basic include/config/auto.conf include/config/tristate.conf
+scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
+ asm-generic
$(Q)$(MAKE) $(build)=$(@)
# Objects we will link into vmlinux / subdirs we need to visit
diff --git a/arch/arc/include/asm/irqflags.h b/arch/arc/include/asm/irqflags.h
index ccd8480..eac0716 100644
--- a/arch/arc/include/asm/irqflags.h
+++ b/arch/arc/include/asm/irqflags.h
@@ -39,7 +39,7 @@
" flag.nz %0 \n"
: "=r"(temp), "=r"(flags)
: "n"((STATUS_E1_MASK | STATUS_E2_MASK))
- : "cc");
+ : "memory", "cc");
return flags;
}
@@ -53,7 +53,8 @@
__asm__ __volatile__(
" flag %0 \n"
:
- : "r"(flags));
+ : "r"(flags)
+ : "memory");
}
/*
@@ -73,7 +74,8 @@
" and %0, %0, %1 \n"
" flag %0 \n"
: "=&r"(temp)
- : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK)));
+ : "n"(~(STATUS_E1_MASK | STATUS_E2_MASK))
+ : "memory");
}
/*
@@ -85,7 +87,9 @@
__asm__ __volatile__(
" lr %0, [status32] \n"
- : "=&r"(temp));
+ : "=&r"(temp)
+ :
+ : "memory");
return temp;
}
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
index 6ce3d17..fd36e1c 100644
--- a/arch/arm/boot/dts/imx28-m28evk.dts
+++ b/arch/arm/boot/dts/imx28-m28evk.dts
@@ -152,7 +152,6 @@
i2c0: i2c@80058000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
- clock-frequency = <400000>;
status = "okay";
sgtl5000: codec@0a {
diff --git a/arch/arm/boot/dts/imx28-sps1.dts b/arch/arm/boot/dts/imx28-sps1.dts
index e6cde8a..6c6a544 100644
--- a/arch/arm/boot/dts/imx28-sps1.dts
+++ b/arch/arm/boot/dts/imx28-sps1.dts
@@ -70,7 +70,6 @@
i2c0: i2c@80058000 {
pinctrl-names = "default";
pinctrl-0 = <&i2c0_pins_a>;
- clock-frequency = <400000>;
status = "okay";
rtc: rtc@51 {
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 06ec460..281a223 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -91,6 +91,7 @@
compatible = "arm,cortex-a9-twd-timer";
reg = <0x00a00600 0x20>;
interrupts = <1 13 0xf01>;
+ clocks = <&clks 15>;
};
L2: l2-cache@00a02000 {
diff --git a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
index 93c3afb..3694e94 100644
--- a/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
+++ b/arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
@@ -96,11 +96,11 @@
marvell,function = "gpio";
};
pmx_led_rebuild_brt_ctrl_1: pmx-led-rebuild-brt-ctrl-1 {
- marvell,pins = "mpp44";
+ marvell,pins = "mpp46";
marvell,function = "gpio";
};
pmx_led_rebuild_brt_ctrl_2: pmx-led-rebuild-brt-ctrl-2 {
- marvell,pins = "mpp45";
+ marvell,pins = "mpp47";
marvell,function = "gpio";
};
@@ -157,14 +157,14 @@
gpios = <&gpio0 16 0>;
linux,default-trigger = "default-on";
};
- health_led1 {
+ rebuild_led {
+ label = "status:white:rebuild_led";
+ gpios = <&gpio1 4 0>;
+ };
+ health_led {
label = "status:red:health_led";
gpios = <&gpio1 5 0>;
};
- health_led2 {
- label = "status:white:health_led";
- gpios = <&gpio1 4 0>;
- };
backup_led {
label = "status:blue:backup_led";
gpios = <&gpio0 15 0>;
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 1513c19..122ae94 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -89,7 +89,7 @@
pinmux: pinmux@e0700000 {
compatible = "st,spear1310-pinmux";
reg = <0xe0700000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
apb {
@@ -212,7 +212,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 246>;
+ gpio-ranges = <&pinmux 0 0 246>;
status = "disabled";
st-plgpio,ngpio = <246>;
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index 34da11a..c511c47 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -63,7 +63,7 @@
pinmux: pinmux@e0700000 {
compatible = "st,spear1340-pinmux";
reg = <0xe0700000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
pwm: pwm@e0180000 {
@@ -127,7 +127,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 252>;
+ gpio-ranges = <&pinmux 0 0 252>;
status = "disabled";
st-plgpio,ngpio = <250>;
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index ab45b8c..9537208 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -25,7 +25,7 @@
pinmux: pinmux@b4000000 {
compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
fsmc: flash@44000000 {
@@ -102,7 +102,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 102>;
+ gpio-ranges = <&pinmux 0 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index caa5520..ffea342 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -24,7 +24,7 @@
pinmux: pinmux@b3000000 {
compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
clcd@90000000 {
@@ -130,7 +130,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 102>;
+ gpio-ranges = <&pinmux 0 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500-bv07.dts
index 567cf4e..877b33a 100644
--- a/arch/arm/boot/dts/vt8500-bv07.dts
+++ b/arch/arm/boot/dts/vt8500-bv07.dts
@@ -11,26 +11,22 @@
/ {
model = "Benign BV07 Netbook";
+};
- /*
- * Display node is based on Sascha Hauer's patch on dri-devel.
- * Added a bpp property to calculate the size of the framebuffer
- * until the binding is formalized.
- */
- display: display@0 {
- modes {
- mode0: mode@0 {
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hfront-porch = <40>;
- hsync-len = <0>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <1>;
- clock = <0>; /* unused but required */
- bpp = <16>; /* non-standard but required */
- };
+&fb {
+ bits-per-pixel = <16>;
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <0>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <1>;
};
};
};
diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500.dtsi
index cf31ced..68c8dc6 100644
--- a/arch/arm/boot/dts/vt8500.dtsi
+++ b/arch/arm/boot/dts/vt8500.dtsi
@@ -98,12 +98,10 @@
interrupts = <43>;
};
- fb@d800e400 {
+ fb: fb@d8050800 {
compatible = "via,vt8500-fb";
reg = <0xd800e400 0x400>;
interrupts = <12>;
- display = <&display>;
- default-mode = <&mode0>;
};
ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/wm8505-ref.dts
index fd4e248..edd2cec 100644
--- a/arch/arm/boot/dts/wm8505-ref.dts
+++ b/arch/arm/boot/dts/wm8505-ref.dts
@@ -11,26 +11,22 @@
/ {
model = "Wondermedia WM8505 Netbook";
+};
- /*
- * Display node is based on Sascha Hauer's patch on dri-devel.
- * Added a bpp property to calculate the size of the framebuffer
- * until the binding is formalized.
- */
- display: display@0 {
- modes {
- mode0: mode@0 {
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hfront-porch = <40>;
- hsync-len = <0>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <1>;
- clock = <0>; /* unused but required */
- bpp = <32>; /* non-standard but required */
- };
+&fb {
+ bits-per-pixel = <32>;
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <0>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <1>;
};
};
};
diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi
index e74a1c0..bcf668d 100644
--- a/arch/arm/boot/dts/wm8505.dtsi
+++ b/arch/arm/boot/dts/wm8505.dtsi
@@ -128,11 +128,9 @@
interrupts = <0>;
};
- fb@d8050800 {
+ fb: fb@d8050800 {
compatible = "wm,wm8505-fb";
reg = <0xd8050800 0x200>;
- display = <&display>;
- default-mode = <&mode0>;
};
ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/wm8650-mid.dts
index cefd938..61671a0 100644
--- a/arch/arm/boot/dts/wm8650-mid.dts
+++ b/arch/arm/boot/dts/wm8650-mid.dts
@@ -11,26 +11,24 @@
/ {
model = "Wondermedia WM8650-MID Tablet";
+};
- /*
- * Display node is based on Sascha Hauer's patch on dri-devel.
- * Added a bpp property to calculate the size of the framebuffer
- * until the binding is formalized.
- */
- display: display@0 {
- modes {
- mode0: mode@0 {
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hfront-porch = <40>;
- hsync-len = <0>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <1>;
- clock = <0>; /* unused but required */
- bpp = <16>; /* non-standard but required */
- };
+&fb {
+ bits-per-pixel = <16>;
+
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <0>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <1>;
};
};
};
+
diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/wm8650.dtsi
index db3c0a1..9313407 100644
--- a/arch/arm/boot/dts/wm8650.dtsi
+++ b/arch/arm/boot/dts/wm8650.dtsi
@@ -128,11 +128,9 @@
interrupts = <43>;
};
- fb@d8050800 {
+ fb: fb@d8050800 {
compatible = "wm,wm8505-fb";
reg = <0xd8050800 0x200>;
- display = <&display>;
- default-mode = <&mode0>;
};
ge_rops@d8050400 {
diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts
index fcc660c..32d2253 100644
--- a/arch/arm/boot/dts/wm8850-w70v2.dts
+++ b/arch/arm/boot/dts/wm8850-w70v2.dts
@@ -15,28 +15,6 @@
/ {
model = "Wondermedia WM8850-W70v2 Tablet";
- /*
- * Display node is based on Sascha Hauer's patch on dri-devel.
- * Added a bpp property to calculate the size of the framebuffer
- * until the binding is formalized.
- */
- display: display@0 {
- modes {
- mode0: mode@0 {
- hactive = <800>;
- vactive = <480>;
- hback-porch = <88>;
- hfront-porch = <40>;
- hsync-len = <0>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <1>;
- clock = <0>; /* unused but required */
- bpp = <16>; /* non-standard but required */
- };
- };
- };
-
backlight {
compatible = "pwm-backlight";
pwms = <&pwm 0 50000 1>; /* duty inverted */
@@ -45,3 +23,21 @@
default-brightness-level = <5>;
};
};
+
+&fb {
+ bits-per-pixel = <16>;
+ display-timings {
+ native-mode = <&timing0>;
+ timing0: 800x480 {
+ clock-frequency = <0>; /* unused but required */
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <0>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <1>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/wm8850.dtsi
index e8cbfdc..7149cd1 100644
--- a/arch/arm/boot/dts/wm8850.dtsi
+++ b/arch/arm/boot/dts/wm8850.dtsi
@@ -135,11 +135,9 @@
};
};
- fb@d8051700 {
+ fb: fb@d8051700 {
compatible = "wm,wm8505-fb";
reg = <0xd8051700 0x200>;
- display = <&display>;
- default-mode = <&mode0>;
};
ge_rops@d8050400 {
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index cca9f15..ea289e1 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -19,14 +19,6 @@
#undef _CACHE
#undef MULTI_CACHE
-#if defined(CONFIG_CPU_CACHE_V3)
-# ifdef _CACHE
-# define MULTI_CACHE 1
-# else
-# define _CACHE v3
-# endif
-#endif
-
#if defined(CONFIG_CPU_CACHE_V4)
# ifdef _CACHE
# define MULTI_CACHE 1
diff --git a/arch/arm/include/asm/hardware/iop3xx.h b/arch/arm/include/asm/hardware/iop3xx.h
index 02fe2fb..ed94b1a 100644
--- a/arch/arm/include/asm/hardware/iop3xx.h
+++ b/arch/arm/include/asm/hardware/iop3xx.h
@@ -37,7 +37,7 @@
* IOP3XX processor registers
*/
#define IOP3XX_PERIPHERAL_PHYS_BASE 0xffffe000
-#define IOP3XX_PERIPHERAL_VIRT_BASE 0xfeffe000
+#define IOP3XX_PERIPHERAL_VIRT_BASE 0xfedfe000
#define IOP3XX_PERIPHERAL_SIZE 0x00002000
#define IOP3XX_PERIPHERAL_UPPER_PA (IOP3XX_PERIPHERAL_PHYS_BASE +\
IOP3XX_PERIPHERAL_SIZE - 1)
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index 6ef8afd..86b8fe3 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -111,7 +111,7 @@
#define L_PTE_S2_MT_WRITETHROUGH (_AT(pteval_t, 0xa) << 2) /* MemAttr[3:0] */
#define L_PTE_S2_MT_WRITEBACK (_AT(pteval_t, 0xf) << 2) /* MemAttr[3:0] */
#define L_PTE_S2_RDONLY (_AT(pteval_t, 1) << 6) /* HAP[1] */
-#define L_PTE_S2_RDWR (_AT(pteval_t, 2) << 6) /* HAP[2:1] */
+#define L_PTE_S2_RDWR (_AT(pteval_t, 3) << 6) /* HAP[2:1] */
/*
* Hyp-mode PL2 PTE definitions for LPAE.
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index 9e9c041..ab865e6 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -14,7 +14,6 @@
#include <asm/glue.h>
-#define TLB_V3_PAGE (1 << 0)
#define TLB_V4_U_PAGE (1 << 1)
#define TLB_V4_D_PAGE (1 << 2)
#define TLB_V4_I_PAGE (1 << 3)
@@ -22,7 +21,6 @@
#define TLB_V6_D_PAGE (1 << 5)
#define TLB_V6_I_PAGE (1 << 6)
-#define TLB_V3_FULL (1 << 8)
#define TLB_V4_U_FULL (1 << 9)
#define TLB_V4_D_FULL (1 << 10)
#define TLB_V4_I_FULL (1 << 11)
@@ -52,7 +50,6 @@
* =============
*
* We have the following to choose from:
- * v3 - ARMv3
* v4 - ARMv4 without write buffer
* v4wb - ARMv4 with write buffer without I TLB flush entry instruction
* v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
@@ -330,7 +327,6 @@
if (tlb_flag(TLB_WB))
dsb();
- tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
tlb_op(TLB_V4_U_FULL | TLB_V6_U_FULL, "c8, c7, 0", zero);
tlb_op(TLB_V4_D_FULL | TLB_V6_D_FULL, "c8, c6, 0", zero);
tlb_op(TLB_V4_I_FULL | TLB_V6_I_FULL, "c8, c5, 0", zero);
@@ -351,9 +347,8 @@
if (tlb_flag(TLB_WB))
dsb();
- if (possible_tlb_flags & (TLB_V3_FULL|TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
+ if (possible_tlb_flags & (TLB_V4_U_FULL|TLB_V4_D_FULL|TLB_V4_I_FULL)) {
if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
- tlb_op(TLB_V3_FULL, "c6, c0, 0", zero);
tlb_op(TLB_V4_U_FULL, "c8, c7, 0", zero);
tlb_op(TLB_V4_D_FULL, "c8, c6, 0", zero);
tlb_op(TLB_V4_I_FULL, "c8, c5, 0", zero);
@@ -385,9 +380,8 @@
if (tlb_flag(TLB_WB))
dsb();
- if (possible_tlb_flags & (TLB_V3_PAGE|TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
+ if (possible_tlb_flags & (TLB_V4_U_PAGE|TLB_V4_D_PAGE|TLB_V4_I_PAGE|TLB_V4_I_FULL) &&
cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
- tlb_op(TLB_V3_PAGE, "c6, c0, 0", uaddr);
tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", uaddr);
tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", uaddr);
tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", uaddr);
@@ -418,7 +412,6 @@
if (tlb_flag(TLB_WB))
dsb();
- tlb_op(TLB_V3_PAGE, "c6, c0, 0", kaddr);
tlb_op(TLB_V4_U_PAGE, "c8, c7, 1", kaddr);
tlb_op(TLB_V4_D_PAGE, "c8, c6, 1", kaddr);
tlb_op(TLB_V4_I_PAGE, "c8, c5, 1", kaddr);
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 5dc1aa6..1fd749e 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -1043,7 +1043,7 @@
return NOTIFY_OK;
}
-static struct notifier_block __cpuinitdata dbg_cpu_pm_nb = {
+static struct notifier_block dbg_cpu_pm_nb = {
.notifier_call = dbg_cpu_pm_notify,
};
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 146157d..8c3094d 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -253,7 +253,10 @@
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
struct pmu *leader_pmu = event->group_leader->pmu;
- if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
+ if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF)
+ return 1;
+
+ if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
return 1;
return armpmu->get_event_idx(hw_events, event) >= 0;
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
index bd6f56b..59d2adb 100644
--- a/arch/arm/kernel/sched_clock.c
+++ b/arch/arm/kernel/sched_clock.c
@@ -45,12 +45,12 @@
static u32 __read_mostly (*read_sched_clock)(void) = jiffy_sched_clock_read;
-static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+static inline u64 notrace cyc_to_ns(u64 cyc, u32 mult, u32 shift)
{
return (cyc * mult) >> shift;
}
-static unsigned long long cyc_to_sched_clock(u32 cyc, u32 mask)
+static unsigned long long notrace cyc_to_sched_clock(u32 cyc, u32 mask)
{
u64 epoch_ns;
u32 epoch_cyc;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index d343a6c..234e339 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -56,7 +56,6 @@
#include <asm/virt.h>
#include "atags.h"
-#include "tcm.h"
#if defined(CONFIG_FPE_NWFPE) || defined(CONFIG_FPE_FASTFPE)
@@ -798,8 +797,6 @@
reserve_crashkernel();
- tcm_init();
-
#ifdef CONFIG_MULTI_IRQ_HANDLER
handle_arch_irq = mdesc->handle_irq;
#endif
diff --git a/arch/arm/kernel/tcm.c b/arch/arm/kernel/tcm.c
index 30ae6bb..f50f19e 100644
--- a/arch/arm/kernel/tcm.c
+++ b/arch/arm/kernel/tcm.c
@@ -17,7 +17,6 @@
#include <asm/mach/map.h>
#include <asm/memory.h>
#include <asm/system_info.h>
-#include "tcm.h"
static struct gen_pool *tcm_pool;
static bool dtcm_present;
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 5a93698..c1fe498 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -201,6 +201,7 @@
break;
case KVM_CAP_ARM_SET_DEVICE_ADDR:
r = 1;
+ break;
case KVM_CAP_NR_VCPUS:
r = num_online_cpus();
break;
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 4ea9a98..7bed755 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -79,11 +79,11 @@
u32 val;
int cpu;
- cpu = get_cpu();
-
if (!p->is_write)
return read_from_write_only(vcpu, p);
+ cpu = get_cpu();
+
cpumask_setall(&vcpu->arch.require_dcache_flush);
cpumask_clear_cpu(cpu, &vcpu->arch.require_dcache_flush);
diff --git a/arch/arm/mach-highbank/hotplug.c b/arch/arm/mach-highbank/hotplug.c
index f30c528..890cae2 100644
--- a/arch/arm/mach-highbank/hotplug.c
+++ b/arch/arm/mach-highbank/hotplug.c
@@ -28,13 +28,11 @@
*/
void __ref highbank_cpu_die(unsigned int cpu)
{
- flush_cache_all();
-
highbank_set_cpu_jump(cpu, phys_to_virt(0));
+
+ flush_cache_louis();
highbank_set_core_pwr();
- cpu_do_idle();
-
- /* We should never return from idle */
- panic("highbank: cpu %d unexpectedly exit from shutdown\n", cpu);
+ while (1)
+ cpu_do_idle();
}
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index e13a8fa..2193c83 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -257,6 +257,7 @@
clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
+ clk_register_clkdev(clk[admux_gate], "audmux", NULL);
clk_prepare_enable(clk[spba_gate]);
clk_prepare_enable(clk[gpio1_gate]);
@@ -265,6 +266,7 @@
clk_prepare_enable(clk[iim_gate]);
clk_prepare_enable(clk[emi_gate]);
clk_prepare_enable(clk[max_gate]);
+ clk_prepare_enable(clk[iomuxc_gate]);
/*
* SCC is needed to boot via mmc after a watchdog reset. The clock code
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 2f9ff93..d38e54f 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -115,7 +115,7 @@
static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
-static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", };
+static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
@@ -443,7 +443,6 @@
clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
- clk_register_clkdev(clk[twd], NULL, "smp_twd");
clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);
clk_register_clkdev(clk[ahb], "ahb", NULL);
clk_register_clkdev(clk[cko1], "cko1", NULL);
diff --git a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
index f655b26..e5f7041 100644
--- a/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
+++ b/arch/arm/mach-kirkwood/board-iomega_ix2_200.c
@@ -20,10 +20,15 @@
.duplex = DUPLEX_FULL,
};
+static struct mv643xx_eth_platform_data iomega_ix2_200_ge01_data = {
+ .phy_addr = MV643XX_ETH_PHY_ADDR(11),
+};
+
void __init iomega_ix2_200_init(void)
{
/*
* Basic setup. Needs to be called early.
*/
- kirkwood_ge01_init(&iomega_ix2_200_ge00_data);
+ kirkwood_ge00_init(&iomega_ix2_200_ge00_data);
+ kirkwood_ge01_init(&iomega_ix2_200_ge01_data);
}
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
index 6a9195e..d5970f5 100644
--- a/arch/arm/mach-mvebu/irq-armada-370-xp.c
+++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c
@@ -61,7 +61,6 @@
*/
static void armada_370_xp_irq_mask(struct irq_data *d)
{
-#ifdef CONFIG_SMP
irq_hw_number_t hwirq = irqd_to_hwirq(d);
if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
@@ -70,15 +69,10 @@
else
writel(hwirq, per_cpu_int_base +
ARMADA_370_XP_INT_SET_MASK_OFFS);
-#else
- writel(irqd_to_hwirq(d),
- per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
-#endif
}
static void armada_370_xp_irq_unmask(struct irq_data *d)
{
-#ifdef CONFIG_SMP
irq_hw_number_t hwirq = irqd_to_hwirq(d);
if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
@@ -87,10 +81,6 @@
else
writel(hwirq, per_cpu_int_base +
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
-#else
- writel(irqd_to_hwirq(d),
- per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
-#endif
}
#ifdef CONFIG_SMP
@@ -146,7 +136,11 @@
unsigned int virq, irq_hw_number_t hw)
{
armada_370_xp_irq_mask(irq_get_irq_data(virq));
- writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
+ if (hw != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
+ writel(hw, per_cpu_int_base +
+ ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+ else
+ writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
irq_set_status_flags(virq, IRQ_LEVEL);
if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 9e05765..eaba9dc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -2714,16 +2714,22 @@
{ }
};
-static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = {
- { .role = "48mhz", .clk = "ocp2scp_usb_phy_phy_48m" },
-};
-
/* ocp2scp_usb_phy */
static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
.name = "ocp2scp_usb_phy",
.class = &omap44xx_ocp2scp_hwmod_class,
.clkdm_name = "l3_init_clkdm",
- .main_clk = "func_48m_fclk",
+ /*
+ * ocp2scp_usb_phy_phy_48m is provided by the OMAP4 PRCM IP
+ * block as an "optional clock," and normally should never be
+ * specified as the main_clk for an OMAP IP block. However it
+ * turns out that this clock is actually the main clock for
+ * the ocp2scp_usb_phy IP block:
+ * http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/119943.html
+ * So listing ocp2scp_usb_phy_phy_48m as a main_clk here seems
+ * to be the best workaround.
+ */
+ .main_clk = "ocp2scp_usb_phy_phy_48m",
.prcm = {
.omap4 = {
.clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET,
@@ -2732,8 +2738,6 @@
},
},
.dev_attr = ocp2scp_dev_attr,
- .opt_clks = ocp2scp_usb_phy_opt_clks,
- .opt_clks_cnt = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks),
};
/*
diff --git a/arch/arm/mach-s3c24xx/include/mach/irqs.h b/arch/arm/mach-s3c24xx/include/mach/irqs.h
index b7a9f4d..1e73f5f 100644
--- a/arch/arm/mach-s3c24xx/include/mach/irqs.h
+++ b/arch/arm/mach-s3c24xx/include/mach/irqs.h
@@ -188,10 +188,8 @@
#if defined(CONFIG_CPU_S3C2416)
#define NR_IRQS (IRQ_S3C2416_I2S1 + 1)
-#elif defined(CONFIG_CPU_S3C2443)
-#define NR_IRQS (IRQ_S3C2443_AC97+1)
#else
-#define NR_IRQS (IRQ_S3C2440_AC97+1)
+#define NR_IRQS (IRQ_S3C2443_AC97 + 1)
#endif
/* compatibility define. */
diff --git a/arch/arm/mach-s3c24xx/irq.c b/arch/arm/mach-s3c24xx/irq.c
index cb9f5e0..d8ba9be 100644
--- a/arch/arm/mach-s3c24xx/irq.c
+++ b/arch/arm/mach-s3c24xx/irq.c
@@ -500,7 +500,7 @@
base = (void *)0xfd000000;
intc->reg_mask = base + 0xa4;
- intc->reg_pending = base + 0x08;
+ intc->reg_pending = base + 0xa8;
irq_num = 20;
irq_start = S3C2410_IRQ(32);
irq_offset = 4;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 025d173..4045c49 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -43,7 +43,7 @@
depends on !MMU
select CPU_32v4T
select CPU_ABRT_LV4T
- select CPU_CACHE_V3 # although the core is v4t
+ select CPU_CACHE_V4
select CPU_CP15_MPU
select CPU_PABRT_LEGACY
help
@@ -469,9 +469,6 @@
bool
# The cache model
-config CPU_CACHE_V3
- bool
-
config CPU_CACHE_V4
bool
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 4e333fa..9e51be9 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -33,7 +33,6 @@
obj-$(CONFIG_CPU_PABRT_V6) += pabort-v6.o
obj-$(CONFIG_CPU_PABRT_V7) += pabort-v7.o
-obj-$(CONFIG_CPU_CACHE_V3) += cache-v3.o
obj-$(CONFIG_CPU_CACHE_V4) += cache-v4.o
obj-$(CONFIG_CPU_CACHE_V4WT) += cache-v4wt.o
obj-$(CONFIG_CPU_CACHE_V4WB) += cache-v4wb.o
diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c
index dd3d591..48bc3c0 100644
--- a/arch/arm/mm/cache-feroceon-l2.c
+++ b/arch/arm/mm/cache-feroceon-l2.c
@@ -343,6 +343,7 @@
outer_cache.inv_range = feroceon_l2_inv_range;
outer_cache.clean_range = feroceon_l2_clean_range;
outer_cache.flush_range = feroceon_l2_flush_range;
+ outer_cache.inv_all = l2_inv_all;
enable_l2();
diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S
deleted file mode 100644
index 8a3fade..0000000
--- a/arch/arm/mm/cache-v3.S
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * linux/arch/arm/mm/cache-v3.S
- *
- * Copyright (C) 1997-2002 Russell king
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/page.h>
-#include "proc-macros.S"
-
-/*
- * flush_icache_all()
- *
- * Unconditionally clean and invalidate the entire icache.
- */
-ENTRY(v3_flush_icache_all)
- mov pc, lr
-ENDPROC(v3_flush_icache_all)
-
-/*
- * flush_user_cache_all()
- *
- * Invalidate all cache entries in a particular address
- * space.
- *
- * - mm - mm_struct describing address space
- */
-ENTRY(v3_flush_user_cache_all)
- /* FALLTHROUGH */
-/*
- * flush_kern_cache_all()
- *
- * Clean and invalidate the entire cache.
- */
-ENTRY(v3_flush_kern_cache_all)
- /* FALLTHROUGH */
-
-/*
- * flush_user_cache_range(start, end, flags)
- *
- * Invalidate a range of cache entries in the specified
- * address space.
- *
- * - start - start address (may not be aligned)
- * - end - end address (exclusive, may not be aligned)
- * - flags - vma_area_struct flags describing address space
- */
-ENTRY(v3_flush_user_cache_range)
- mov ip, #0
- mcreq p15, 0, ip, c7, c0, 0 @ flush ID cache
- mov pc, lr
-
-/*
- * coherent_kern_range(start, end)
- *
- * Ensure coherency between the Icache and the Dcache in the
- * region described by start. If you have non-snooping
- * Harvard caches, you need to implement this function.
- *
- * - start - virtual start address
- * - end - virtual end address
- */
-ENTRY(v3_coherent_kern_range)
- /* FALLTHROUGH */
-
-/*
- * coherent_user_range(start, end)
- *
- * Ensure coherency between the Icache and the Dcache in the
- * region described by start. If you have non-snooping
- * Harvard caches, you need to implement this function.
- *
- * - start - virtual start address
- * - end - virtual end address
- */
-ENTRY(v3_coherent_user_range)
- mov r0, #0
- mov pc, lr
-
-/*
- * flush_kern_dcache_area(void *page, size_t size)
- *
- * Ensure no D cache aliasing occurs, either with itself or
- * the I cache
- *
- * - addr - kernel address
- * - size - region size
- */
-ENTRY(v3_flush_kern_dcache_area)
- /* FALLTHROUGH */
-
-/*
- * dma_flush_range(start, end)
- *
- * Clean and invalidate the specified virtual address range.
- *
- * - start - virtual start address
- * - end - virtual end address
- */
-ENTRY(v3_dma_flush_range)
- mov r0, #0
- mcr p15, 0, r0, c7, c0, 0 @ flush ID cache
- mov pc, lr
-
-/*
- * dma_unmap_area(start, size, dir)
- * - start - kernel virtual start address
- * - size - size of region
- * - dir - DMA direction
- */
-ENTRY(v3_dma_unmap_area)
- teq r2, #DMA_TO_DEVICE
- bne v3_dma_flush_range
- /* FALLTHROUGH */
-
-/*
- * dma_map_area(start, size, dir)
- * - start - kernel virtual start address
- * - size - size of region
- * - dir - DMA direction
- */
-ENTRY(v3_dma_map_area)
- mov pc, lr
-ENDPROC(v3_dma_unmap_area)
-ENDPROC(v3_dma_map_area)
-
- .globl v3_flush_kern_cache_louis
- .equ v3_flush_kern_cache_louis, v3_flush_kern_cache_all
-
- __INITDATA
-
- @ define struct cpu_cache_fns (see <asm/cacheflush.h> and proc-macros.S)
- define_cache_functions v3
diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S
index 43e5d77..a7ba68f 100644
--- a/arch/arm/mm/cache-v4.S
+++ b/arch/arm/mm/cache-v4.S
@@ -58,7 +58,7 @@
ENTRY(v4_flush_user_cache_range)
#ifdef CONFIG_CPU_CP15
mov ip, #0
- mcreq p15, 0, ip, c7, c7, 0 @ flush ID cache
+ mcr p15, 0, ip, c7, c7, 0 @ flush ID cache
mov pc, lr
#else
/* FALLTHROUGH */
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 7897894..a84ff76 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -34,6 +34,7 @@
#include <asm/mach/pci.h>
#include "mm.h"
+#include "tcm.h"
/*
* empty_zero_page is a special page that is used for
@@ -1277,6 +1278,7 @@
dma_contiguous_remap();
devicemaps_init(mdesc);
kmap_init();
+ tcm_init();
top_pmd = pmd_off_k(0xffff0000);
diff --git a/arch/arm/mm/proc-arm740.S b/arch/arm/mm/proc-arm740.S
index dc5de5d..fde2d2a 100644
--- a/arch/arm/mm/proc-arm740.S
+++ b/arch/arm/mm/proc-arm740.S
@@ -77,24 +77,27 @@
mcr p15, 0, r0, c6, c0 @ set area 0, default
ldr r0, =(CONFIG_DRAM_BASE & 0xFFFFF000) @ base[31:12] of RAM
- ldr r1, =(CONFIG_DRAM_SIZE >> 12) @ size of RAM (must be >= 4KB)
- mov r2, #10 @ 11 is the minimum (4KB)
-1: add r2, r2, #1 @ area size *= 2
- mov r1, r1, lsr #1
+ ldr r3, =(CONFIG_DRAM_SIZE >> 12) @ size of RAM (must be >= 4KB)
+ mov r4, #10 @ 11 is the minimum (4KB)
+1: add r4, r4, #1 @ area size *= 2
+ movs r3, r3, lsr #1
bne 1b @ count not zero r-shift
- orr r0, r0, r2, lsl #1 @ the area register value
+ orr r0, r0, r4, lsl #1 @ the area register value
orr r0, r0, #1 @ set enable bit
mcr p15, 0, r0, c6, c1 @ set area 1, RAM
ldr r0, =(CONFIG_FLASH_MEM_BASE & 0xFFFFF000) @ base[31:12] of FLASH
- ldr r1, =(CONFIG_FLASH_SIZE >> 12) @ size of FLASH (must be >= 4KB)
- mov r2, #10 @ 11 is the minimum (4KB)
-1: add r2, r2, #1 @ area size *= 2
- mov r1, r1, lsr #1
+ ldr r3, =(CONFIG_FLASH_SIZE >> 12) @ size of FLASH (must be >= 4KB)
+ cmp r3, #0
+ moveq r0, #0
+ beq 2f
+ mov r4, #10 @ 11 is the minimum (4KB)
+1: add r4, r4, #1 @ area size *= 2
+ movs r3, r3, lsr #1
bne 1b @ count not zero r-shift
- orr r0, r0, r2, lsl #1 @ the area register value
+ orr r0, r0, r4, lsl #1 @ the area register value
orr r0, r0, #1 @ set enable bit
- mcr p15, 0, r0, c6, c2 @ set area 2, ROM/FLASH
+2: mcr p15, 0, r0, c6, c2 @ set area 2, ROM/FLASH
mov r0, #0x06
mcr p15, 0, r0, c2, c0 @ Region 1&2 cacheable
@@ -137,13 +140,14 @@
.long 0x41807400
.long 0xfffffff0
.long 0
+ .long 0
b __arm740_setup
.long cpu_arch_name
.long cpu_elf_name
- .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+ .long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_26BIT
.long cpu_arm740_name
.long arm740_processor_functions
.long 0
.long 0
- .long v3_cache_fns @ cache model
+ .long v4_cache_fns @ cache model
.size __arm740_proc_info, . - __arm740_proc_info
diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S
index 2c3b942..2556cf1 100644
--- a/arch/arm/mm/proc-arm920.S
+++ b/arch/arm/mm/proc-arm920.S
@@ -387,7 +387,7 @@
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm920_suspend_size
.equ cpu_arm920_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_arm920_do_suspend)
stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S
index f1803f7..344c8a5 100644
--- a/arch/arm/mm/proc-arm926.S
+++ b/arch/arm/mm/proc-arm926.S
@@ -402,7 +402,7 @@
/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
.globl cpu_arm926_suspend_size
.equ cpu_arm926_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_arm926_do_suspend)
stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c13, c0, 0 @ PID
diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S
index 82f9cdc..0b60dd3 100644
--- a/arch/arm/mm/proc-mohawk.S
+++ b/arch/arm/mm/proc-mohawk.S
@@ -350,7 +350,7 @@
.globl cpu_mohawk_suspend_size
.equ cpu_mohawk_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_mohawk_do_suspend)
stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S
index 3aa0da1..d92dfd0 100644
--- a/arch/arm/mm/proc-sa1100.S
+++ b/arch/arm/mm/proc-sa1100.S
@@ -172,7 +172,7 @@
.globl cpu_sa1100_suspend_size
.equ cpu_sa1100_suspend_size, 4 * 3
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_sa1100_do_suspend)
stmfd sp!, {r4 - r6, lr}
mrc p15, 0, r4, c3, c0, 0 @ domain ID
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index 3e6210b..054b491 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -17,7 +17,9 @@
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_dcache_clean_area);
+#ifdef CONFIG_MMU
EXPORT_SYMBOL(cpu_set_pte_ext);
+#endif
#else
EXPORT_SYMBOL(processor);
#endif
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index bcaaa8d..5c07ee4 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -138,7 +138,7 @@
/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
.globl cpu_v6_suspend_size
.equ cpu_v6_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_v6_do_suspend)
stmfd sp!, {r4 - r9, lr}
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S
index eb93d64..e8efd83 100644
--- a/arch/arm/mm/proc-xsc3.S
+++ b/arch/arm/mm/proc-xsc3.S
@@ -413,7 +413,7 @@
.globl cpu_xsc3_suspend_size
.equ cpu_xsc3_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_xsc3_do_suspend)
stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S
index 2551036..e766f88 100644
--- a/arch/arm/mm/proc-xscale.S
+++ b/arch/arm/mm/proc-xscale.S
@@ -528,7 +528,7 @@
.globl cpu_xscale_suspend_size
.equ cpu_xscale_suspend_size, 4 * 6
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_ARM_CPU_SUSPEND
ENTRY(cpu_xscale_do_suspend)
stmfd sp!, {r4 - r9, lr}
mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode
diff --git a/arch/arm/kernel/tcm.h b/arch/arm/mm/tcm.h
similarity index 100%
rename from arch/arm/kernel/tcm.h
rename to arch/arm/mm/tcm.h
diff --git a/arch/arm/plat-samsung/include/plat/fb.h b/arch/arm/plat-samsung/include/plat/fb.h
index b885322..9ae5072 100644
--- a/arch/arm/plat-samsung/include/plat/fb.h
+++ b/arch/arm/plat-samsung/include/plat/fb.h
@@ -15,55 +15,7 @@
#ifndef __PLAT_S3C_FB_H
#define __PLAT_S3C_FB_H __FILE__
-/* S3C_FB_MAX_WIN
- * Set to the maximum number of windows that any of the supported hardware
- * can use. Since the platform data uses this for an array size, having it
- * set to the maximum of any version of the hardware can do is safe.
- */
-#define S3C_FB_MAX_WIN (5)
-
-/**
- * struct s3c_fb_pd_win - per window setup data
- * @xres : The window X size.
- * @yres : The window Y size.
- * @virtual_x: The virtual X size.
- * @virtual_y: The virtual Y size.
- */
-struct s3c_fb_pd_win {
- unsigned short default_bpp;
- unsigned short max_bpp;
- unsigned short xres;
- unsigned short yres;
- unsigned short virtual_x;
- unsigned short virtual_y;
-};
-
-/**
- * struct s3c_fb_platdata - S3C driver platform specific information
- * @setup_gpio: Setup the external GPIO pins to the right state to transfer
- * the data from the display system to the connected display
- * device.
- * @vidcon0: The base vidcon0 values to control the panel data format.
- * @vidcon1: The base vidcon1 values to control the panel data output.
- * @vtiming: Video timing when connected to a RGB type panel.
- * @win: The setup data for each hardware window, or NULL for unused.
- * @display_mode: The LCD output display mode.
- *
- * The platform data supplies the video driver with all the information
- * it requires to work with the display(s) attached to the machine. It
- * controls the initial mode, the number of display windows (0 is always
- * the base framebuffer) that are initialised etc.
- *
- */
-struct s3c_fb_platdata {
- void (*setup_gpio)(void);
-
- struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN];
- struct fb_videomode *vtiming;
-
- u32 vidcon0;
- u32 vidcon1;
-};
+#include <linux/platform_data/video_s3c.h>
/**
* s3c_fb_set_platdata() - Setup the FB device with platform data.
diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h
index cf60d0a..fc6483f 100644
--- a/arch/avr32/include/asm/io.h
+++ b/arch/avr32/include/asm/io.h
@@ -165,6 +165,10 @@
#define readw_be __raw_readw
#define readl_be __raw_readl
+#define writeb_relaxed writeb
+#define writew_relaxed writew
+#define writel_relaxed writel
+
#define writeb_be __raw_writeb
#define writew_be __raw_writew
#define writel_be __raw_writel
diff --git a/arch/c6x/include/asm/irqflags.h b/arch/c6x/include/asm/irqflags.h
index cf78e09..2c71d56 100644
--- a/arch/c6x/include/asm/irqflags.h
+++ b/arch/c6x/include/asm/irqflags.h
@@ -27,7 +27,7 @@
/* set interrupt enabled status */
static inline void arch_local_irq_restore(unsigned long flags)
{
- asm volatile (" mvc .s2 %0,CSR\n" : : "b"(flags));
+ asm volatile (" mvc .s2 %0,CSR\n" : : "b"(flags) : "memory");
}
/* unconditionally enable interrupts */
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 9a02f71..e7e55a0 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -187,7 +187,7 @@
config IA64_DIG_VTD
bool "DIG+Intel+IOMMU"
- select DMAR
+ select INTEL_IOMMU
select PCI_MSI
config IA64_HP_ZX1
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index d2bf1fd..76acbcd 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -106,16 +106,15 @@
return -EFAULT;
{
- register unsigned long r8 __asm ("r8");
+ register unsigned long r8 __asm ("r8") = 0;
unsigned long prev;
__asm__ __volatile__(
" mf;; \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" (r8), "=r" (prev)
+ : "+r" (r8), "=&r" (prev)
: "r" (uaddr), "r" (newval),
"rO" ((long) (unsigned) oldval)
: "memory");
diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h
index 43f96ab..8c70961 100644
--- a/arch/ia64/include/asm/mca.h
+++ b/arch/ia64/include/asm/mca.h
@@ -143,6 +143,7 @@
extern int cpe_vector;
extern int ia64_cpe_irq;
extern void ia64_mca_init(void);
+extern void ia64_mca_irq_init(void);
extern void ia64_mca_cpu_init(void *);
extern void ia64_os_mca_dispatch(void);
extern void ia64_os_mca_dispatch_end(void);
diff --git a/arch/ia64/include/asm/numa.h b/arch/ia64/include/asm/numa.h
index 2e27ef1..2db0a6c 100644
--- a/arch/ia64/include/asm/numa.h
+++ b/arch/ia64/include/asm/numa.h
@@ -67,14 +67,13 @@
extern void map_cpu_to_node(int cpu, int nid);
extern void unmap_cpu_from_node(int cpu, int nid);
-
+extern void numa_clear_node(int cpu);
#else /* !CONFIG_NUMA */
#define map_cpu_to_node(cpu, nid) do{}while(0)
#define unmap_cpu_from_node(cpu, nid) do{}while(0)
-
#define paddr_to_nid(addr) 0
-
+#define numa_clear_node(cpu) do { } while (0)
#endif /* CONFIG_NUMA */
#endif /* _ASM_IA64_NUMA_H */
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index c4cd45d..abc6dee 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -90,53 +90,6 @@
FSYS_RETURN
END(fsys_getpid)
-ENTRY(fsys_getppid)
- .prologue
- .altrp b6
- .body
- add r17=IA64_TASK_GROUP_LEADER_OFFSET,r16
- ;;
- ld8 r17=[r17] // r17 = current->group_leader
- add r9=TI_FLAGS+IA64_TASK_SIZE,r16
- ;;
-
- ld4 r9=[r9]
- add r17=IA64_TASK_REAL_PARENT_OFFSET,r17 // r17 = ¤t->group_leader->real_parent
- ;;
- and r9=TIF_ALLWORK_MASK,r9
-
-1: ld8 r18=[r17] // r18 = current->group_leader->real_parent
- ;;
- cmp.ne p8,p0=0,r9
- add r8=IA64_TASK_TGID_OFFSET,r18 // r8 = ¤t->group_leader->real_parent->tgid
- ;;
-
- /*
- * The .acq is needed to ensure that the read of tgid has returned its data before
- * we re-check "real_parent".
- */
- ld4.acq r8=[r8] // r8 = current->group_leader->real_parent->tgid
-#ifdef CONFIG_SMP
- /*
- * Re-read current->group_leader->real_parent.
- */
- ld8 r19=[r17] // r19 = current->group_leader->real_parent
-(p8) br.spnt.many fsys_fallback_syscall
- ;;
- cmp.ne p6,p0=r18,r19 // did real_parent change?
- mov r19=0 // i must not leak kernel bits...
-(p6) br.cond.spnt.few 1b // yes -> redo the read of tgid and the check
- ;;
- mov r17=0 // i must not leak kernel bits...
- mov r18=0 // i must not leak kernel bits...
-#else
- mov r17=0 // i must not leak kernel bits...
- mov r18=0 // i must not leak kernel bits...
- mov r19=0 // i must not leak kernel bits...
-#endif
- FSYS_RETURN
-END(fsys_getppid)
-
ENTRY(fsys_set_tid_address)
.prologue
.altrp b6
@@ -614,7 +567,7 @@
data8 0 // chown
data8 0 // lseek // 1040
data8 fsys_getpid // getpid
- data8 fsys_getppid // getppid
+ data8 0 // getppid
data8 0 // mount
data8 0 // umount
data8 0 // setuid // 1045
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index ee33c3a..19f107b 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -76,7 +76,7 @@
* PCI pin -> global system interrupt (GSI) -> IA-64 vector <-> IRQ
*
* Note: The term "IRQ" is loosely used everywhere in Linux kernel to
- * describeinterrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ
+ * describe interrupts. Now we use "IRQ" only for Linux IRQ's. ISA IRQ
* (isa_irq) is the only exception in this source code.
*/
@@ -1010,6 +1010,26 @@
return 0;
}
+static int
+iosapic_delete_rte(unsigned int irq, unsigned int gsi)
+{
+ struct iosapic_rte_info *rte, *temp;
+
+ list_for_each_entry_safe(rte, temp, &iosapic_intr_info[irq].rtes,
+ rte_list) {
+ if (rte->iosapic->gsi_base + rte->rte_index == gsi) {
+ if (rte->refcnt)
+ return -EBUSY;
+
+ list_del(&rte->rte_list);
+ kfree(rte);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
int iosapic_init(unsigned long phys_addr, unsigned int gsi_base)
{
int num_rte, err, index;
@@ -1069,7 +1089,7 @@
int iosapic_remove(unsigned int gsi_base)
{
- int index, err = 0;
+ int i, irq, index, err = 0;
unsigned long flags;
spin_lock_irqsave(&iosapic_lock, flags);
@@ -1087,6 +1107,16 @@
goto out;
}
+ for (i = gsi_base; i < gsi_base + iosapic_lists[index].num_rte; i++) {
+ irq = __gsi_to_irq(i);
+ if (irq < 0)
+ continue;
+
+ err = iosapic_delete_rte(irq, i);
+ if (err)
+ goto out;
+ }
+
iounmap(iosapic_lists[index].addr);
iosapic_free(index);
out:
diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
index ad69606..f2c41828 100644
--- a/arch/ia64/kernel/irq.c
+++ b/arch/ia64/kernel/irq.c
@@ -23,6 +23,8 @@
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <asm/mca.h>
+
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -83,6 +85,12 @@
#endif /* CONFIG_SMP */
+int __init arch_early_irq_init(void)
+{
+ ia64_mca_irq_init();
+ return 0;
+}
+
#ifdef CONFIG_HOTPLUG_CPU
unsigned int vectors_in_migration[NR_IRQS];
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 65bf9cd..d7396db 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -2074,22 +2074,16 @@
printk(KERN_INFO "MCA related initialization done\n");
}
-/*
- * ia64_mca_late_init
- *
- * Opportunity to setup things that require initialization later
- * than ia64_mca_init. Setup a timer to poll for CPEs if the
- * platform doesn't support an interrupt driven mechanism.
- *
- * Inputs : None
- * Outputs : Status
- */
-static int __init
-ia64_mca_late_init(void)
-{
- if (!mca_init)
- return 0;
+/*
+ * These pieces cannot be done in ia64_mca_init() because it is called before
+ * early_irq_init() which would wipe out our percpu irq registrations. But we
+ * cannot leave them until ia64_mca_late_init() because by then all the other
+ * processors have been brought online and have set their own CMC vectors to
+ * point at a non-existant action. Called from arch_early_irq_init().
+ */
+void __init ia64_mca_irq_init(void)
+{
/*
* Configure the CMCI/P vector and handler. Interrupts for CMC are
* per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c).
@@ -2108,6 +2102,23 @@
/* Setup the CPEI/P handler */
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
#endif
+}
+
+/*
+ * ia64_mca_late_init
+ *
+ * Opportunity to setup things that require initialization later
+ * than ia64_mca_init. Setup a timer to poll for CPEs if the
+ * platform doesn't support an interrupt driven mechanism.
+ *
+ * Inputs : None
+ * Outputs : Status
+ */
+static int __init
+ia64_mca_late_init(void)
+{
+ if (!mca_init)
+ return 0;
register_hotcpu_notifier(&mca_cpu_notifier);
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 9392e02..94f8bf7 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -349,7 +349,7 @@
/* - 3 - */
slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
- slidx_pool.buffer = (slidx_list_t *)
+ slidx_pool.buffer =
kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
return slidx_pool.buffer ? 0 : -ENOMEM;
diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c
index 77597e5..79521d5 100644
--- a/arch/ia64/kernel/palinfo.c
+++ b/arch/ia64/kernel/palinfo.c
@@ -849,17 +849,6 @@
#define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries)
-/*
- * this array is used to keep track of the proc entries we create. This is
- * required in the module mode when we need to remove all entries. The procfs code
- * does not do recursion of deletion
- *
- * Notes:
- * - +1 accounts for the cpuN directory entry in /proc/pal
- */
-#define NR_PALINFO_PROC_ENTRIES (NR_CPUS*(NR_PALINFO_ENTRIES+1))
-
-static struct proc_dir_entry *palinfo_proc_entries[NR_PALINFO_PROC_ENTRIES];
static struct proc_dir_entry *palinfo_dir;
/*
@@ -971,60 +960,32 @@
static void __cpuinit
create_palinfo_proc_entries(unsigned int cpu)
{
-# define CPUSTR "cpu%d"
-
pal_func_cpu_u_t f;
- struct proc_dir_entry **pdir;
struct proc_dir_entry *cpu_dir;
int j;
- char cpustr[sizeof(CPUSTR)];
-
-
- /*
- * we keep track of created entries in a depth-first order for
- * cleanup purposes. Each entry is stored into palinfo_proc_entries
- */
- sprintf(cpustr,CPUSTR, cpu);
+ char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
+ sprintf(cpustr, "cpu%d", cpu);
cpu_dir = proc_mkdir(cpustr, palinfo_dir);
+ if (!cpu_dir)
+ return;
f.req_cpu = cpu;
- /*
- * Compute the location to store per cpu entries
- * We dont store the top level entry in this list, but
- * remove it finally after removing all cpu entries.
- */
- pdir = &palinfo_proc_entries[cpu*(NR_PALINFO_ENTRIES+1)];
- *pdir++ = cpu_dir;
for (j=0; j < NR_PALINFO_ENTRIES; j++) {
f.func_id = j;
- *pdir = create_proc_read_entry(
- palinfo_entries[j].name, 0, cpu_dir,
- palinfo_read_entry, (void *)f.value);
- pdir++;
+ create_proc_read_entry(
+ palinfo_entries[j].name, 0, cpu_dir,
+ palinfo_read_entry, (void *)f.value);
}
}
static void
remove_palinfo_proc_entries(unsigned int hcpu)
{
- int j;
- struct proc_dir_entry *cpu_dir, **pdir;
-
- pdir = &palinfo_proc_entries[hcpu*(NR_PALINFO_ENTRIES+1)];
- cpu_dir = *pdir;
- *pdir++=NULL;
- for (j=0; j < (NR_PALINFO_ENTRIES); j++) {
- if ((*pdir)) {
- remove_proc_entry ((*pdir)->name, cpu_dir);
- *pdir ++= NULL;
- }
- }
-
- if (cpu_dir) {
- remove_proc_entry(cpu_dir->name, palinfo_dir);
- }
+ char cpustr[3+4+1]; /* cpu numbers are up to 4095 on itanic */
+ sprintf(cpustr, "cpu%d", hcpu);
+ remove_proc_subtree(cpustr, palinfo_dir);
}
static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb,
@@ -1058,6 +1019,8 @@
printk(KERN_INFO "PAL Information Facility v%s\n", PALINFO_VERSION);
palinfo_dir = proc_mkdir("pal", NULL);
+ if (!palinfo_dir)
+ return -ENOMEM;
/* Create palinfo dirs in /proc for all online cpus */
for_each_online_cpu(i) {
@@ -1073,22 +1036,8 @@
static void __exit
palinfo_exit(void)
{
- int i = 0;
-
- /* remove all nodes: depth first pass. Could optimize this */
- for_each_online_cpu(i) {
- remove_palinfo_proc_entries(i);
- }
-
- /*
- * Remove the top level entry finally
- */
- remove_proc_entry(palinfo_dir->name, NULL);
-
- /*
- * Unregister from cpu notifier callbacks
- */
unregister_hotcpu_notifier(&palinfo_cpu_notifier);
+ remove_proc_subtree("pal", NULL);
}
module_init(palinfo_init);
diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c
index 4332f7e..a7869f8 100644
--- a/arch/ia64/kvm/vtlb.c
+++ b/arch/ia64/kvm/vtlb.c
@@ -256,7 +256,7 @@
"srlz.d;;"
"ssm psr.i;;"
"srlz.d;;"
- : "=r"(ret) : "r"(iha), "r"(pte):"memory");
+ : "=&r"(ret) : "r"(iha), "r"(pte) : "memory");
return ret;
}
diff --git a/arch/ia64/mm/ioremap.c b/arch/ia64/mm/ioremap.c
index 3dccdd8..43964cd 100644
--- a/arch/ia64/mm/ioremap.c
+++ b/arch/ia64/mm/ioremap.c
@@ -16,7 +16,7 @@
#include <asm/meminit.h>
static inline void __iomem *
-__ioremap (unsigned long phys_addr)
+__ioremap_uc(unsigned long phys_addr)
{
return (void __iomem *) (__IA64_UNCACHED_OFFSET | phys_addr);
}
@@ -24,7 +24,11 @@
void __iomem *
early_ioremap (unsigned long phys_addr, unsigned long size)
{
- return __ioremap(phys_addr);
+ u64 attr;
+ attr = kern_mem_attribute(phys_addr, size);
+ if (attr & EFI_MEMORY_WB)
+ return (void __iomem *) phys_to_virt(phys_addr);
+ return __ioremap_uc(phys_addr);
}
void __iomem *
@@ -47,7 +51,7 @@
if (attr & EFI_MEMORY_WB)
return (void __iomem *) phys_to_virt(phys_addr);
else if (attr & EFI_MEMORY_UC)
- return __ioremap(phys_addr);
+ return __ioremap_uc(phys_addr);
/*
* Some chipsets don't support UC access to memory. If
@@ -93,7 +97,7 @@
return (void __iomem *) (offset + (char __iomem *)addr);
}
- return __ioremap(phys_addr);
+ return __ioremap_uc(phys_addr);
}
EXPORT_SYMBOL(ioremap);
@@ -103,7 +107,7 @@
if (kern_mem_attribute(phys_addr, size) & EFI_MEMORY_WB)
return NULL;
- return __ioremap(phys_addr);
+ return __ioremap_uc(phys_addr);
}
EXPORT_SYMBOL(ioremap_nocache);
diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
index 3efea7d..def782e 100644
--- a/arch/ia64/mm/numa.c
+++ b/arch/ia64/mm/numa.c
@@ -73,6 +73,11 @@
return -1;
}
+void __cpuinit numa_clear_node(int cpu)
+{
+ unmap_cpu_from_node(cpu, NUMA_NO_NODE);
+}
+
#ifdef CONFIG_MEMORY_HOTPLUG
/*
* SRAT information is stored in node_memblk[], then we can use SRAT
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 60532ab..de1474f 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/slab.h>
@@ -458,6 +459,16 @@
platform_pci_fixup_bus(b);
}
+void pcibios_add_bus(struct pci_bus *bus)
+{
+ acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+ acpi_pci_remove_bus(bus);
+}
+
void pcibios_set_master (struct pci_dev *dev)
{
/* No special bus mastering setup handling */
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index 14c1711..e35f648 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -490,11 +490,14 @@
{
cnodeid_t cnodeid;
int found_tiocx_device = 0;
+ int err;
if (!ia64_platform_is("sn2"))
return 0;
- bus_register(&tiocx_bus_type);
+ err = bus_register(&tiocx_bus_type);
+ if (err)
+ return err;
for (cnodeid = 0; cnodeid < num_cnodes; cnodeid++) {
nasid_t nasid;
diff --git a/arch/m68k/include/asm/gpio.h b/arch/m68k/include/asm/gpio.h
index 4395ffc..8cc8343 100644
--- a/arch/m68k/include/asm/gpio.h
+++ b/arch/m68k/include/asm/gpio.h
@@ -86,4 +86,24 @@
return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
}
+static inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ int err;
+
+ err = gpio_request(gpio, label);
+ if (err)
+ return err;
+
+ if (flags & GPIOF_DIR_IN)
+ err = gpio_direction_input(gpio);
+ else
+ err = gpio_direction_output(gpio,
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+ if (err)
+ gpio_free(gpio);
+
+ return err;
+}
+
#endif
diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h
index 99fc547..eab99e5 100644
--- a/arch/mips/include/asm/page.h
+++ b/arch/mips/include/asm/page.h
@@ -31,7 +31,7 @@
#define PAGE_SHIFT 16
#endif
#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
-#define PAGE_MASK (~(PAGE_SIZE - 1))
+#define PAGE_MASK (~((1 << PAGE_SHIFT) - 1))
#ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT
#define HPAGE_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 0872f12..594e60d 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -115,7 +115,6 @@
pci_bus_assign_resources(bus);
pci_enable_bridges(bus);
}
- bus->dev.of_node = hose->of_node;
}
}
@@ -169,6 +168,13 @@
}
}
}
+
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
+{
+ struct pci_controller *hose = bus->sysdata;
+
+ return of_node_get(hose->of_node);
+}
#endif
static DEFINE_MUTEX(pci_scan_mutex);
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile
index 01d95e2..113e282 100644
--- a/arch/parisc/Makefile
+++ b/arch/parisc/Makefile
@@ -65,8 +65,10 @@
endif
# Use long jumps instead of long branches (needed if your linker fails to
-# link a too big vmlinux executable)
-cflags-$(CONFIG_MLONGCALLS) += -mlong-calls
+# link a too big vmlinux executable). Not enabled for building modules.
+ifdef CONFIG_MLONGCALLS
+KBUILD_CFLAGS_KERNEL += -mlong-calls
+endif
# select which processor to optimise for
cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index 79f694f..f0e2784 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -140,7 +140,10 @@
return page_address(page);
}
-#define kunmap(page) kunmap_parisc(page_address(page))
+static inline void kunmap(struct page *page)
+{
+ kunmap_parisc(page_address(page));
+}
static inline void *kmap_atomic(struct page *page)
{
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h
index 7df49fa..1e40d7f 100644
--- a/arch/parisc/include/asm/pgtable.h
+++ b/arch/parisc/include/asm/pgtable.h
@@ -16,6 +16,8 @@
#include <asm/processor.h>
#include <asm/cache.h>
+extern spinlock_t pa_dbit_lock;
+
/*
* kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel
* memory. For the return value to be meaningful, ADDR must be >=
@@ -44,8 +46,11 @@
#define set_pte_at(mm, addr, ptep, pteval) \
do { \
+ unsigned long flags; \
+ spin_lock_irqsave(&pa_dbit_lock, flags); \
set_pte(ptep, pteval); \
purge_tlb_entries(mm, addr); \
+ spin_unlock_irqrestore(&pa_dbit_lock, flags); \
} while (0)
#endif /* !__ASSEMBLY__ */
@@ -435,48 +440,46 @@
static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
{
-#ifdef CONFIG_SMP
+ pte_t pte;
+ unsigned long flags;
+
if (!pte_young(*ptep))
return 0;
- return test_and_clear_bit(xlate_pabit(_PAGE_ACCESSED_BIT), &pte_val(*ptep));
-#else
- pte_t pte = *ptep;
- if (!pte_young(pte))
- return 0;
- set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
- return 1;
-#endif
-}
-extern spinlock_t pa_dbit_lock;
+ spin_lock_irqsave(&pa_dbit_lock, flags);
+ pte = *ptep;
+ if (!pte_young(pte)) {
+ spin_unlock_irqrestore(&pa_dbit_lock, flags);
+ return 0;
+ }
+ set_pte(ptep, pte_mkold(pte));
+ purge_tlb_entries(vma->vm_mm, addr);
+ spin_unlock_irqrestore(&pa_dbit_lock, flags);
+ return 1;
+}
struct mm_struct;
static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t old_pte;
+ unsigned long flags;
- spin_lock(&pa_dbit_lock);
+ spin_lock_irqsave(&pa_dbit_lock, flags);
old_pte = *ptep;
pte_clear(mm,addr,ptep);
- spin_unlock(&pa_dbit_lock);
+ purge_tlb_entries(mm, addr);
+ spin_unlock_irqrestore(&pa_dbit_lock, flags);
return old_pte;
}
static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
-#ifdef CONFIG_SMP
- unsigned long new, old;
-
- do {
- old = pte_val(*ptep);
- new = pte_val(pte_wrprotect(__pte (old)));
- } while (cmpxchg((unsigned long *) ptep, old, new) != old);
+ unsigned long flags;
+ spin_lock_irqsave(&pa_dbit_lock, flags);
+ set_pte(ptep, pte_wrprotect(*ptep));
purge_tlb_entries(mm, addr);
-#else
- pte_t old_pte = *ptep;
- set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
-#endif
+ spin_unlock_irqrestore(&pa_dbit_lock, flags);
}
#define pte_same(A,B) (pte_val(A) == pte_val(B))
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 4ba2c93..e0a8235 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -181,30 +181,24 @@
#if !defined(CONFIG_64BIT)
#define __put_kernel_asm64(__val,ptr) do { \
- u64 __val64 = (u64)(__val); \
- u32 hi = (__val64) >> 32; \
- u32 lo = (__val64) & 0xffffffff; \
__asm__ __volatile__ ( \
"\n1:\tstw %2,0(%1)" \
- "\n2:\tstw %3,4(%1)\n\t" \
+ "\n2:\tstw %R2,4(%1)\n\t" \
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
: "=r"(__pu_err) \
- : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r"(ptr), "r"(__val), "0"(__pu_err) \
: "r1"); \
} while (0)
#define __put_user_asm64(__val,ptr) do { \
- u64 __val64 = (u64)(__val); \
- u32 hi = (__val64) >> 32; \
- u32 lo = (__val64) & 0xffffffff; \
__asm__ __volatile__ ( \
"\n1:\tstw %2,0(%%sr3,%1)" \
- "\n2:\tstw %3,4(%%sr3,%1)\n\t" \
+ "\n2:\tstw %R2,4(%%sr3,%1)\n\t" \
ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\
ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\
: "=r"(__pu_err) \
- : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \
+ : "r"(ptr), "r"(__val), "0"(__pu_err) \
: "r1"); \
} while (0)
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 4b12890..83ded26 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -421,14 +421,11 @@
/* Note: purge_tlb_entries can be called at startup with
no context. */
- /* Disable preemption while we play with %sr1. */
- preempt_disable();
- mtsp(mm->context, 1);
purge_tlb_start(flags);
+ mtsp(mm->context, 1);
pdtlb(addr);
pitlb(addr);
purge_tlb_end(flags);
- preempt_enable();
}
EXPORT_SYMBOL(purge_tlb_entries);
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 6795dc6..568b2c6 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -120,11 +120,13 @@
extern void __ashldi3(void);
extern void __lshrdi3(void);
extern void __muldi3(void);
+extern void __ucmpdi2(void);
EXPORT_SYMBOL(__ashrdi3);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
asmlinkage void * __canonicalize_funcptr_for_compare(void *);
EXPORT_SYMBOL(__canonicalize_funcptr_for_compare);
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile
index 5f2e690..5651536 100644
--- a/arch/parisc/lib/Makefile
+++ b/arch/parisc/lib/Makefile
@@ -2,6 +2,7 @@
# Makefile for parisc-specific library files
#
-lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
+lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \
+ ucmpdi2.o
obj-y := iomap.o
diff --git a/arch/parisc/lib/ucmpdi2.c b/arch/parisc/lib/ucmpdi2.c
new file mode 100644
index 0000000..149c016
--- /dev/null
+++ b/arch/parisc/lib/ucmpdi2.c
@@ -0,0 +1,25 @@
+#include <linux/module.h>
+
+union ull_union {
+ unsigned long long ull;
+ struct {
+ unsigned int high;
+ unsigned int low;
+ } ui;
+};
+
+int __ucmpdi2(unsigned long long a, unsigned long long b)
+{
+ union ull_union au = {.ull = a};
+ union ull_union bu = {.ull = b};
+
+ if (au.ui.high < bu.ui.high)
+ return 0;
+ else if (au.ui.high > bu.ui.high)
+ return 2;
+ if (au.ui.low < bu.ui.low)
+ return 0;
+ else if (au.ui.low > bu.ui.low)
+ return 2;
+ return 1;
+}
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 256c5bf..04d69c4 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -304,7 +304,7 @@
subi r12,r12,TI_FLAGS
4: /* Anything else left to do? */
- SET_DEFAULT_THREAD_PPR(r3, r9) /* Set thread.ppr = 3 */
+ SET_DEFAULT_THREAD_PPR(r3, r10) /* Set thread.ppr = 3 */
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
beq .ret_from_except_lite
@@ -657,7 +657,7 @@
/* Clear _TIF_EMULATE_STACK_STORE flag */
lis r11,_TIF_EMULATE_STACK_STORE@h
addi r5,r9,TI_FLAGS
- ldarx r4,0,r5
+0: ldarx r4,0,r5
andc r4,r4,r11
stdcx. r4,0,r5
bne- 0b
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 59dd545..16e77a8 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -555,10 +555,12 @@
new->thread.regs->msr |=
(MSR_FP | new->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(&new->thread);
new->thread.regs->msr |= MSR_VEC;
}
+#endif
/* We may as well turn on VSX too since all the state is restored now */
if (msr & MSR_VSX)
new->thread.regs->msr |= MSR_VSX;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 3acb28e..95068bf 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -866,10 +866,12 @@
do_load_up_transact_fpu(¤t->thread);
regs->msr |= (MSR_FP | current->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(¤t->thread);
regs->msr |= MSR_VEC;
}
+#endif
return 0;
}
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 995f854..c179428 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -522,10 +522,12 @@
do_load_up_transact_fpu(¤t->thread);
regs->msr |= (MSR_FP | current->thread.fpexc_mode);
}
+#ifdef CONFIG_ALTIVEC
if (msr & MSR_VEC) {
do_load_up_transact_altivec(¤t->thread);
regs->msr |= MSR_VEC;
}
+#endif
return err;
}
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S
index 84dbace..2da67e7 100644
--- a/arch/powerpc/kernel/tm.S
+++ b/arch/powerpc/kernel/tm.S
@@ -309,6 +309,7 @@
or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */
mtmsr r5
+#ifdef CONFIG_ALTIVEC
/* FP and VEC registers: These are recheckpointed from thread.fpr[]
* and thread.vr[] respectively. The thread.transact_fpr[] version
* is more modern, and will be loaded subsequently by any FPUnavailable
@@ -323,6 +324,7 @@
REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */
ld r5, THREAD_VRSAVE(r3)
mtspr SPRN_VRSAVE, r5
+#endif
dont_restore_vec:
andi. r0, r4, MSR_FP
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h
index 41cefd4..33db48a 100644
--- a/arch/powerpc/kvm/e500.h
+++ b/arch/powerpc/kvm/e500.h
@@ -26,17 +26,20 @@
#define E500_PID_NUM 3
#define E500_TLB_NUM 2
-#define E500_TLB_VALID 1
-#define E500_TLB_BITMAP 2
+/* entry is mapped somewhere in host TLB */
+#define E500_TLB_VALID (1 << 0)
+/* TLB1 entry is mapped by host TLB1, tracked by bitmaps */
+#define E500_TLB_BITMAP (1 << 1)
+/* TLB1 entry is mapped by host TLB0 */
#define E500_TLB_TLB0 (1 << 2)
struct tlbe_ref {
- pfn_t pfn;
- unsigned int flags; /* E500_TLB_* */
+ pfn_t pfn; /* valid only for TLB0, except briefly */
+ unsigned int flags; /* E500_TLB_* */
};
struct tlbe_priv {
- struct tlbe_ref ref; /* TLB0 only -- TLB1 uses tlb_refs */
+ struct tlbe_ref ref;
};
#ifdef CONFIG_KVM_E500V2
@@ -63,17 +66,6 @@
unsigned int gtlb_nv[E500_TLB_NUM];
- /*
- * information associated with each host TLB entry --
- * TLB1 only for now. If/when guest TLB1 entries can be
- * mapped with host TLB0, this will be used for that too.
- *
- * We don't want to use this for guest TLB0 because then we'd
- * have the overhead of doing the translation again even if
- * the entry is still in the guest TLB (e.g. we swapped out
- * and back, and our host TLB entries got evicted).
- */
- struct tlbe_ref *tlb_refs[E500_TLB_NUM];
unsigned int host_tlb1_nv;
u32 svr;
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index a222edf..1c6a9d72 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -193,8 +193,11 @@
struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[tlbsel][esel].ref;
/* Don't bother with unmapped entries */
- if (!(ref->flags & E500_TLB_VALID))
- return;
+ if (!(ref->flags & E500_TLB_VALID)) {
+ WARN(ref->flags & (E500_TLB_BITMAP | E500_TLB_TLB0),
+ "%s: flags %x\n", __func__, ref->flags);
+ WARN_ON(tlbsel == 1 && vcpu_e500->g2h_tlb1_map[esel]);
+ }
if (tlbsel == 1 && ref->flags & E500_TLB_BITMAP) {
u64 tmp = vcpu_e500->g2h_tlb1_map[esel];
@@ -248,7 +251,7 @@
pfn_t pfn)
{
ref->pfn = pfn;
- ref->flags = E500_TLB_VALID;
+ ref->flags |= E500_TLB_VALID;
if (tlbe_is_writable(gtlbe))
kvm_set_pfn_dirty(pfn);
@@ -257,6 +260,7 @@
static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
{
if (ref->flags & E500_TLB_VALID) {
+ /* FIXME: don't log bogus pfn for TLB1 */
trace_kvm_booke206_ref_release(ref->pfn, ref->flags);
ref->flags = 0;
}
@@ -274,36 +278,23 @@
static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
{
- int tlbsel = 0;
+ int tlbsel;
int i;
- for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
- struct tlbe_ref *ref =
- &vcpu_e500->gtlb_priv[tlbsel][i].ref;
- kvmppc_e500_ref_release(ref);
+ for (tlbsel = 0; tlbsel <= 1; tlbsel++) {
+ for (i = 0; i < vcpu_e500->gtlb_params[tlbsel].entries; i++) {
+ struct tlbe_ref *ref =
+ &vcpu_e500->gtlb_priv[tlbsel][i].ref;
+ kvmppc_e500_ref_release(ref);
+ }
}
}
-static void clear_tlb_refs(struct kvmppc_vcpu_e500 *vcpu_e500)
-{
- int stlbsel = 1;
- int i;
-
- kvmppc_e500_tlbil_all(vcpu_e500);
-
- for (i = 0; i < host_tlb_params[stlbsel].entries; i++) {
- struct tlbe_ref *ref =
- &vcpu_e500->tlb_refs[stlbsel][i];
- kvmppc_e500_ref_release(ref);
- }
-
- clear_tlb_privs(vcpu_e500);
-}
-
void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
- clear_tlb_refs(vcpu_e500);
+ kvmppc_e500_tlbil_all(vcpu_e500);
+ clear_tlb_privs(vcpu_e500);
clear_tlb1_bitmap(vcpu_e500);
}
@@ -458,8 +449,6 @@
gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
}
- /* Drop old ref and setup new one. */
- kvmppc_e500_ref_release(ref);
kvmppc_e500_ref_setup(ref, gtlbe, pfn);
kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
@@ -507,14 +496,15 @@
if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
vcpu_e500->host_tlb1_nv = 0;
- vcpu_e500->tlb_refs[1][sesel] = *ref;
- vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
- vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
if (vcpu_e500->h2g_tlb1_rmap[sesel]) {
- unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel];
+ unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel] - 1;
vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel);
}
- vcpu_e500->h2g_tlb1_rmap[sesel] = esel;
+
+ vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
+ vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
+ vcpu_e500->h2g_tlb1_rmap[sesel] = esel + 1;
+ WARN_ON(!(ref->flags & E500_TLB_VALID));
return sesel;
}
@@ -526,13 +516,12 @@
u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
struct kvm_book3e_206_tlb_entry *stlbe, int esel)
{
- struct tlbe_ref ref;
+ struct tlbe_ref *ref = &vcpu_e500->gtlb_priv[1][esel].ref;
int sesel;
int r;
- ref.flags = 0;
r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe,
- &ref);
+ ref);
if (r)
return r;
@@ -544,7 +533,7 @@
}
/* Otherwise map into TLB1 */
- sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, &ref, esel);
+ sesel = kvmppc_e500_tlb1_map_tlb1(vcpu_e500, ref, esel);
write_stlbe(vcpu_e500, gtlbe, stlbe, 1, sesel);
return 0;
@@ -565,7 +554,7 @@
case 0:
priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
- /* Triggers after clear_tlb_refs or on initial mapping */
+ /* Triggers after clear_tlb_privs or on initial mapping */
if (!(priv->ref.flags & E500_TLB_VALID)) {
kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
} else {
@@ -665,35 +654,16 @@
host_tlb_params[0].entries / host_tlb_params[0].ways;
host_tlb_params[1].sets = 1;
- vcpu_e500->tlb_refs[0] =
- kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[0].entries,
- GFP_KERNEL);
- if (!vcpu_e500->tlb_refs[0])
- goto err;
-
- vcpu_e500->tlb_refs[1] =
- kzalloc(sizeof(struct tlbe_ref) * host_tlb_params[1].entries,
- GFP_KERNEL);
- if (!vcpu_e500->tlb_refs[1])
- goto err;
-
vcpu_e500->h2g_tlb1_rmap = kzalloc(sizeof(unsigned int) *
host_tlb_params[1].entries,
GFP_KERNEL);
if (!vcpu_e500->h2g_tlb1_rmap)
- goto err;
+ return -EINVAL;
return 0;
-
-err:
- kfree(vcpu_e500->tlb_refs[0]);
- kfree(vcpu_e500->tlb_refs[1]);
- return -EINVAL;
}
void e500_mmu_host_uninit(struct kvmppc_vcpu_e500 *vcpu_e500)
{
kfree(vcpu_e500->h2g_tlb1_rmap);
- kfree(vcpu_e500->tlb_refs[0]);
- kfree(vcpu_e500->tlb_refs[1]);
}
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index 1f89d26..2f4baa0 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -108,6 +108,8 @@
{
}
+static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu);
+
void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu);
@@ -136,8 +138,11 @@
mtspr(SPRN_GDEAR, vcpu->arch.shared->dar);
mtspr(SPRN_GESR, vcpu->arch.shared->esr);
- if (vcpu->arch.oldpir != mfspr(SPRN_PIR))
+ if (vcpu->arch.oldpir != mfspr(SPRN_PIR) ||
+ __get_cpu_var(last_vcpu_on_cpu) != vcpu) {
kvmppc_e500_tlbil_all(vcpu_e500);
+ __get_cpu_var(last_vcpu_on_cpu) = vcpu;
+ }
kvmppc_load_guest_fp(vcpu);
}
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 0da39fe..299731e 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -186,7 +186,13 @@
(0x1UL << 4), &dummy1, &dummy2);
if (lpar_rc == H_SUCCESS)
return i;
- BUG_ON(lpar_rc != H_NOT_FOUND);
+
+ /*
+ * The test for adjunct partition is performed before the
+ * ANDCOND test. H_RESOURCE may be returned, so we need to
+ * check for that as well.
+ */
+ BUG_ON(lpar_rc != H_NOT_FOUND && lpar_rc != H_RESOURCE);
slot_offset++;
slot_offset &= 0x7;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index eb8fb62..bda6ba6 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -375,19 +375,6 @@
Say Y if you are unsure.
-config SMALL_STACK
- def_bool n
- prompt "Use 8kb for kernel stack instead of 16kb"
- depends on PACK_STACK && 64BIT && !LOCKDEP
- help
- If you say Y here and the compiler supports the -mkernel-backchain
- option the kernel will use a smaller kernel stack size. The reduced
- size is 8kb instead of 16kb. This allows to run more threads on a
- system and reduces the pressure on the memory management for higher
- order page allocations.
-
- Say N if you are unsure.
-
config CHECK_STACK
def_bool y
prompt "Detect kernel stack overflow"
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 7e3ce78..a7d68a4 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -55,22 +55,12 @@
ifeq ($(call cc-option-yn,-mkernel-backchain),y)
cflags-$(CONFIG_PACK_STACK) += -mkernel-backchain -D__PACK_STACK
aflags-$(CONFIG_PACK_STACK) += -D__PACK_STACK
-cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-ifdef CONFIG_SMALL_STACK
-STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
-endif
endif
# new style option for packed stacks
ifeq ($(call cc-option-yn,-mpacked-stack),y)
cflags-$(CONFIG_PACK_STACK) += -mpacked-stack -D__PACK_STACK
aflags-$(CONFIG_PACK_STACK) += -D__PACK_STACK
-cflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-aflags-$(CONFIG_SMALL_STACK) += -D__SMALL_STACK
-ifdef CONFIG_SMALL_STACK
-STACK_SIZE := $(shell echo $$(($(STACK_SIZE)/2)) )
-endif
endif
ifeq ($(call cc-option-yn,-mstack-size=8192 -mstack-guard=128),y)
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
index 9fd4a40..bb5dd49 100644
--- a/arch/s390/hypfs/hypfs_dbfs.c
+++ b/arch/s390/hypfs/hypfs_dbfs.c
@@ -105,9 +105,7 @@
int hypfs_dbfs_init(void)
{
dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
- if (IS_ERR(dbfs_dir))
- return PTR_ERR(dbfs_dir);
- return 0;
+ return PTR_RET(dbfs_dir);
}
void hypfs_dbfs_exit(void)
diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 1542293..4d8604e 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -61,8 +61,6 @@
#ifndef CONFIG_64BIT
-#define __BITOPS_ALIGN 3
-#define __BITOPS_WORDSIZE 32
#define __BITOPS_OR "or"
#define __BITOPS_AND "nr"
#define __BITOPS_XOR "xr"
@@ -81,8 +79,6 @@
#else /* CONFIG_64BIT */
-#define __BITOPS_ALIGN 7
-#define __BITOPS_WORDSIZE 64
#define __BITOPS_OR "ogr"
#define __BITOPS_AND "ngr"
#define __BITOPS_XOR "xgr"
@@ -101,8 +97,7 @@
#endif /* CONFIG_64BIT */
-#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE)
-#define __BITOPS_BARRIER() asm volatile("" : : : "memory")
+#define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG)
#ifdef CONFIG_SMP
/*
@@ -114,9 +109,9 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make OR mask */
- mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ mask = 1UL << (nr & (BITS_PER_LONG - 1));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
}
@@ -130,9 +125,9 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make AND mask */
- mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+ mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
}
@@ -146,9 +141,9 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make XOR mask */
- mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ mask = 1UL << (nr & (BITS_PER_LONG - 1));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
}
@@ -163,12 +158,12 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make OR/test mask */
- mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ mask = 1UL << (nr & (BITS_PER_LONG - 1));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR);
- __BITOPS_BARRIER();
+ barrier();
return (old & mask) != 0;
}
@@ -182,12 +177,12 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make AND/test mask */
- mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1)));
+ mask = ~(1UL << (nr & (BITS_PER_LONG - 1)));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND);
- __BITOPS_BARRIER();
+ barrier();
return (old ^ new) != 0;
}
@@ -201,12 +196,12 @@
addr = (unsigned long) ptr;
/* calculate address for CS */
- addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3;
+ addr += (nr ^ (nr & (BITS_PER_LONG - 1))) >> 3;
/* make XOR/test mask */
- mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1));
+ mask = 1UL << (nr & (BITS_PER_LONG - 1));
/* Do the atomic update. */
__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR);
- __BITOPS_BARRIER();
+ barrier();
return (old & mask) != 0;
}
#endif /* CONFIG_SMP */
@@ -218,7 +213,7 @@
{
unsigned long addr;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
asm volatile(
" oc %O0(1,%R0),%1"
: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -229,7 +224,7 @@
{
unsigned long addr;
- addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
*(unsigned char *) addr |= 1 << (nr & 7);
}
@@ -246,7 +241,7 @@
{
unsigned long addr;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
asm volatile(
" nc %O0(1,%R0),%1"
: "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc" );
@@ -257,7 +252,7 @@
{
unsigned long addr;
- addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
*(unsigned char *) addr &= ~(1 << (nr & 7));
}
@@ -273,7 +268,7 @@
{
unsigned long addr;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
asm volatile(
" xc %O0(1,%R0),%1"
: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" );
@@ -284,7 +279,7 @@
{
unsigned long addr;
- addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = ((unsigned long) ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
*(unsigned char *) addr ^= 1 << (nr & 7);
}
@@ -302,7 +297,7 @@
unsigned long addr;
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile(
" oc %O0(1,%R0),%1"
@@ -321,7 +316,7 @@
unsigned long addr;
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile(
" nc %O0(1,%R0),%1"
@@ -340,7 +335,7 @@
unsigned long addr;
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
ch = *(unsigned char *) addr;
asm volatile(
" xc %O0(1,%R0),%1"
@@ -376,7 +371,7 @@
unsigned long addr;
unsigned char ch;
- addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3);
+ addr = (unsigned long) ptr + ((nr ^ (BITS_PER_LONG - 8)) >> 3);
ch = *(volatile unsigned char *) addr;
return (ch >> (nr & 7)) & 1;
}
@@ -384,7 +379,7 @@
static inline int
__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
return (((volatile char *) addr)
- [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0;
+ [(nr^(BITS_PER_LONG-8))>>3] & (1<<(nr&7))) != 0;
}
#define test_bit(nr,addr) \
@@ -693,18 +688,18 @@
if (offset >= size)
return size;
- bit = offset & (__BITOPS_WORDSIZE - 1);
+ bit = offset & (BITS_PER_LONG - 1);
offset -= bit;
size -= offset;
- p = addr + offset / __BITOPS_WORDSIZE;
+ p = addr + offset / BITS_PER_LONG;
if (bit) {
set = __flo_word(0, *p & (~0UL << bit));
if (set >= size)
return size + offset;
- if (set < __BITOPS_WORDSIZE)
+ if (set < BITS_PER_LONG)
return set + offset;
- offset += __BITOPS_WORDSIZE;
- size -= __BITOPS_WORDSIZE;
+ offset += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
p++;
}
return offset + find_first_bit_left(p, size);
@@ -736,22 +731,22 @@
if (offset >= size)
return size;
- bit = offset & (__BITOPS_WORDSIZE - 1);
+ bit = offset & (BITS_PER_LONG - 1);
offset -= bit;
size -= offset;
- p = addr + offset / __BITOPS_WORDSIZE;
+ p = addr + offset / BITS_PER_LONG;
if (bit) {
/*
- * __ffz_word returns __BITOPS_WORDSIZE
+ * __ffz_word returns BITS_PER_LONG
* if no zero bit is present in the word.
*/
set = __ffz_word(bit, *p >> bit);
if (set >= size)
return size + offset;
- if (set < __BITOPS_WORDSIZE)
+ if (set < BITS_PER_LONG)
return set + offset;
- offset += __BITOPS_WORDSIZE;
- size -= __BITOPS_WORDSIZE;
+ offset += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
p++;
}
return offset + find_first_zero_bit(p, size);
@@ -773,22 +768,22 @@
if (offset >= size)
return size;
- bit = offset & (__BITOPS_WORDSIZE - 1);
+ bit = offset & (BITS_PER_LONG - 1);
offset -= bit;
size -= offset;
- p = addr + offset / __BITOPS_WORDSIZE;
+ p = addr + offset / BITS_PER_LONG;
if (bit) {
/*
- * __ffs_word returns __BITOPS_WORDSIZE
+ * __ffs_word returns BITS_PER_LONG
* if no one bit is present in the word.
*/
set = __ffs_word(0, *p & (~0UL << bit));
if (set >= size)
return size + offset;
- if (set < __BITOPS_WORDSIZE)
+ if (set < BITS_PER_LONG)
return set + offset;
- offset += __BITOPS_WORDSIZE;
- size -= __BITOPS_WORDSIZE;
+ offset += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
p++;
}
return offset + find_first_bit(p, size);
@@ -843,22 +838,22 @@
if (offset >= size)
return size;
- bit = offset & (__BITOPS_WORDSIZE - 1);
+ bit = offset & (BITS_PER_LONG - 1);
offset -= bit;
size -= offset;
- p = addr + offset / __BITOPS_WORDSIZE;
+ p = addr + offset / BITS_PER_LONG;
if (bit) {
/*
- * s390 version of ffz returns __BITOPS_WORDSIZE
+ * s390 version of ffz returns BITS_PER_LONG
* if no zero bit is present in the word.
*/
set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit);
if (set >= size)
return size + offset;
- if (set < __BITOPS_WORDSIZE)
+ if (set < BITS_PER_LONG)
return set + offset;
- offset += __BITOPS_WORDSIZE;
- size -= __BITOPS_WORDSIZE;
+ offset += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
p++;
}
return offset + find_first_zero_bit_le(p, size);
@@ -885,22 +880,22 @@
if (offset >= size)
return size;
- bit = offset & (__BITOPS_WORDSIZE - 1);
+ bit = offset & (BITS_PER_LONG - 1);
offset -= bit;
size -= offset;
- p = addr + offset / __BITOPS_WORDSIZE;
+ p = addr + offset / BITS_PER_LONG;
if (bit) {
/*
- * s390 version of ffz returns __BITOPS_WORDSIZE
+ * s390 version of ffz returns BITS_PER_LONG
* if no zero bit is present in the word.
*/
set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit));
if (set >= size)
return size + offset;
- if (set < __BITOPS_WORDSIZE)
+ if (set < BITS_PER_LONG)
return set + offset;
- offset += __BITOPS_WORDSIZE;
- size -= __BITOPS_WORDSIZE;
+ offset += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
p++;
}
return offset + find_first_bit_le(p, size);
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h
index e606161..f201af8 100644
--- a/arch/s390/include/asm/ccwdev.h
+++ b/arch/s390/include/asm/ccwdev.h
@@ -220,7 +220,8 @@
#define to_ccwdrv(n) container_of(n, struct ccw_driver, driver)
extern struct ccw_device *ccw_device_probe_console(void);
-extern int ccw_device_force_console(void);
+extern void ccw_device_wait_idle(struct ccw_device *);
+extern int ccw_device_force_console(struct ccw_device *);
int ccw_device_siosl(struct ccw_device *);
diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h
index ad2b924..ffb8989 100644
--- a/arch/s390/include/asm/cio.h
+++ b/arch/s390/include/asm/cio.h
@@ -296,8 +296,6 @@
return 0;
}
-extern void wait_cons_dev(void);
-
extern void css_schedule_reprobe(void);
extern void reipl_ccw_dev(struct ccw_dev_id *id);
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index f8c6df6..c1e7c64 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -70,6 +70,22 @@
typedef u64 compat_u64;
typedef u32 compat_uptr_t;
+typedef struct {
+ u32 mask;
+ u32 addr;
+} __aligned(8) psw_compat_t;
+
+typedef struct {
+ psw_compat_t psw;
+ u32 gprs[NUM_GPRS];
+ u32 acrs[NUM_ACRS];
+ u32 orig_gpr2;
+} s390_compat_regs;
+
+typedef struct {
+ u32 gprs_high[NUM_GPRS];
+} s390_compat_regs_high;
+
struct compat_timespec {
compat_time_t tv_sec;
s32 tv_nsec;
@@ -124,18 +140,33 @@
};
struct compat_statfs {
- s32 f_type;
- s32 f_bsize;
- s32 f_blocks;
- s32 f_bfree;
- s32 f_bavail;
- s32 f_files;
- s32 f_ffree;
+ u32 f_type;
+ u32 f_bsize;
+ u32 f_blocks;
+ u32 f_bfree;
+ u32 f_bavail;
+ u32 f_files;
+ u32 f_ffree;
compat_fsid_t f_fsid;
- s32 f_namelen;
- s32 f_frsize;
- s32 f_flags;
- s32 f_spare[5];
+ u32 f_namelen;
+ u32 f_frsize;
+ u32 f_flags;
+ u32 f_spare[4];
+};
+
+struct compat_statfs64 {
+ u32 f_type;
+ u32 f_bsize;
+ u64 f_blocks;
+ u64 f_bfree;
+ u64 f_bavail;
+ u64 f_files;
+ u64 f_ffree;
+ compat_fsid_t f_fsid;
+ u32 f_namelen;
+ u32 f_frsize;
+ u32 f_flags;
+ u32 f_spare[4];
};
#define COMPAT_RLIM_OLD_INFINITY 0x7fffffff
@@ -248,8 +279,6 @@
return is_32bit_task();
}
-#endif
-
static inline void __user *arch_compat_alloc_user_space(long len)
{
unsigned long stack;
@@ -260,6 +289,8 @@
return (void __user *) (stack - len);
}
+#endif
+
struct compat_ipc64_perm {
compat_key_t key;
__compat_uid32_t uid;
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index 1bfdf24..78f4f87 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -119,6 +119,8 @@
*/
#include <asm/ptrace.h>
+#include <asm/compat.h>
+#include <asm/syscall.h>
#include <asm/user.h>
typedef s390_fp_regs elf_fpregset_t;
@@ -180,18 +182,31 @@
extern char elf_platform[];
#define ELF_PLATFORM (elf_platform)
-#ifdef CONFIG_64BIT
+#ifndef CONFIG_COMPAT
+#define SET_PERSONALITY(ex) \
+do { \
+ set_personality(PER_LINUX | \
+ (current->personality & (~PER_MASK))); \
+ current_thread_info()->sys_call_table = \
+ (unsigned long) &sys_call_table; \
+} while (0)
+#else /* CONFIG_COMPAT */
#define SET_PERSONALITY(ex) \
do { \
if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_LINUX | \
(current->personality & ~PER_MASK)); \
- if ((ex).e_ident[EI_CLASS] == ELFCLASS32) \
+ if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
set_thread_flag(TIF_31BIT); \
- else \
+ current_thread_info()->sys_call_table = \
+ (unsigned long) &sys_call_table_emu; \
+ } else { \
clear_thread_flag(TIF_31BIT); \
+ current_thread_info()->sys_call_table = \
+ (unsigned long) &sys_call_table; \
+ } \
} while (0)
-#endif /* CONFIG_64BIT */
+#endif /* CONFIG_COMPAT */
#define STACK_RND_MASK 0x7ffUL
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index 27cb321..379d96e 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -50,10 +50,6 @@
#define ioremap_nocache(addr, size) ioremap(addr, size)
#define ioremap_wc ioremap_nocache
-/* TODO: s390 cannot support io_remap_pfn_range... */
-#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
- remap_pfn_range(vma, vaddr, pfn, size, prot)
-
static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
{
return (void __iomem *) offset;
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 05333b7..6c18012 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -140,6 +140,7 @@
struct zpci_dev *zpci_alloc_device(void);
int zpci_create_device(struct zpci_dev *);
int zpci_enable_device(struct zpci_dev *);
+int zpci_disable_device(struct zpci_dev *);
void zpci_stop_device(struct zpci_dev *);
void zpci_free_device(struct zpci_dev *);
int zpci_scan_device(struct zpci_dev *);
diff --git a/arch/s390/include/asm/pci_debug.h b/arch/s390/include/asm/pci_debug.h
index 6bbec42..1ca5d10 100644
--- a/arch/s390/include/asm/pci_debug.h
+++ b/arch/s390/include/asm/pci_debug.h
@@ -7,14 +7,11 @@
extern debug_info_t *pci_debug_err_id;
#ifdef CONFIG_PCI_DEBUG
-#define zpci_dbg(fmt, args...) \
- do { \
- if (pci_debug_msg_id->level >= 2) \
- debug_sprintf_event(pci_debug_msg_id, 2, fmt , ## args);\
- } while (0)
+#define zpci_dbg(imp, fmt, args...) \
+ debug_sprintf_event(pci_debug_msg_id, imp, fmt, ##args)
#else /* !CONFIG_PCI_DEBUG */
-#define zpci_dbg(fmt, args...) do { } while (0)
+#define zpci_dbg(imp, fmt, args...) do { } while (0)
#endif
#define zpci_err(text...) \
diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h
index 1486a98..e6a2bdd 100644
--- a/arch/s390/include/asm/pci_insn.h
+++ b/arch/s390/include/asm/pci_insn.h
@@ -1,10 +1,6 @@
#ifndef _ASM_S390_PCI_INSN_H
#define _ASM_S390_PCI_INSN_H
-#include <linux/delay.h>
-
-#define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */
-
/* Load/Store status codes */
#define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4
#define ZPCI_PCI_ST_FUNC_IN_ERR 8
@@ -82,199 +78,12 @@
u64 reserved7;
} __packed;
-/* Modify PCI Function Controls */
-static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
-{
- u8 cc;
- asm volatile (
- " .insn rxy,0xe300000000d0,%[req],%[fib]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
- : : "cc");
- *status = req >> 24 & 0xff;
- return cc;
-}
-
-static inline int mpcifc_instr(u64 req, struct zpci_fib *fib)
-{
- u8 cc, status;
-
- do {
- cc = __mpcifc(req, fib, &status);
- if (cc == 2)
- msleep(ZPCI_INSN_BUSY_DELAY);
- } while (cc == 2);
-
- if (cc)
- printk_once(KERN_ERR "%s: error cc: %d status: %d\n",
- __func__, cc, status);
- return (cc) ? -EIO : 0;
-}
-
-/* Refresh PCI Translations */
-static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
-{
- register u64 __addr asm("2") = addr;
- register u64 __range asm("3") = range;
- u8 cc;
-
- asm volatile (
- " .insn rre,0xb9d30000,%[fn],%[addr]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [fn] "+d" (fn)
- : [addr] "d" (__addr), "d" (__range)
- : "cc");
- *status = fn >> 24 & 0xff;
- return cc;
-}
-
-static inline int rpcit_instr(u64 fn, u64 addr, u64 range)
-{
- u8 cc, status;
-
- do {
- cc = __rpcit(fn, addr, range, &status);
- if (cc == 2)
- udelay(ZPCI_INSN_BUSY_DELAY);
- } while (cc == 2);
-
- if (cc)
- printk_once(KERN_ERR "%s: error cc: %d status: %d dma_addr: %Lx size: %Lx\n",
- __func__, cc, status, addr, range);
- return (cc) ? -EIO : 0;
-}
-
-/* Store PCI function controls */
-static inline u8 __stpcifc(u32 handle, u8 space, struct zpci_fib *fib, u8 *status)
-{
- u64 fn = (u64) handle << 32 | space << 16;
- u8 cc;
-
- asm volatile (
- " .insn rxy,0xe300000000d4,%[fn],%[fib]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [fn] "+d" (fn), [fib] "=m" (*fib)
- : : "cc");
- *status = fn >> 24 & 0xff;
- return cc;
-}
-
-/* Set Interruption Controls */
-static inline void sic_instr(u16 ctl, char *unused, u8 isc)
-{
- asm volatile (
- " .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
- : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
-}
-
-/* PCI Load */
-static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
-{
- register u64 __req asm("2") = req;
- register u64 __offset asm("3") = offset;
- u64 __data;
- u8 cc;
-
- asm volatile (
- " .insn rre,0xb9d20000,%[data],%[req]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req)
- : "d" (__offset)
- : "cc");
- *status = __req >> 24 & 0xff;
- *data = __data;
- return cc;
-}
-
-static inline int pcilg_instr(u64 *data, u64 req, u64 offset)
-{
- u8 cc, status;
-
- do {
- cc = __pcilg(data, req, offset, &status);
- if (cc == 2)
- udelay(ZPCI_INSN_BUSY_DELAY);
- } while (cc == 2);
-
- if (cc) {
- printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
- __func__, cc, status, req, offset);
- /* TODO: on IO errors set data to 0xff...
- * here or in users of pcilg (le conversion)?
- */
- }
- return (cc) ? -EIO : 0;
-}
-
-/* PCI Store */
-static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status)
-{
- register u64 __req asm("2") = req;
- register u64 __offset asm("3") = offset;
- u8 cc;
-
- asm volatile (
- " .insn rre,0xb9d00000,%[data],%[req]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [req] "+d" (__req)
- : "d" (__offset), [data] "d" (data)
- : "cc");
- *status = __req >> 24 & 0xff;
- return cc;
-}
-
-static inline int pcistg_instr(u64 data, u64 req, u64 offset)
-{
- u8 cc, status;
-
- do {
- cc = __pcistg(data, req, offset, &status);
- if (cc == 2)
- udelay(ZPCI_INSN_BUSY_DELAY);
- } while (cc == 2);
-
- if (cc)
- printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
- __func__, cc, status, req, offset);
- return (cc) ? -EIO : 0;
-}
-
-/* PCI Store Block */
-static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
-{
- u8 cc;
-
- asm volatile (
- " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
- " ipm %[cc]\n"
- " srl %[cc],28\n"
- : [cc] "=d" (cc), [req] "+d" (req)
- : [offset] "d" (offset), [data] "Q" (*data)
- : "cc");
- *status = req >> 24 & 0xff;
- return cc;
-}
-
-static inline int pcistb_instr(const u64 *data, u64 req, u64 offset)
-{
- u8 cc, status;
-
- do {
- cc = __pcistb(data, req, offset, &status);
- if (cc == 2)
- udelay(ZPCI_INSN_BUSY_DELAY);
- } while (cc == 2);
-
- if (cc)
- printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
- __func__, cc, status, req, offset);
- return (cc) ? -EIO : 0;
-}
+int s390pci_mod_fc(u64 req, struct zpci_fib *fib);
+int s390pci_refresh_trans(u64 fn, u64 addr, u64 range);
+int s390pci_load(u64 *data, u64 req, u64 offset);
+int s390pci_store(u64 data, u64 req, u64 offset);
+int s390pci_store_block(const u64 *data, u64 req, u64 offset);
+void set_irq_ctrl(u16 ctl, char *unused, u8 isc);
#endif
diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h
index 5fd81f3..83a9caa 100644
--- a/arch/s390/include/asm/pci_io.h
+++ b/arch/s390/include/asm/pci_io.h
@@ -36,7 +36,7 @@
u64 data; \
int rc; \
\
- rc = pcilg_instr(&data, req, ZPCI_OFFSET(addr)); \
+ rc = s390pci_load(&data, req, ZPCI_OFFSET(addr)); \
if (rc) \
data = -1ULL; \
return (RETTYPE) data; \
@@ -50,7 +50,7 @@
u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH); \
u64 data = (VALTYPE) val; \
\
- pcistg_instr(data, req, ZPCI_OFFSET(addr)); \
+ s390pci_store(data, req, ZPCI_OFFSET(addr)); \
}
zpci_read(8, u64)
@@ -83,15 +83,18 @@
val = 0; /* let FW report error */
break;
}
- return pcistg_instr(val, req, offset);
+ return s390pci_store(val, req, offset);
}
static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len)
{
u64 data;
- u8 cc;
+ int cc;
- cc = pcilg_instr(&data, req, offset);
+ cc = s390pci_load(&data, req, offset);
+ if (cc)
+ goto out;
+
switch (len) {
case 1:
*((u8 *) dst) = (u8) data;
@@ -106,12 +109,13 @@
*((u64 *) dst) = (u64) data;
break;
}
+out:
return cc;
}
static inline int zpci_write_block(u64 req, const u64 *data, u64 offset)
{
- return pcistb_instr(data, req, offset);
+ return s390pci_store_block(data, req, offset);
}
static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max)
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 4a54431..4a64c0e 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -57,6 +57,10 @@
(((unsigned long)(vaddr)) &zero_page_mask))))
#define __HAVE_COLOR_ZERO_PAGE
+/* TODO: s390 cannot support io_remap_pfn_range... */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \
+ remap_pfn_range(vma, vaddr, pfn, size, prot)
+
#endif /* !__ASSEMBLY__ */
/*
@@ -760,6 +764,8 @@
int gmap_map_segment(struct gmap *gmap, unsigned long from,
unsigned long to, unsigned long length);
int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len);
+unsigned long __gmap_translate(unsigned long address, struct gmap *);
+unsigned long gmap_translate(unsigned long address, struct gmap *);
unsigned long __gmap_fault(unsigned long address, struct gmap *);
unsigned long gmap_fault(unsigned long address, struct gmap *);
void gmap_discard(unsigned long from, unsigned long to, struct gmap *);
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index 94e749c..6b49987 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -161,7 +161,8 @@
extern void show_code(struct pt_regs *regs);
extern void print_fn_code(unsigned char *code, unsigned long len);
-extern int insn_to_mnemonic(unsigned char *instruction, char buf[8]);
+extern int insn_to_mnemonic(unsigned char *instruction, char *buf,
+ unsigned int len);
unsigned long get_wchan(struct task_struct *p);
#define task_pt_regs(tsk) ((struct pt_regs *) \
diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h
index 3ee5da3..559512a 100644
--- a/arch/s390/include/asm/ptrace.h
+++ b/arch/s390/include/asm/ptrace.h
@@ -9,9 +9,7 @@
#include <uapi/asm/ptrace.h>
#ifndef __ASSEMBLY__
-#ifndef __s390x__
-#else /* __s390x__ */
-#endif /* __s390x__ */
+
extern long psw_kernel_bits;
extern long psw_user_bits;
@@ -77,8 +75,6 @@
#define PER_CONTROL_SUSPENSION 0x00400000UL
#define PER_CONTROL_ALTERATION 0x00200000UL
-#ifdef __s390x__
-#endif /* __s390x__ */
/*
* These are defined as per linux/ptrace.h, which see.
*/
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index fe7b997..cd29d2f 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -23,6 +23,7 @@
* type here is what we want [need] for both 32 bit and 64 bit systems.
*/
extern const unsigned int sys_call_table[];
+extern const unsigned int sys_call_table_emu[];
static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 9e2cfe0..eb5f64d 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -14,13 +14,8 @@
#define THREAD_ORDER 1
#define ASYNC_ORDER 1
#else /* CONFIG_64BIT */
-#ifndef __SMALL_STACK
#define THREAD_ORDER 2
#define ASYNC_ORDER 2
-#else
-#define THREAD_ORDER 1
-#define ASYNC_ORDER 1
-#endif
#endif /* CONFIG_64BIT */
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
@@ -41,6 +36,7 @@
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
+ unsigned long sys_call_table; /* System call table address */
unsigned int cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h
index a5ca214..3aa9f1e 100644
--- a/arch/s390/include/uapi/asm/ptrace.h
+++ b/arch/s390/include/uapi/asm/ptrace.h
@@ -215,12 +215,6 @@
unsigned long addr;
} __attribute__ ((aligned(8))) psw_t;
-typedef struct
-{
- __u32 mask;
- __u32 addr;
-} __attribute__ ((aligned(8))) psw_compat_t;
-
#ifndef __s390x__
#define PSW_MASK_PER 0x40000000UL
@@ -295,20 +289,6 @@
unsigned long orig_gpr2;
} s390_regs;
-typedef struct
-{
- psw_compat_t psw;
- __u32 gprs[NUM_GPRS];
- __u32 acrs[NUM_ACRS];
- __u32 orig_gpr2;
-} s390_compat_regs;
-
-typedef struct
-{
- __u32 gprs_high[NUM_GPRS];
-} s390_compat_regs_high;
-
-
/*
* Now for the user space program event recording (trace) definitions.
* The following structures are used only for the ptrace interface, don't
diff --git a/arch/s390/include/uapi/asm/statfs.h b/arch/s390/include/uapi/asm/statfs.h
index 5acca0a..a61d538 100644
--- a/arch/s390/include/uapi/asm/statfs.h
+++ b/arch/s390/include/uapi/asm/statfs.h
@@ -7,9 +7,6 @@
#ifndef _S390_STATFS_H
#define _S390_STATFS_H
-#ifndef __s390x__
-#include <asm-generic/statfs.h>
-#else
/*
* We can't use <asm-generic/statfs.h> because in 64-bit mode
* we mix ints of different sizes in our struct statfs.
@@ -21,49 +18,33 @@
#endif
struct statfs {
- int f_type;
- int f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
+ unsigned int f_type;
+ unsigned int f_bsize;
+ unsigned long f_blocks;
+ unsigned long f_bfree;
+ unsigned long f_bavail;
+ unsigned long f_files;
+ unsigned long f_ffree;
__kernel_fsid_t f_fsid;
- int f_namelen;
- int f_frsize;
- int f_flags;
- int f_spare[4];
+ unsigned int f_namelen;
+ unsigned int f_frsize;
+ unsigned int f_flags;
+ unsigned int f_spare[4];
};
struct statfs64 {
- int f_type;
- int f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
+ unsigned int f_type;
+ unsigned int f_bsize;
+ unsigned long f_blocks;
+ unsigned long f_bfree;
+ unsigned long f_bavail;
+ unsigned long f_files;
+ unsigned long f_ffree;
__kernel_fsid_t f_fsid;
- int f_namelen;
- int f_frsize;
- int f_flags;
- int f_spare[4];
+ unsigned int f_namelen;
+ unsigned int f_frsize;
+ unsigned int f_flags;
+ unsigned int f_spare[4];
};
-struct compat_statfs64 {
- __u32 f_type;
- __u32 f_bsize;
- __u64 f_blocks;
- __u64 f_bfree;
- __u64 f_bavail;
- __u64 f_files;
- __u64 f_ffree;
- __kernel_fsid_t f_fsid;
- __u32 f_namelen;
- __u32 f_frsize;
- __u32 f_flags;
- __u32 f_spare[4];
-};
-
-#endif /* __s390x__ */
#endif
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 2ac311e..1386fca 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -14,16 +14,25 @@
CFLAGS_smp.o := -Wno-nonnull
#
+# Disable tailcall optimizations for stack / callchain walking functions
+# since this might generate broken code when accessing register 15 and
+# passing its content to other functions.
+#
+CFLAGS_stacktrace.o += -fno-optimize-sibling-calls
+CFLAGS_dumpstack.o += -fno-optimize-sibling-calls
+
+#
# Pass UTS_MACHINE for user_regset definition
#
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w
-obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \
- processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \
- debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \
- sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o
+obj-y += processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
+obj-y += debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o
+obj-y += sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o pgm_check.o
+obj-y += dumpstack.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index fface87..7a82f9f 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -35,6 +35,7 @@
DEFINE(__TI_task, offsetof(struct thread_info, task));
DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain));
DEFINE(__TI_flags, offsetof(struct thread_info, flags));
+ DEFINE(__TI_sysc_table, offsetof(struct thread_info, sys_call_table));
DEFINE(__TI_cpu, offsetof(struct thread_info, cpu));
DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count));
DEFINE(__TI_user_timer, offsetof(struct thread_info, user_timer));
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 6de049f..c439ac9 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -362,6 +362,7 @@
/* set extra registers only for synchronous signals */
regs->gprs[4] = regs->int_code & 127;
regs->gprs[5] = regs->int_parm_long;
+ regs->gprs[6] = task_thread_info(current)->last_break;
}
/* Place signal number on stack to allow backtrace from handler. */
@@ -421,6 +422,7 @@
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (__force __u64) &frame->info;
regs->gprs[4] = (__force __u64) &frame->uc;
+ regs->gprs[5] = task_thread_info(current)->last_break;
return 0;
give_sigsegv:
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index 3ad5e95..7f4a4a8 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -1696,14 +1696,15 @@
* insn_to_mnemonic - decode an s390 instruction
* @instruction: instruction to decode
* @buf: buffer to fill with mnemonic
+ * @len: length of buffer
*
* Decode the instruction at @instruction and store the corresponding
- * mnemonic into @buf.
+ * mnemonic into @buf of length @len.
* @buf is left unchanged if the instruction could not be decoded.
* Returns:
* %0 on success, %-ENOENT if the instruction was not found.
*/
-int insn_to_mnemonic(unsigned char *instruction, char buf[8])
+int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len)
{
struct insn *insn;
@@ -1711,10 +1712,10 @@
if (!insn)
return -ENOENT;
if (insn->name[0] == '\0')
- snprintf(buf, 8, "%s",
+ snprintf(buf, len, "%s",
long_insn_name[(int) insn->name[1]]);
else
- snprintf(buf, 8, "%.5s", insn->name);
+ snprintf(buf, len, "%.5s", insn->name);
return 0;
}
EXPORT_SYMBOL_GPL(insn_to_mnemonic);
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
new file mode 100644
index 0000000..03dce39
--- /dev/null
+++ b/arch/s390/kernel/dumpstack.c
@@ -0,0 +1,236 @@
+/*
+ * Stack dumping functions
+ *
+ * Copyright IBM Corp. 1999, 2013
+ */
+
+#include <linux/kallsyms.h>
+#include <linux/hardirq.h>
+#include <linux/kprobes.h>
+#include <linux/utsname.h>
+#include <linux/export.h>
+#include <linux/kdebug.h>
+#include <linux/ptrace.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/debug.h>
+#include <asm/ipl.h>
+
+#ifndef CONFIG_64BIT
+#define LONG "%08lx "
+#define FOURLONG "%08lx %08lx %08lx %08lx\n"
+static int kstack_depth_to_print = 12;
+#else /* CONFIG_64BIT */
+#define LONG "%016lx "
+#define FOURLONG "%016lx %016lx %016lx %016lx\n"
+static int kstack_depth_to_print = 20;
+#endif /* CONFIG_64BIT */
+
+/*
+ * For show_trace we have tree different stack to consider:
+ * - the panic stack which is used if the kernel stack has overflown
+ * - the asynchronous interrupt stack (cpu related)
+ * - the synchronous kernel stack (process related)
+ * The stack trace can start at any of the three stack and can potentially
+ * touch all of them. The order is: panic stack, async stack, sync stack.
+ */
+static unsigned long
+__show_trace(unsigned long sp, unsigned long low, unsigned long high)
+{
+ struct stack_frame *sf;
+ struct pt_regs *regs;
+
+ while (1) {
+ sp = sp & PSW_ADDR_INSN;
+ if (sp < low || sp > high - sizeof(*sf))
+ return sp;
+ sf = (struct stack_frame *) sp;
+ printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+ print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
+ /* Follow the backchain. */
+ while (1) {
+ low = sp;
+ sp = sf->back_chain & PSW_ADDR_INSN;
+ if (!sp)
+ break;
+ if (sp <= low || sp > high - sizeof(*sf))
+ return sp;
+ sf = (struct stack_frame *) sp;
+ printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
+ print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
+ }
+ /* Zero backchain detected, check for interrupt frame. */
+ sp = (unsigned long) (sf + 1);
+ if (sp <= low || sp > high - sizeof(*regs))
+ return sp;
+ regs = (struct pt_regs *) sp;
+ printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
+ print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
+ low = sp;
+ sp = regs->gprs[15];
+ }
+}
+
+static void show_trace(struct task_struct *task, unsigned long *stack)
+{
+ register unsigned long __r15 asm ("15");
+ unsigned long sp;
+
+ sp = (unsigned long) stack;
+ if (!sp)
+ sp = task ? task->thread.ksp : __r15;
+ printk("Call Trace:\n");
+#ifdef CONFIG_CHECK_STACK
+ sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
+ S390_lowcore.panic_stack);
+#endif
+ sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
+ S390_lowcore.async_stack);
+ if (task)
+ __show_trace(sp, (unsigned long) task_stack_page(task),
+ (unsigned long) task_stack_page(task) + THREAD_SIZE);
+ else
+ __show_trace(sp, S390_lowcore.thread_info,
+ S390_lowcore.thread_info + THREAD_SIZE);
+ if (!task)
+ task = current;
+ debug_show_held_locks(task);
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ register unsigned long *__r15 asm ("15");
+ unsigned long *stack;
+ int i;
+
+ if (!sp)
+ stack = task ? (unsigned long *) task->thread.ksp : __r15;
+ else
+ stack = sp;
+
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
+ break;
+ if ((i * sizeof(long) % 32) == 0)
+ printk("%s ", i == 0 ? "" : "\n");
+ printk(LONG, *stack++);
+ }
+ printk("\n");
+ show_trace(task, sp);
+}
+
+static void show_last_breaking_event(struct pt_regs *regs)
+{
+#ifdef CONFIG_64BIT
+ printk("Last Breaking-Event-Address:\n");
+ printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
+ print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
+#endif
+}
+
+/*
+ * The architecture-independent dump_stack generator
+ */
+void dump_stack(void)
+{
+ printk("CPU: %d %s %s %.*s\n",
+ task_thread_info(current)->cpu, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+ printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+ current->comm, current->pid, current,
+ (void *) current->thread.ksp);
+ show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
+{
+ return (regs->psw.mask & bits) / ((~bits + 1) & bits);
+}
+
+void show_registers(struct pt_regs *regs)
+{
+ char *mode;
+
+ mode = user_mode(regs) ? "User" : "Krnl";
+ printk("%s PSW : %p %p",
+ mode, (void *) regs->psw.mask,
+ (void *) regs->psw.addr);
+ print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
+ printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
+ "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
+ mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
+ mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
+ mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
+ mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
+ mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
+#ifdef CONFIG_64BIT
+ printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
+#endif
+ printk("\n%s GPRS: " FOURLONG, mode,
+ regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
+ printk(" " FOURLONG,
+ regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
+ printk(" " FOURLONG,
+ regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
+ printk(" " FOURLONG,
+ regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
+ show_code(regs);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ printk("CPU: %d %s %s %.*s\n",
+ task_thread_info(current)->cpu, print_tainted(),
+ init_utsname()->release,
+ (int)strcspn(init_utsname()->version, " "),
+ init_utsname()->version);
+ printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
+ current->comm, current->pid, current,
+ (void *) current->thread.ksp);
+ show_registers(regs);
+ /* Show stack backtrace if pt_regs is from kernel mode */
+ if (!user_mode(regs))
+ show_trace(NULL, (unsigned long *) regs->gprs[15]);
+ show_last_breaking_event(regs);
+}
+
+static DEFINE_SPINLOCK(die_lock);
+
+void die(struct pt_regs *regs, const char *str)
+{
+ static int die_counter;
+
+ oops_enter();
+ lgr_info_log();
+ debug_stop_all();
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+ printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
+#ifdef CONFIG_PREEMPT
+ printk("PREEMPT ");
+#endif
+#ifdef CONFIG_SMP
+ printk("SMP ");
+#endif
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ printk("DEBUG_PAGEALLOC");
+#endif
+ printk("\n");
+ notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
+ print_modules();
+ show_regs(regs);
+ bust_spinlocks(0);
+ add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
+ spin_unlock_irq(&die_lock);
+ if (in_interrupt())
+ panic("Fatal exception in interrupt");
+ if (panic_on_oops)
+ panic("Fatal exception: panic_on_oops");
+ oops_exit();
+ do_exit(SIGSEGV);
+}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 94feff7..4d5e6f8 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -45,6 +45,7 @@
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
+STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
#define BASED(name) name-system_call(%r13)
@@ -97,10 +98,10 @@
sra %r14,\shift
jnz 1f
CHECK_STACK 1<<\shift,\savearea
+ ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 2f
1: l %r15,\stack # load target stack
-2: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
- la %r11,STACK_FRAME_OVERHEAD(%r15)
+2: la %r11,STACK_FRAME_OVERHEAD(%r15)
.endm
.macro ADD64 high,low,timer
@@ -150,7 +151,7 @@
l %r4,__THREAD_info(%r2) # get thread_info of prev
l %r5,__THREAD_info(%r3) # get thread_info of next
lr %r15,%r5
- ahi %r15,STACK_SIZE # end of kernel stack of next
+ ahi %r15,STACK_INIT # end of kernel stack of next
st %r3,__LC_CURRENT # store task struct of next
st %r5,__LC_THREAD_INFO # store thread info of next
st %r15,__LC_KERNEL_STACK # store end of kernel stack
@@ -178,7 +179,6 @@
l %r13,__LC_SVC_NEW_PSW+4
sysc_per:
l %r15,__LC_KERNEL_STACK
- ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
sysc_vtime:
UPDATE_VTIME %r8,%r9,__LC_SYNC_ENTER_TIMER
@@ -188,6 +188,7 @@
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc:
oi __TI_flags+3(%r12),_TIF_SYSCALL
+ l %r10,__TI_sysc_table(%r12) # 31 bit system call table
lh %r8,__PT_INT_CODE+2(%r11)
sla %r8,2 # shift and test for svc0
jnz sysc_nr_ok
@@ -198,7 +199,6 @@
lr %r8,%r1
sla %r8,2
sysc_nr_ok:
- l %r10,BASED(.Lsys_call_table) # 31 bit system call table
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
st %r2,__PT_ORIG_GPR2(%r11)
st %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -359,11 +359,11 @@
tm __LC_PGM_ILC+3,0x80 # check for per exception
jnz pgm_svcper # -> single stepped svc
0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
+ ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 2f
1: UPDATE_VTIME %r14,%r15,__LC_SYNC_ENTER_TIMER
l %r15,__LC_KERNEL_STACK
-2: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
- la %r11,STACK_FRAME_OVERHEAD(%r15)
+2: la %r11,STACK_FRAME_OVERHEAD(%r15)
stm %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(32,%r11),__LC_SAVE_AREA_SYNC
stm %r8,%r9,__PT_PSW(%r11)
@@ -485,7 +485,6 @@
#
io_work_user:
l %r1,__LC_KERNEL_STACK
- ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
la %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -646,7 +645,6 @@
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jno mcck_return
l %r1,__LC_KERNEL_STACK # switch to kernel stack
- ahi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1)
la %r11,STACK_FRAME_OVERHEAD(%r15)
@@ -674,6 +672,7 @@
sra %r14,PAGE_SHIFT
jz 0f
l %r15,__LC_PANIC_STACK
+ j mcck_skip
0: ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j mcck_skip
@@ -714,12 +713,10 @@
*/
stack_overflow:
l %r15,__LC_PANIC_STACK # change to panic stack
- ahi %r15,-__PT_SIZE # create pt_regs
- stm %r0,%r7,__PT_R0(%r15)
- stm %r8,%r9,__PT_PSW(%r15)
+ la %r11,STACK_FRAME_OVERHEAD(%r15)
+ stm %r0,%r7,__PT_R0(%r11)
+ stm %r8,%r9,__PT_PSW(%r11)
mvc __PT_R8(32,%r11),0(%r14)
- lr %r15,%r11
- ahi %r15,-STACK_FRAME_OVERHEAD
l %r1,BASED(1f)
xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
lr %r2,%r11 # pass pointer to pt_regs
@@ -799,15 +796,14 @@
mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
# set up saved register 11
l %r15,__LC_KERNEL_STACK
- ahi %r15,-__PT_SIZE
- st %r15,12(%r11) # r11 pt_regs pointer
+ la %r9,STACK_FRAME_OVERHEAD(%r15)
+ st %r9,12(%r11) # r11 pt_regs pointer
# fill pt_regs
- mvc __PT_R8(32,%r15),__LC_SAVE_AREA_SYNC
- stm %r0,%r7,__PT_R0(%r15)
- mvc __PT_PSW(8,%r15),__LC_SVC_OLD_PSW
- mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
+ mvc __PT_R8(32,%r9),__LC_SAVE_AREA_SYNC
+ stm %r0,%r7,__PT_R0(%r9)
+ mvc __PT_PSW(8,%r9),__LC_SVC_OLD_PSW
+ mvc __PT_INT_CODE(4,%r9),__LC_SVC_ILC
# setup saved register 15
- ahi %r15,-STACK_FRAME_OVERHEAD
st %r15,28(%r11) # r15 stack pointer
# set new psw address and exit
l %r9,BASED(cleanup_table+4) # sysc_do_svc + 0x80000000
@@ -910,7 +906,6 @@
.Ltrace_enter: .long do_syscall_trace_enter
.Ltrace_exit: .long do_syscall_trace_exit
.Lschedule_tail: .long schedule_tail
-.Lsys_call_table: .long sys_call_table
.Lsysc_per: .long sysc_per + 0x80000000
#ifdef CONFIG_TRACE_IRQFLAGS
.Lhardirqs_on: .long trace_hardirqs_on_caller
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index c3a736a..aa0ab02 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -7,6 +7,7 @@
#include <asm/cputime.h>
extern void *restart_stack;
+extern unsigned long suspend_zero_pages;
void system_call(void);
void pgm_check_handler(void);
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 2e6d60c..4c17eec 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -39,6 +39,7 @@
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
+STACK_INIT = STACK_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE
_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
_TIF_MCCK_PENDING | _TIF_PER_TRAP )
@@ -124,10 +125,10 @@
srag %r14,%r14,\shift
jnz 1f
CHECK_STACK 1<<\shift,\savearea
+ aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 2f
1: lg %r15,\stack # load target stack
-2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
- la %r11,STACK_FRAME_OVERHEAD(%r15)
+2: la %r11,STACK_FRAME_OVERHEAD(%r15)
.endm
.macro UPDATE_VTIME scratch,enter_timer
@@ -177,7 +178,7 @@
lg %r4,__THREAD_info(%r2) # get thread_info of prev
lg %r5,__THREAD_info(%r3) # get thread_info of next
lgr %r15,%r5
- aghi %r15,STACK_SIZE # end of kernel stack of next
+ aghi %r15,STACK_INIT # end of kernel stack of next
stg %r3,__LC_CURRENT # store task struct of next
stg %r5,__LC_THREAD_INFO # store thread info of next
stg %r15,__LC_KERNEL_STACK # store end of kernel stack
@@ -203,10 +204,8 @@
stmg %r8,%r15,__LC_SAVE_AREA_SYNC
lg %r10,__LC_LAST_BREAK
lg %r12,__LC_THREAD_INFO
- larl %r13,system_call
sysc_per:
lg %r15,__LC_KERNEL_STACK
- aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
la %r11,STACK_FRAME_OVERHEAD(%r15) # pointer to pt_regs
sysc_vtime:
UPDATE_VTIME %r13,__LC_SYNC_ENTER_TIMER
@@ -217,6 +216,7 @@
mvc __PT_INT_CODE(4,%r11),__LC_SVC_ILC
sysc_do_svc:
oi __TI_flags+7(%r12),_TIF_SYSCALL
+ lg %r10,__TI_sysc_table(%r12) # address of system call table
llgh %r8,__PT_INT_CODE+2(%r11)
slag %r8,%r8,2 # shift and test for svc 0
jnz sysc_nr_ok
@@ -227,13 +227,6 @@
sth %r1,__PT_INT_CODE+2(%r11)
slag %r8,%r1,2
sysc_nr_ok:
- larl %r10,sys_call_table # 64 bit system call table
-#ifdef CONFIG_COMPAT
- tm __TI_flags+5(%r12),(_TIF_31BIT>>16)
- jno sysc_noemu
- larl %r10,sys_call_table_emu # 31 bit system call table
-sysc_noemu:
-#endif
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
stg %r2,__PT_ORIG_GPR2(%r11)
stg %r7,STACK_FRAME_OVERHEAD(%r15)
@@ -389,6 +382,7 @@
tm __LC_PGM_ILC+3,0x80 # check for per exception
jnz pgm_svcper # -> single stepped svc
0: CHECK_STACK STACK_SIZE,__LC_SAVE_AREA_SYNC
+ aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
j 2f
1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER
LAST_BREAK %r14
@@ -398,8 +392,7 @@
tm __LC_PGM_ILC+2,0x02 # check for transaction abort
jz 2f
mvc __THREAD_trap_tdb(256,%r14),0(%r13)
-2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
- la %r11,STACK_FRAME_OVERHEAD(%r15)
+2: la %r11,STACK_FRAME_OVERHEAD(%r15)
stmg %r0,%r7,__PT_R0(%r11)
mvc __PT_R8(64,%r11),__LC_SAVE_AREA_SYNC
stmg %r8,%r9,__PT_PSW(%r11)
@@ -526,7 +519,6 @@
#
io_work_user:
lg %r1,__LC_KERNEL_STACK
- aghi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
la %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -688,7 +680,6 @@
tm __PT_PSW+1(%r11),0x01 # returning to user ?
jno mcck_return
lg %r1,__LC_KERNEL_STACK # switch to kernel stack
- aghi %r1,-(STACK_FRAME_OVERHEAD + __PT_SIZE)
mvc STACK_FRAME_OVERHEAD(__PT_SIZE,%r1),0(%r11)
xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1)
la %r11,STACK_FRAME_OVERHEAD(%r1)
@@ -755,14 +746,12 @@
* Setup a pt_regs so that show_trace can provide a good call trace.
*/
stack_overflow:
- lg %r11,__LC_PANIC_STACK # change to panic stack
- aghi %r11,-__PT_SIZE # create pt_regs
+ lg %r15,__LC_PANIC_STACK # change to panic stack
+ la %r11,STACK_FRAME_OVERHEAD(%r15)
stmg %r0,%r7,__PT_R0(%r11)
stmg %r8,%r9,__PT_PSW(%r11)
mvc __PT_R8(64,%r11),0(%r14)
stg %r10,__PT_ORIG_GPR2(%r11) # store last break to orig_gpr2
- lgr %r15,%r11
- aghi %r15,-STACK_FRAME_OVERHEAD
xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
lgr %r2,%r11 # pass pointer to pt_regs
jg kernel_stack_overflow
@@ -846,15 +835,14 @@
mvc __TI_last_break(8,%r12),16(%r11)
0: # set up saved register r11
lg %r15,__LC_KERNEL_STACK
- aghi %r15,-__PT_SIZE
- stg %r15,24(%r11) # r11 pt_regs pointer
+ la %r9,STACK_FRAME_OVERHEAD(%r15)
+ stg %r9,24(%r11) # r11 pt_regs pointer
# fill pt_regs
- mvc __PT_R8(64,%r15),__LC_SAVE_AREA_SYNC
- stmg %r0,%r7,__PT_R0(%r15)
- mvc __PT_PSW(16,%r15),__LC_SVC_OLD_PSW
- mvc __PT_INT_CODE(4,%r15),__LC_SVC_ILC
+ mvc __PT_R8(64,%r9),__LC_SAVE_AREA_SYNC
+ stmg %r0,%r7,__PT_R0(%r9)
+ mvc __PT_PSW(16,%r9),__LC_SVC_OLD_PSW
+ mvc __PT_INT_CODE(4,%r9),__LC_SVC_ILC
# setup saved register r15
- aghi %r15,-STACK_FRAME_OVERHEAD
stg %r15,56(%r11) # r15 stack pointer
# set new psw address and exit
larl %r9,sysc_do_svc
@@ -1011,6 +999,7 @@
#ifdef CONFIG_COMPAT
#define SYSCALL(esa,esame,emu) .long emu
+ .globl sys_call_table_emu
sys_call_table_emu:
#include "syscalls.S"
#undef SYSCALL
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
index b3de277..ac21781 100644
--- a/arch/s390/kernel/machine_kexec.c
+++ b/arch/s390/kernel/machine_kexec.c
@@ -13,6 +13,7 @@
#include <linux/reboot.h>
#include <linux/ftrace.h>
#include <linux/debug_locks.h>
+#include <linux/suspend.h>
#include <asm/cio.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
@@ -67,6 +68,35 @@
memcpy((void *) SAVE_AREA_BASE, (void *) sa, sizeof(struct save_area));
}
+/*
+ * PM notifier callback for kdump
+ */
+static int machine_kdump_pm_cb(struct notifier_block *nb, unsigned long action,
+ void *ptr)
+{
+ switch (action) {
+ case PM_SUSPEND_PREPARE:
+ case PM_HIBERNATION_PREPARE:
+ if (crashk_res.start)
+ crash_map_reserved_pages();
+ break;
+ case PM_POST_SUSPEND:
+ case PM_POST_HIBERNATION:
+ if (crashk_res.start)
+ crash_unmap_reserved_pages();
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
+static int __init machine_kdump_pm_init(void)
+{
+ pm_notifier(machine_kdump_pm_cb, 0);
+ return 0;
+}
+arch_initcall(machine_kdump_pm_init);
#endif
/*
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2926885..0f419c5 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -377,11 +377,14 @@
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->clock_comparator = -1ULL;
- lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
+ lc->kernel_stack = ((unsigned long) &init_thread_union)
+ + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
lc->async_stack = (unsigned long)
- __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
+ __alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0)
+ + ASYNC_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
lc->panic_stack = (unsigned long)
- __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
+ __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0)
+ + PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
lc->thread_info = (unsigned long) &init_thread_union;
lc->machine_flags = S390_lowcore.machine_flags;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 549c9d1..8bde89e 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -181,8 +181,10 @@
lc = pcpu->lowcore;
memcpy(lc, &S390_lowcore, 512);
memset((char *) lc + 512, 0, sizeof(*lc) - 512);
- lc->async_stack = pcpu->async_stack + ASYNC_SIZE;
- lc->panic_stack = pcpu->panic_stack + PAGE_SIZE;
+ lc->async_stack = pcpu->async_stack + ASYNC_SIZE
+ - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
+ lc->panic_stack = pcpu->panic_stack + PAGE_SIZE
+ - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
lc->cpu_nr = cpu;
#ifndef CONFIG_64BIT
if (MACHINE_HAS_IEEE) {
@@ -253,7 +255,8 @@
struct _lowcore *lc = pcpu->lowcore;
struct thread_info *ti = task_thread_info(tsk);
- lc->kernel_stack = (unsigned long) task_stack_page(tsk) + THREAD_SIZE;
+ lc->kernel_stack = (unsigned long) task_stack_page(tsk)
+ + THREAD_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
lc->thread_info = (unsigned long) task_thread_info(tsk);
lc->current_task = (unsigned long) tsk;
lc->user_timer = ti->user_timer;
@@ -810,8 +813,10 @@
pcpu->state = CPU_STATE_CONFIGURED;
pcpu->address = boot_cpu_address;
pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
- pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE;
- pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE;
+ pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE
+ + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
+ pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE
+ + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
S390_lowcore.percpu_offset = __per_cpu_offset[0];
smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
set_cpu_present(0, true);
diff --git a/arch/s390/kernel/suspend.c b/arch/s390/kernel/suspend.c
index aa1494d..c479d2f 100644
--- a/arch/s390/kernel/suspend.c
+++ b/arch/s390/kernel/suspend.c
@@ -41,6 +41,7 @@
static struct page_key_data *page_key_data;
static struct page_key_data *page_key_rp, *page_key_wp;
static unsigned long page_key_rx, page_key_wx;
+unsigned long suspend_zero_pages;
/*
* For each page in the hibernation image one additional byte is
@@ -149,6 +150,36 @@
return 0;
}
+/*
+ * PM notifier callback for suspend
+ */
+static int suspend_pm_cb(struct notifier_block *nb, unsigned long action,
+ void *ptr)
+{
+ switch (action) {
+ case PM_SUSPEND_PREPARE:
+ case PM_HIBERNATION_PREPARE:
+ suspend_zero_pages = __get_free_pages(GFP_KERNEL, LC_ORDER);
+ if (!suspend_zero_pages)
+ return NOTIFY_BAD;
+ break;
+ case PM_POST_SUSPEND:
+ case PM_POST_HIBERNATION:
+ free_pages(suspend_zero_pages, LC_ORDER);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
+static int __init suspend_pm_init(void)
+{
+ pm_notifier(suspend_pm_cb, 0);
+ return 0;
+}
+arch_initcall(suspend_pm_init);
+
void save_processor_state(void)
{
/* swsusp_arch_suspend() actually saves all cpu register contents.
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index d4ca4e0..c487be4 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -36,8 +36,8 @@
/* Store prefix register on stack */
stpx __SF_EMPTY(%r15)
- /* Save prefix register contents for lowcore */
- llgf %r4,__SF_EMPTY(%r15)
+ /* Save prefix register contents for lowcore copy */
+ llgf %r10,__SF_EMPTY(%r15)
/* Get pointer to save area */
lghi %r1,0x1000
@@ -91,7 +91,18 @@
xc __SF_EMPTY(4,%r15),__SF_EMPTY(%r15)
spx __SF_EMPTY(%r15)
+ /* Save absolute zero pages */
+ larl %r2,suspend_zero_pages
+ lg %r2,0(%r2)
+ lghi %r4,0
+ lghi %r3,2*PAGE_SIZE
+ lghi %r5,2*PAGE_SIZE
+1: mvcle %r2,%r4,0
+ jo 1b
+
+ /* Copy lowcore to absolute zero lowcore */
lghi %r2,0
+ lgr %r4,%r10
lghi %r3,2*PAGE_SIZE
lghi %r5,2*PAGE_SIZE
1: mvcle %r2,%r4,0
@@ -248,8 +259,20 @@
/* Load old stack */
lg %r15,0x2f8(%r13)
+ /* Save prefix register */
+ mvc __SF_EMPTY(4,%r15),0x318(%r13)
+
+ /* Restore absolute zero pages */
+ lghi %r2,0
+ larl %r4,suspend_zero_pages
+ lg %r4,0(%r4)
+ lghi %r3,2*PAGE_SIZE
+ lghi %r5,2*PAGE_SIZE
+1: mvcle %r2,%r4,0
+ jo 1b
+
/* Restore prefix register */
- spx 0x318(%r13)
+ spx __SF_EMPTY(%r15)
/* Activate DAT */
stosm __SF_EMPTY(%r15),0x04
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 13dd63f..c576232 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -12,49 +12,16 @@
* 'Traps.c' handles hardware traps and faults after we have saved some
* state in 'asm.s'.
*/
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/seq_file.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/kdebug.h>
-#include <linux/kallsyms.h>
-#include <linux/reboot.h>
#include <linux/kprobes.h>
-#include <linux/bug.h>
-#include <linux/utsname.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <asm/mathemu.h>
-#include <asm/cpcmd.h>
-#include <asm/lowcore.h>
-#include <asm/debug.h>
-#include <asm/ipl.h>
+#include <linux/kdebug.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
#include "entry.h"
int show_unhandled_signals = 1;
-#define stack_pointer ({ void **sp; asm("la %0,0(15)" : "=&d" (sp)); sp; })
-
-#ifndef CONFIG_64BIT
-#define LONG "%08lx "
-#define FOURLONG "%08lx %08lx %08lx %08lx\n"
-static int kstack_depth_to_print = 12;
-#else /* CONFIG_64BIT */
-#define LONG "%016lx "
-#define FOURLONG "%016lx %016lx %016lx %016lx\n"
-static int kstack_depth_to_print = 20;
-#endif /* CONFIG_64BIT */
-
static inline void __user *get_trap_ip(struct pt_regs *regs)
{
#ifdef CONFIG_64BIT
@@ -72,215 +39,6 @@
#endif
}
-/*
- * For show_trace we have tree different stack to consider:
- * - the panic stack which is used if the kernel stack has overflown
- * - the asynchronous interrupt stack (cpu related)
- * - the synchronous kernel stack (process related)
- * The stack trace can start at any of the three stack and can potentially
- * touch all of them. The order is: panic stack, async stack, sync stack.
- */
-static unsigned long
-__show_trace(unsigned long sp, unsigned long low, unsigned long high)
-{
- struct stack_frame *sf;
- struct pt_regs *regs;
-
- while (1) {
- sp = sp & PSW_ADDR_INSN;
- if (sp < low || sp > high - sizeof(*sf))
- return sp;
- sf = (struct stack_frame *) sp;
- printk("([<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
- print_symbol("%s)\n", sf->gprs[8] & PSW_ADDR_INSN);
- /* Follow the backchain. */
- while (1) {
- low = sp;
- sp = sf->back_chain & PSW_ADDR_INSN;
- if (!sp)
- break;
- if (sp <= low || sp > high - sizeof(*sf))
- return sp;
- sf = (struct stack_frame *) sp;
- printk(" [<%016lx>] ", sf->gprs[8] & PSW_ADDR_INSN);
- print_symbol("%s\n", sf->gprs[8] & PSW_ADDR_INSN);
- }
- /* Zero backchain detected, check for interrupt frame. */
- sp = (unsigned long) (sf + 1);
- if (sp <= low || sp > high - sizeof(*regs))
- return sp;
- regs = (struct pt_regs *) sp;
- printk(" [<%016lx>] ", regs->psw.addr & PSW_ADDR_INSN);
- print_symbol("%s\n", regs->psw.addr & PSW_ADDR_INSN);
- low = sp;
- sp = regs->gprs[15];
- }
-}
-
-static void show_trace(struct task_struct *task, unsigned long *stack)
-{
- register unsigned long __r15 asm ("15");
- unsigned long sp;
-
- sp = (unsigned long) stack;
- if (!sp)
- sp = task ? task->thread.ksp : __r15;
- printk("Call Trace:\n");
-#ifdef CONFIG_CHECK_STACK
- sp = __show_trace(sp, S390_lowcore.panic_stack - 4096,
- S390_lowcore.panic_stack);
-#endif
- sp = __show_trace(sp, S390_lowcore.async_stack - ASYNC_SIZE,
- S390_lowcore.async_stack);
- if (task)
- __show_trace(sp, (unsigned long) task_stack_page(task),
- (unsigned long) task_stack_page(task) + THREAD_SIZE);
- else
- __show_trace(sp, S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
- if (!task)
- task = current;
- debug_show_held_locks(task);
-}
-
-void show_stack(struct task_struct *task, unsigned long *sp)
-{
- register unsigned long * __r15 asm ("15");
- unsigned long *stack;
- int i;
-
- if (!sp)
- stack = task ? (unsigned long *) task->thread.ksp : __r15;
- else
- stack = sp;
-
- for (i = 0; i < kstack_depth_to_print; i++) {
- if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
- break;
- if ((i * sizeof(long) % 32) == 0)
- printk("%s ", i == 0 ? "" : "\n");
- printk(LONG, *stack++);
- }
- printk("\n");
- show_trace(task, sp);
-}
-
-static void show_last_breaking_event(struct pt_regs *regs)
-{
-#ifdef CONFIG_64BIT
- printk("Last Breaking-Event-Address:\n");
- printk(" [<%016lx>] ", regs->args[0] & PSW_ADDR_INSN);
- print_symbol("%s\n", regs->args[0] & PSW_ADDR_INSN);
-#endif
-}
-
-/*
- * The architecture-independent dump_stack generator
- */
-void dump_stack(void)
-{
- printk("CPU: %d %s %s %.*s\n",
- task_thread_info(current)->cpu, print_tainted(),
- init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
- printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
- current->comm, current->pid, current,
- (void *) current->thread.ksp);
- show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
-
-static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
-{
- return (regs->psw.mask & bits) / ((~bits + 1) & bits);
-}
-
-void show_registers(struct pt_regs *regs)
-{
- char *mode;
-
- mode = user_mode(regs) ? "User" : "Krnl";
- printk("%s PSW : %p %p",
- mode, (void *) regs->psw.mask,
- (void *) regs->psw.addr);
- print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN);
- printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
- "P:%x AS:%x CC:%x PM:%x", mask_bits(regs, PSW_MASK_PER),
- mask_bits(regs, PSW_MASK_DAT), mask_bits(regs, PSW_MASK_IO),
- mask_bits(regs, PSW_MASK_EXT), mask_bits(regs, PSW_MASK_KEY),
- mask_bits(regs, PSW_MASK_MCHECK), mask_bits(regs, PSW_MASK_WAIT),
- mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
- mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
-#ifdef CONFIG_64BIT
- printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
-#endif
- printk("\n%s GPRS: " FOURLONG, mode,
- regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
- printk(" " FOURLONG,
- regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
- printk(" " FOURLONG,
- regs->gprs[8], regs->gprs[9], regs->gprs[10], regs->gprs[11]);
- printk(" " FOURLONG,
- regs->gprs[12], regs->gprs[13], regs->gprs[14], regs->gprs[15]);
-
- show_code(regs);
-}
-
-void show_regs(struct pt_regs *regs)
-{
- printk("CPU: %d %s %s %.*s\n",
- task_thread_info(current)->cpu, print_tainted(),
- init_utsname()->release,
- (int)strcspn(init_utsname()->version, " "),
- init_utsname()->version);
- printk("Process %s (pid: %d, task: %p, ksp: %p)\n",
- current->comm, current->pid, current,
- (void *) current->thread.ksp);
- show_registers(regs);
- /* Show stack backtrace if pt_regs is from kernel mode */
- if (!user_mode(regs))
- show_trace(NULL, (unsigned long *) regs->gprs[15]);
- show_last_breaking_event(regs);
-}
-
-static DEFINE_SPINLOCK(die_lock);
-
-void die(struct pt_regs *regs, const char *str)
-{
- static int die_counter;
-
- oops_enter();
- lgr_info_log();
- debug_stop_all();
- console_verbose();
- spin_lock_irq(&die_lock);
- bust_spinlocks(1);
- printk("%s: %04x [#%d] ", str, regs->int_code & 0xffff, ++die_counter);
-#ifdef CONFIG_PREEMPT
- printk("PREEMPT ");
-#endif
-#ifdef CONFIG_SMP
- printk("SMP ");
-#endif
-#ifdef CONFIG_DEBUG_PAGEALLOC
- printk("DEBUG_PAGEALLOC");
-#endif
- printk("\n");
- notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
- print_modules();
- show_regs(regs);
- bust_spinlocks(0);
- add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
- spin_unlock_irq(&die_lock);
- if (in_interrupt())
- panic("Fatal exception in interrupt");
- if (panic_on_oops)
- panic("Fatal exception: panic_on_oops");
- oops_exit();
- do_exit(SIGSEGV);
-}
-
static inline void report_user_fault(struct pt_regs *regs, int signr)
{
if ((task_pid_nr(current) > 1) && !show_unhandled_signals)
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index 2b29e62..53252d2d 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -117,7 +117,7 @@
__entry->instruction,
insn_to_mnemonic((unsigned char *)
&__entry->instruction,
- __entry->insn) ?
+ __entry->insn, sizeof(__entry->insn)) ?
"unknown" : __entry->insn)
);
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 479e942..9d84a1f 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -458,12 +458,10 @@
if (rc)
goto out_pm;
cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
- rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
- if (rc)
- goto out_kthread;
- return 0;
+ if (!IS_ERR(cmm_thread_ptr))
+ return 0;
-out_kthread:
+ rc = PTR_ERR(cmm_thread_ptr);
unregister_pm_notifier(&cmm_power_notifier);
out_pm:
unregister_oom_notifier(&cmm_oom_nb);
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2fb9e63..047c3e4 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -395,8 +395,13 @@
int fault;
trans_exc_code = regs->int_parm_long;
- /* Protection exception is suppressing, decrement psw address. */
- regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
+ /*
+ * Protection exceptions are suppressing, decrement psw address.
+ * The exception to this rule are aborted transactions, for these
+ * the PSW already points to the correct location.
+ */
+ if (!(regs->int_code & 0x200))
+ regs->psw.addr = __rewind_psw(regs->psw, regs->int_code >> 16);
/*
* Check for low-address protection. This needs to be treated
* as a special case because the translation exception code
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 49ce6bb2..9f9c315 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -63,10 +63,18 @@
break;
case 0x2097: /* z10 */
case 0x2098: /* z10 */
- default:
+ case 0x2817: /* z196 */
+ case 0x2818: /* z196 */
order = 2;
break;
+ case 0x2827: /* zEC12 */
+ default:
+ order = 5;
+ break;
}
+ /* Limit number of empty zero pages for small memory sizes */
+ if (order > 2 && totalram_pages <= 16384)
+ order = 2;
empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!empty_zero_page)
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index d21040e..80adfbf 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -9,31 +9,25 @@
#include <asm/pgtable.h>
#include <asm/page.h>
+static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
+{
+ asm volatile(".insn rrf,0xb22b0000,%[skey],%[addr],9,0"
+ : [addr] "+a" (addr) : [skey] "d" (skey));
+ return addr;
+}
+
void storage_key_init_range(unsigned long start, unsigned long end)
{
- unsigned long boundary, function, size;
+ unsigned long boundary, size;
while (start < end) {
- if (MACHINE_HAS_EDAT2) {
- /* set storage keys for a 2GB frame */
- function = 0x22000 | PAGE_DEFAULT_KEY;
- size = 1UL << 31;
- boundary = (start + size) & ~(size - 1);
- if (boundary <= end) {
- do {
- start = pfmf(function, start);
- } while (start < boundary);
- continue;
- }
- }
if (MACHINE_HAS_EDAT1) {
/* set storage keys for a 1MB frame */
- function = 0x21000 | PAGE_DEFAULT_KEY;
size = 1UL << 20;
boundary = (start + size) & ~(size - 1);
if (boundary <= end) {
do {
- start = pfmf(function, start);
+ start = sske_frame(start, PAGE_DEFAULT_KEY);
} while (start < boundary);
continue;
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index ae44d2a..bd954e9 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -379,78 +379,186 @@
}
EXPORT_SYMBOL_GPL(gmap_map_segment);
-/*
- * this function is assumed to be called with mmap_sem held
- */
-unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
+static unsigned long *gmap_table_walk(unsigned long address, struct gmap *gmap)
{
- unsigned long *table, vmaddr, segment;
- struct mm_struct *mm;
- struct gmap_pgtable *mp;
- struct gmap_rmap *rmap;
- struct vm_area_struct *vma;
- struct page *page;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
+ unsigned long *table;
- current->thread.gmap_addr = address;
- mm = gmap->mm;
- /* Walk the gmap address space page table */
table = gmap->table + ((address >> 53) & 0x7ff);
if (unlikely(*table & _REGION_ENTRY_INV))
- return -EFAULT;
+ return ERR_PTR(-EFAULT);
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + ((address >> 42) & 0x7ff);
if (unlikely(*table & _REGION_ENTRY_INV))
- return -EFAULT;
+ return ERR_PTR(-EFAULT);
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + ((address >> 31) & 0x7ff);
if (unlikely(*table & _REGION_ENTRY_INV))
- return -EFAULT;
+ return ERR_PTR(-EFAULT);
table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
table = table + ((address >> 20) & 0x7ff);
+ return table;
+}
+/**
+ * __gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ * The mmap_sem of the mm that belongs to the address space must be held
+ * when this function gets called.
+ */
+unsigned long __gmap_translate(unsigned long address, struct gmap *gmap)
+{
+ unsigned long *segment_ptr, vmaddr, segment;
+ struct gmap_pgtable *mp;
+ struct page *page;
+
+ current->thread.gmap_addr = address;
+ segment_ptr = gmap_table_walk(address, gmap);
+ if (IS_ERR(segment_ptr))
+ return PTR_ERR(segment_ptr);
/* Convert the gmap address to an mm address. */
- segment = *table;
- if (likely(!(segment & _SEGMENT_ENTRY_INV))) {
+ segment = *segment_ptr;
+ if (!(segment & _SEGMENT_ENTRY_INV)) {
page = pfn_to_page(segment >> PAGE_SHIFT);
mp = (struct gmap_pgtable *) page->index;
return mp->vmaddr | (address & ~PMD_MASK);
} else if (segment & _SEGMENT_ENTRY_RO) {
vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
- vma = find_vma(mm, vmaddr);
- if (!vma || vma->vm_start > vmaddr)
- return -EFAULT;
-
- /* Walk the parent mm page table */
- pgd = pgd_offset(mm, vmaddr);
- pud = pud_alloc(mm, pgd, vmaddr);
- if (!pud)
- return -ENOMEM;
- pmd = pmd_alloc(mm, pud, vmaddr);
- if (!pmd)
- return -ENOMEM;
- if (!pmd_present(*pmd) &&
- __pte_alloc(mm, vma, pmd, vmaddr))
- return -ENOMEM;
- /* pmd now points to a valid segment table entry. */
- rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
- if (!rmap)
- return -ENOMEM;
- /* Link gmap segment table entry location to page table. */
- page = pmd_page(*pmd);
- mp = (struct gmap_pgtable *) page->index;
- rmap->entry = table;
- spin_lock(&mm->page_table_lock);
- list_add(&rmap->list, &mp->mapper);
- spin_unlock(&mm->page_table_lock);
- /* Set gmap segment table entry to page table. */
- *table = pmd_val(*pmd) & PAGE_MASK;
return vmaddr | (address & ~PMD_MASK);
}
return -EFAULT;
}
+EXPORT_SYMBOL_GPL(__gmap_translate);
+
+/**
+ * gmap_translate - translate a guest address to a user space address
+ * @address: guest address
+ * @gmap: pointer to guest mapping meta data structure
+ *
+ * Returns user space address which corresponds to the guest address or
+ * -EFAULT if no such mapping exists.
+ * This function does not establish potentially missing page table entries.
+ */
+unsigned long gmap_translate(unsigned long address, struct gmap *gmap)
+{
+ unsigned long rc;
+
+ down_read(&gmap->mm->mmap_sem);
+ rc = __gmap_translate(address, gmap);
+ up_read(&gmap->mm->mmap_sem);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(gmap_translate);
+
+static int gmap_connect_pgtable(unsigned long segment,
+ unsigned long *segment_ptr,
+ struct gmap *gmap)
+{
+ unsigned long vmaddr;
+ struct vm_area_struct *vma;
+ struct gmap_pgtable *mp;
+ struct gmap_rmap *rmap;
+ struct mm_struct *mm;
+ struct page *page;
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ mm = gmap->mm;
+ vmaddr = segment & _SEGMENT_ENTRY_ORIGIN;
+ vma = find_vma(mm, vmaddr);
+ if (!vma || vma->vm_start > vmaddr)
+ return -EFAULT;
+ /* Walk the parent mm page table */
+ pgd = pgd_offset(mm, vmaddr);
+ pud = pud_alloc(mm, pgd, vmaddr);
+ if (!pud)
+ return -ENOMEM;
+ pmd = pmd_alloc(mm, pud, vmaddr);
+ if (!pmd)
+ return -ENOMEM;
+ if (!pmd_present(*pmd) &&
+ __pte_alloc(mm, vma, pmd, vmaddr))
+ return -ENOMEM;
+ /* pmd now points to a valid segment table entry. */
+ rmap = kmalloc(sizeof(*rmap), GFP_KERNEL|__GFP_REPEAT);
+ if (!rmap)
+ return -ENOMEM;
+ /* Link gmap segment table entry location to page table. */
+ page = pmd_page(*pmd);
+ mp = (struct gmap_pgtable *) page->index;
+ rmap->entry = segment_ptr;
+ spin_lock(&mm->page_table_lock);
+ if (*segment_ptr == segment) {
+ list_add(&rmap->list, &mp->mapper);
+ /* Set gmap segment table entry to page table. */
+ *segment_ptr = pmd_val(*pmd) & PAGE_MASK;
+ rmap = NULL;
+ }
+ spin_unlock(&mm->page_table_lock);
+ kfree(rmap);
+ return 0;
+}
+
+static void gmap_disconnect_pgtable(struct mm_struct *mm, unsigned long *table)
+{
+ struct gmap_rmap *rmap, *next;
+ struct gmap_pgtable *mp;
+ struct page *page;
+ int flush;
+
+ flush = 0;
+ spin_lock(&mm->page_table_lock);
+ page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
+ *rmap->entry =
+ _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
+ list_del(&rmap->list);
+ kfree(rmap);
+ flush = 1;
+ }
+ spin_unlock(&mm->page_table_lock);
+ if (flush)
+ __tlb_flush_global();
+}
+
+/*
+ * this function is assumed to be called with mmap_sem held
+ */
+unsigned long __gmap_fault(unsigned long address, struct gmap *gmap)
+{
+ unsigned long *segment_ptr, segment;
+ struct gmap_pgtable *mp;
+ struct page *page;
+ int rc;
+
+ current->thread.gmap_addr = address;
+ segment_ptr = gmap_table_walk(address, gmap);
+ if (IS_ERR(segment_ptr))
+ return -EFAULT;
+ /* Convert the gmap address to an mm address. */
+ while (1) {
+ segment = *segment_ptr;
+ if (!(segment & _SEGMENT_ENTRY_INV)) {
+ /* Page table is present */
+ page = pfn_to_page(segment >> PAGE_SHIFT);
+ mp = (struct gmap_pgtable *) page->index;
+ return mp->vmaddr | (address & ~PMD_MASK);
+ }
+ if (!(segment & _SEGMENT_ENTRY_RO))
+ /* Nothing mapped in the gmap address space. */
+ break;
+ rc = gmap_connect_pgtable(segment, segment_ptr, gmap);
+ if (rc)
+ return rc;
+ }
+ return -EFAULT;
+}
unsigned long gmap_fault(unsigned long address, struct gmap *gmap)
{
@@ -511,29 +619,6 @@
}
EXPORT_SYMBOL_GPL(gmap_discard);
-void gmap_unmap_notifier(struct mm_struct *mm, unsigned long *table)
-{
- struct gmap_rmap *rmap, *next;
- struct gmap_pgtable *mp;
- struct page *page;
- int flush;
-
- flush = 0;
- spin_lock(&mm->page_table_lock);
- page = pfn_to_page(__pa(table) >> PAGE_SHIFT);
- mp = (struct gmap_pgtable *) page->index;
- list_for_each_entry_safe(rmap, next, &mp->mapper, list) {
- *rmap->entry =
- _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO | mp->vmaddr;
- list_del(&rmap->list);
- kfree(rmap);
- flush = 1;
- }
- spin_unlock(&mm->page_table_lock);
- if (flush)
- __tlb_flush_global();
-}
-
static inline unsigned long *page_table_alloc_pgste(struct mm_struct *mm,
unsigned long vmaddr)
{
@@ -586,8 +671,8 @@
{
}
-static inline void gmap_unmap_notifier(struct mm_struct *mm,
- unsigned long *table)
+static inline void gmap_disconnect_pgtable(struct mm_struct *mm,
+ unsigned long *table)
{
}
@@ -653,7 +738,7 @@
unsigned int bit, mask;
if (mm_has_pgste(mm)) {
- gmap_unmap_notifier(mm, table);
+ gmap_disconnect_pgtable(mm, table);
return page_table_free_pgste(table);
}
/* Free 1K/2K page table fragment of a 4K page */
@@ -696,7 +781,7 @@
mm = tlb->mm;
if (mm_has_pgste(mm)) {
- gmap_unmap_notifier(mm, table);
+ gmap_disconnect_pgtable(mm, table);
table = (unsigned long *) (__pa(table) | FRAG_MASK);
tlb_remove_table(tlb, table);
return;
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 0972e91..82f165f 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -747,10 +747,9 @@
if (!bpf_jit_enable)
return;
- addrs = kmalloc(fp->len * sizeof(*addrs), GFP_KERNEL);
+ addrs = kcalloc(fp->len, sizeof(*addrs), GFP_KERNEL);
if (addrs == NULL)
return;
- memset(addrs, 0, fp->len * sizeof(*addrs));
memset(&jit, 0, sizeof(cjit));
memset(&cjit, 0, sizeof(cjit));
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index f0f426a..086a2e37 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -2,5 +2,5 @@
# Makefile for the s390 PCI subsystem.
#
-obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o \
- pci_sysfs.o pci_event.o pci_debug.o
+obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o pci_sysfs.o \
+ pci_event.o pci_debug.o pci_insn.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 27b4c17..e6f15b5 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -99,9 +99,6 @@
static struct kmem_cache *zdev_irq_cache;
static struct kmem_cache *zdev_fmb_cache;
-debug_info_t *pci_debug_msg_id;
-debug_info_t *pci_debug_err_id;
-
static inline int irq_to_msi_nr(unsigned int irq)
{
return irq & ZPCI_MSI_MASK;
@@ -179,7 +176,7 @@
fib->aisb = (u64) bucket->aisb + aisb / 8;
fib->aisbo = aisb & ZPCI_MSI_MASK;
- rc = mpcifc_instr(req, fib);
+ rc = s390pci_mod_fc(req, fib);
pr_debug("%s mpcifc returned noi: %d\n", __func__, fib->noi);
free_page((unsigned long) fib);
@@ -209,7 +206,7 @@
fib->iota = args->iota;
fib->fmb_addr = args->fmb_addr;
- rc = mpcifc_instr(req, fib);
+ rc = s390pci_mod_fc(req, fib);
free_page((unsigned long) fib);
return rc;
}
@@ -249,10 +246,9 @@
if (zdev->fmb)
return -EINVAL;
- zdev->fmb = kmem_cache_alloc(zdev_fmb_cache, GFP_KERNEL);
+ zdev->fmb = kmem_cache_zalloc(zdev_fmb_cache, GFP_KERNEL);
if (!zdev->fmb)
return -ENOMEM;
- memset(zdev->fmb, 0, sizeof(*zdev->fmb));
WARN_ON((u64) zdev->fmb & 0xf);
args.fmb_addr = virt_to_phys(zdev->fmb);
@@ -284,12 +280,12 @@
u64 data;
int rc;
- rc = pcilg_instr(&data, req, offset);
- data = data << ((8 - len) * 8);
- data = le64_to_cpu(data);
- if (!rc)
+ rc = s390pci_load(&data, req, offset);
+ if (!rc) {
+ data = data << ((8 - len) * 8);
+ data = le64_to_cpu(data);
*val = (u32) data;
- else
+ } else
*val = 0xffffffff;
return rc;
}
@@ -302,7 +298,7 @@
data = cpu_to_le64(data);
data = data >> ((8 - len) * 8);
- rc = pcistg_instr(data, req, offset);
+ rc = s390pci_store(data, req, offset);
return rc;
}
@@ -409,20 +405,28 @@
int size, u32 *val)
{
struct zpci_dev *zdev = get_zdev_by_bus(bus);
+ int ret;
if (!zdev || devfn != ZPCI_DEVFN)
- return 0;
- return zpci_cfg_load(zdev, where, val, size);
+ ret = -ENODEV;
+ else
+ ret = zpci_cfg_load(zdev, where, val, size);
+
+ return ret;
}
static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
struct zpci_dev *zdev = get_zdev_by_bus(bus);
+ int ret;
if (!zdev || devfn != ZPCI_DEVFN)
- return 0;
- return zpci_cfg_store(zdev, where, val, size);
+ ret = -ENODEV;
+ else
+ ret = zpci_cfg_store(zdev, where, val, size);
+
+ return ret;
}
static struct pci_ops pci_root_ops = {
@@ -474,7 +478,7 @@
}
/* enable interrupts again */
- sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+ set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
/* check again to not lose initiative */
rmb();
@@ -596,19 +600,6 @@
}
};
-static void zpci_unmap_resources(struct pci_dev *pdev)
-{
- resource_size_t len;
- int i;
-
- for (i = 0; i < PCI_BAR_COUNT; i++) {
- len = pci_resource_len(pdev, i);
- if (!len)
- continue;
- pci_iounmap(pdev, (void *) pdev->resource[i].start);
- }
-};
-
struct zpci_dev *zpci_alloc_device(void)
{
struct zpci_dev *zdev;
@@ -636,32 +627,6 @@
kfree(zdev);
}
-/* Called on removal of pci_dev, leaves zpci and bus device */
-static void zpci_remove_device(struct pci_dev *pdev)
-{
- struct zpci_dev *zdev = get_zdev(pdev);
-
- dev_info(&pdev->dev, "Removing device %u\n", zdev->domain);
- zdev->state = ZPCI_FN_STATE_CONFIGURED;
- zpci_dma_exit_device(zdev);
- zpci_fmb_disable_device(zdev);
- zpci_sysfs_remove_device(&pdev->dev);
- zpci_unmap_resources(pdev);
- list_del(&zdev->entry); /* can be called from init */
- zdev->pdev = NULL;
-}
-
-static void zpci_scan_devices(void)
-{
- struct zpci_dev *zdev;
-
- mutex_lock(&zpci_list_lock);
- list_for_each_entry(zdev, &zpci_list, entry)
- if (zdev->state == ZPCI_FN_STATE_CONFIGURED)
- zpci_scan_device(zdev);
- mutex_unlock(&zpci_list_lock);
-}
-
/*
* Too late for any s390 specific setup, since interrupts must be set up
* already which requires DMA setup too and the pci scan will access the
@@ -688,12 +653,6 @@
return 0;
}
-void pcibios_disable_device(struct pci_dev *pdev)
-{
- zpci_remove_device(pdev);
- pdev->sysdata = NULL;
-}
-
int pcibios_add_platform_entries(struct pci_dev *pdev)
{
return zpci_sysfs_add_device(&pdev->dev);
@@ -789,7 +748,7 @@
spin_lock_init(&bucket->lock);
/* set summary to 1 to be called every time for the ISC */
*zpci_irq_si = 1;
- sic_instr(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
+ set_irq_ctrl(SIC_IRQ_MODE_SINGLE, NULL, PCI_ISC);
return 0;
out_ai:
@@ -872,7 +831,19 @@
spin_unlock(&zpci_iomap_lock);
}
-static int zpci_create_device_bus(struct zpci_dev *zdev)
+int pcibios_add_device(struct pci_dev *pdev)
+{
+ struct zpci_dev *zdev = get_zdev(pdev);
+
+ zdev->pdev = pdev;
+ zpci_debug_init_device(zdev);
+ zpci_fmb_enable_device(zdev);
+ zpci_map_resources(zdev);
+
+ return 0;
+}
+
+static int zpci_scan_bus(struct zpci_dev *zdev)
{
struct resource *res;
LIST_HEAD(resources);
@@ -909,8 +880,8 @@
pci_add_resource(&resources, res);
}
- zdev->bus = pci_create_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
- zdev, &resources);
+ zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops,
+ zdev, &resources);
if (!zdev->bus)
return -EIO;
@@ -959,6 +930,13 @@
}
EXPORT_SYMBOL_GPL(zpci_enable_device);
+int zpci_disable_device(struct zpci_dev *zdev)
+{
+ zpci_dma_exit_device(zdev);
+ return clp_disable_fh(zdev);
+}
+EXPORT_SYMBOL_GPL(zpci_disable_device);
+
int zpci_create_device(struct zpci_dev *zdev)
{
int rc;
@@ -967,9 +945,16 @@
if (rc)
goto out;
- rc = zpci_create_device_bus(zdev);
+ if (zdev->state == ZPCI_FN_STATE_CONFIGURED) {
+ rc = zpci_enable_device(zdev);
+ if (rc)
+ goto out_free;
+
+ zdev->state = ZPCI_FN_STATE_ONLINE;
+ }
+ rc = zpci_scan_bus(zdev);
if (rc)
- goto out_bus;
+ goto out_disable;
mutex_lock(&zpci_list_lock);
list_add_tail(&zdev->entry, &zpci_list);
@@ -977,21 +962,12 @@
hotplug_ops->create_slot(zdev);
mutex_unlock(&zpci_list_lock);
- if (zdev->state == ZPCI_FN_STATE_STANDBY)
- return 0;
-
- rc = zpci_enable_device(zdev);
- if (rc)
- goto out_start;
return 0;
-out_start:
- mutex_lock(&zpci_list_lock);
- list_del(&zdev->entry);
- if (hotplug_ops)
- hotplug_ops->remove_slot(zdev);
- mutex_unlock(&zpci_list_lock);
-out_bus:
+out_disable:
+ if (zdev->state == ZPCI_FN_STATE_ONLINE)
+ zpci_disable_device(zdev);
+out_free:
zpci_free_domain(zdev);
out:
return rc;
@@ -1016,15 +992,9 @@
goto out;
}
- zpci_debug_init_device(zdev);
- zpci_fmb_enable_device(zdev);
- zpci_map_resources(zdev);
pci_bus_add_devices(zdev->bus);
- /* now that pdev was added to the bus mark it as used */
- zdev->state = ZPCI_FN_STATE_ONLINE;
return 0;
-
out:
zpci_dma_exit_device(zdev);
clp_disable_fh(zdev);
@@ -1087,13 +1057,13 @@
}
EXPORT_SYMBOL_GPL(zpci_deregister_hp_ops);
-unsigned int s390_pci_probe = 1;
+unsigned int s390_pci_probe;
EXPORT_SYMBOL_GPL(s390_pci_probe);
char * __init pcibios_setup(char *str)
{
- if (!strcmp(str, "off")) {
- s390_pci_probe = 0;
+ if (!strcmp(str, "on")) {
+ s390_pci_probe = 1;
return NULL;
}
return str;
@@ -1138,7 +1108,6 @@
if (rc)
goto out_find;
- zpci_scan_devices();
return 0;
out_find:
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c
index f339fe2f..bd34359 100644
--- a/arch/s390/pci/pci_clp.c
+++ b/arch/s390/pci/pci_clp.c
@@ -13,6 +13,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/pci.h>
+#include <asm/pci_debug.h>
#include <asm/pci_clp.h>
/*
@@ -144,6 +145,7 @@
struct zpci_dev *zdev;
int rc;
+ zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, configured);
zdev = zpci_alloc_device();
if (IS_ERR(zdev))
return PTR_ERR(zdev);
@@ -204,8 +206,8 @@
if (!rc && rrb->response.hdr.rsp == CLP_RC_OK)
*fh = rrb->response.fh;
else {
- pr_err("Set PCI FN failed with response: %x cc: %d\n",
- rrb->response.hdr.rsp, rc);
+ zpci_dbg(0, "SPF fh:%x, cc:%d, resp:%x\n", *fh, rc,
+ rrb->response.hdr.rsp);
rc = -EIO;
}
clp_free_block(rrb);
@@ -221,6 +223,8 @@
if (!rc)
/* Success -> store enabled handle in zdev */
zdev->fh = fh;
+
+ zpci_dbg(3, "ena fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
return rc;
}
@@ -237,9 +241,8 @@
if (!rc)
/* Success -> store disabled handle in zdev */
zdev->fh = fh;
- else
- dev_err(&zdev->pdev->dev,
- "Failed to disable fn handle: 0x%x\n", fh);
+
+ zpci_dbg(3, "dis fid:%x, fh:%x, rc:%d\n", zdev->fid, zdev->fh, rc);
return rc;
}
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c
index a5d07bc..771b823 100644
--- a/arch/s390/pci/pci_debug.c
+++ b/arch/s390/pci/pci_debug.c
@@ -11,12 +11,17 @@
#include <linux/kernel.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
+#include <linux/export.h>
#include <linux/pci.h>
#include <asm/debug.h>
#include <asm/pci_dma.h>
static struct dentry *debugfs_root;
+debug_info_t *pci_debug_msg_id;
+EXPORT_SYMBOL_GPL(pci_debug_msg_id);
+debug_info_t *pci_debug_err_id;
+EXPORT_SYMBOL_GPL(pci_debug_err_id);
static char *pci_perf_names[] = {
/* hardware counters */
@@ -168,7 +173,6 @@
return -EINVAL;
debug_register_view(pci_debug_msg_id, &debug_sprintf_view);
debug_set_level(pci_debug_msg_id, 3);
- zpci_dbg("Debug view initialized\n");
/* error log */
pci_debug_err_id = debug_register("pci_error", 2, 1, 16);
@@ -176,7 +180,6 @@
return -EINVAL;
debug_register_view(pci_debug_err_id, &debug_hex_ascii_view);
debug_set_level(pci_debug_err_id, 6);
- zpci_err("Debug view initialized\n");
debugfs_root = debugfs_create_dir("pci", NULL);
return 0;
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index a547419..f8e69d5 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -169,8 +169,9 @@
* needs to be redone!
*/
goto no_refresh;
- rc = rpcit_instr((u64) zdev->fh << 32, start_dma_addr,
- nr_pages * PAGE_SIZE);
+
+ rc = s390pci_refresh_trans((u64) zdev->fh << 32, start_dma_addr,
+ nr_pages * PAGE_SIZE);
no_refresh:
spin_unlock_irqrestore(&zdev->dma_table_lock, irq_flags);
@@ -268,8 +269,6 @@
int flags = ZPCI_PTE_VALID;
dma_addr_t dma_addr;
- WARN_ON_ONCE(offset > PAGE_SIZE);
-
/* This rounds up number of pages based on size and offset */
nr_pages = iommu_num_pages(pa, size, PAGE_SIZE);
iommu_page_index = dma_alloc_iommu(zdev, nr_pages);
@@ -291,7 +290,7 @@
if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) {
atomic64_add(nr_pages, (atomic64_t *) &zdev->fmb->mapped_pages);
- return dma_addr + offset;
+ return dma_addr + (offset & ~PAGE_MASK);
}
out_free:
diff --git a/arch/s390/pci/pci_insn.c b/arch/s390/pci/pci_insn.c
new file mode 100644
index 0000000..22eeb9d
--- /dev/null
+++ b/arch/s390/pci/pci_insn.c
@@ -0,0 +1,202 @@
+/*
+ * s390 specific pci instructions
+ *
+ * Copyright IBM Corp. 2013
+ */
+
+#include <linux/export.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <asm/pci_insn.h>
+#include <asm/processor.h>
+
+#define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */
+
+/* Modify PCI Function Controls */
+static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
+{
+ u8 cc;
+
+ asm volatile (
+ " .insn rxy,0xe300000000d0,%[req],%[fib]\n"
+ " ipm %[cc]\n"
+ " srl %[cc],28\n"
+ : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib)
+ : : "cc");
+ *status = req >> 24 & 0xff;
+ return cc;
+}
+
+int s390pci_mod_fc(u64 req, struct zpci_fib *fib)
+{
+ u8 cc, status;
+
+ do {
+ cc = __mpcifc(req, fib, &status);
+ if (cc == 2)
+ msleep(ZPCI_INSN_BUSY_DELAY);
+ } while (cc == 2);
+
+ if (cc)
+ printk_once(KERN_ERR "%s: error cc: %d status: %d\n",
+ __func__, cc, status);
+ return (cc) ? -EIO : 0;
+}
+
+/* Refresh PCI Translations */
+static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status)
+{
+ register u64 __addr asm("2") = addr;
+ register u64 __range asm("3") = range;
+ u8 cc;
+
+ asm volatile (
+ " .insn rre,0xb9d30000,%[fn],%[addr]\n"
+ " ipm %[cc]\n"
+ " srl %[cc],28\n"
+ : [cc] "=d" (cc), [fn] "+d" (fn)
+ : [addr] "d" (__addr), "d" (__range)
+ : "cc");
+ *status = fn >> 24 & 0xff;
+ return cc;
+}
+
+int s390pci_refresh_trans(u64 fn, u64 addr, u64 range)
+{
+ u8 cc, status;
+
+ do {
+ cc = __rpcit(fn, addr, range, &status);
+ if (cc == 2)
+ udelay(ZPCI_INSN_BUSY_DELAY);
+ } while (cc == 2);
+
+ if (cc)
+ printk_once(KERN_ERR "%s: error cc: %d status: %d dma_addr: %Lx size: %Lx\n",
+ __func__, cc, status, addr, range);
+ return (cc) ? -EIO : 0;
+}
+
+/* Set Interruption Controls */
+void set_irq_ctrl(u16 ctl, char *unused, u8 isc)
+{
+ asm volatile (
+ " .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n"
+ : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused));
+}
+
+/* PCI Load */
+static inline int __pcilg(u64 *data, u64 req, u64 offset, u8 *status)
+{
+ register u64 __req asm("2") = req;
+ register u64 __offset asm("3") = offset;
+ int cc = -ENXIO;
+ u64 __data;
+
+ asm volatile (
+ " .insn rre,0xb9d20000,%[data],%[req]\n"
+ "0: ipm %[cc]\n"
+ " srl %[cc],28\n"
+ "1:\n"
+ EX_TABLE(0b, 1b)
+ : [cc] "+d" (cc), [data] "=d" (__data), [req] "+d" (__req)
+ : "d" (__offset)
+ : "cc");
+ *status = __req >> 24 & 0xff;
+ if (!cc)
+ *data = __data;
+
+ return cc;
+}
+
+int s390pci_load(u64 *data, u64 req, u64 offset)
+{
+ u8 status;
+ int cc;
+
+ do {
+ cc = __pcilg(data, req, offset, &status);
+ if (cc == 2)
+ udelay(ZPCI_INSN_BUSY_DELAY);
+ } while (cc == 2);
+
+ if (cc)
+ printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
+ __func__, cc, status, req, offset);
+ return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_load);
+
+/* PCI Store */
+static inline int __pcistg(u64 data, u64 req, u64 offset, u8 *status)
+{
+ register u64 __req asm("2") = req;
+ register u64 __offset asm("3") = offset;
+ int cc = -ENXIO;
+
+ asm volatile (
+ " .insn rre,0xb9d00000,%[data],%[req]\n"
+ "0: ipm %[cc]\n"
+ " srl %[cc],28\n"
+ "1:\n"
+ EX_TABLE(0b, 1b)
+ : [cc] "+d" (cc), [req] "+d" (__req)
+ : "d" (__offset), [data] "d" (data)
+ : "cc");
+ *status = __req >> 24 & 0xff;
+ return cc;
+}
+
+int s390pci_store(u64 data, u64 req, u64 offset)
+{
+ u8 status;
+ int cc;
+
+ do {
+ cc = __pcistg(data, req, offset, &status);
+ if (cc == 2)
+ udelay(ZPCI_INSN_BUSY_DELAY);
+ } while (cc == 2);
+
+ if (cc)
+ printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
+ __func__, cc, status, req, offset);
+ return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_store);
+
+/* PCI Store Block */
+static inline int __pcistb(const u64 *data, u64 req, u64 offset, u8 *status)
+{
+ int cc = -ENXIO;
+
+ asm volatile (
+ " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n"
+ "0: ipm %[cc]\n"
+ " srl %[cc],28\n"
+ "1:\n"
+ EX_TABLE(0b, 1b)
+ : [cc] "+d" (cc), [req] "+d" (req)
+ : [offset] "d" (offset), [data] "Q" (*data)
+ : "cc");
+ *status = req >> 24 & 0xff;
+ return cc;
+}
+
+int s390pci_store_block(const u64 *data, u64 req, u64 offset)
+{
+ u8 status;
+ int cc;
+
+ do {
+ cc = __pcistb(data, req, offset, &status);
+ if (cc == 2)
+ udelay(ZPCI_INSN_BUSY_DELAY);
+ } while (cc == 2);
+
+ if (cc)
+ printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n",
+ __func__, cc, status, req, offset);
+ return (cc > 0) ? -EIO : cc;
+}
+EXPORT_SYMBOL_GPL(s390pci_store_block);
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c
index 0297931..b097aed 100644
--- a/arch/s390/pci/pci_msi.c
+++ b/arch/s390/pci/pci_msi.c
@@ -18,8 +18,9 @@
/* mapping of irq numbers to msi_desc */
static struct hlist_head *msi_hash;
-static unsigned int msihash_shift = 6;
-#define msi_hashfn(nr) hash_long(nr, msihash_shift)
+static const unsigned int msi_hash_bits = 8;
+#define MSI_HASH_BUCKETS (1U << msi_hash_bits)
+#define msi_hashfn(nr) hash_long(nr, msi_hash_bits)
static DEFINE_SPINLOCK(msi_map_lock);
@@ -74,6 +75,7 @@
map->irq = nr;
map->msi = msi;
zdev->msi_map[nr & ZPCI_MSI_MASK] = map;
+ INIT_HLIST_NODE(&map->msi_chain);
pr_debug("%s hashing irq: %u to bucket nr: %llu\n",
__func__, nr, msi_hashfn(nr));
@@ -125,11 +127,11 @@
{
unsigned int i;
- msi_hash = kmalloc(256 * sizeof(*msi_hash), GFP_KERNEL);
+ msi_hash = kmalloc(MSI_HASH_BUCKETS * sizeof(*msi_hash), GFP_KERNEL);
if (!msi_hash)
return -ENOMEM;
- for (i = 0; i < (1U << msihash_shift); i++)
+ for (i = 0; i < MSI_HASH_BUCKETS; i++)
INIT_HLIST_HEAD(&msi_hash[i]);
return 0;
}
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index e26d430..ff18e3c 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -2,11 +2,16 @@
generic-y += clkdev.h
+generic-y += cputime.h
generic-y += div64.h
+generic-y += emergency-restart.h
generic-y += exec.h
generic-y += local64.h
+generic-y += mutex.h
generic-y += irq_regs.h
generic-y += local.h
generic-y += module.h
+generic-y += serial.h
generic-y += trace_clock.h
+generic-y += types.h
generic-y += word-at-a-time.h
diff --git a/arch/sparc/include/asm/cputime.h b/arch/sparc/include/asm/cputime.h
deleted file mode 100644
index 1a642b8..0000000
--- a/arch/sparc/include/asm/cputime.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_CPUTIME_H
-#define __SPARC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __SPARC_CPUTIME_H */
diff --git a/arch/sparc/include/asm/emergency-restart.h b/arch/sparc/include/asm/emergency-restart.h
deleted file mode 100644
index 108d8c4..0000000
--- a/arch/sparc/include/asm/emergency-restart.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/sparc/include/asm/mutex.h b/arch/sparc/include/asm/mutex.h
deleted file mode 100644
index 458c1f7..0000000
--- a/arch/sparc/include/asm/mutex.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Pull in the generic implementation for the mutex fastpath.
- *
- * TODO: implement optimized primitives instead, or leave the generic
- * implementation in place, or pick the atomic_xchg() based generic
- * implementation. (see asm-generic/mutex-xchg.h for details)
- */
-
-#include <asm-generic/mutex-dec.h>
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 08fcce9..7619f2f 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -915,6 +915,7 @@
return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
}
+#include <asm/tlbflush.h>
#include <asm-generic/pgtable.h>
/* We provide our own get_unmapped_area to cope with VA holes and
diff --git a/arch/sparc/include/asm/serial.h b/arch/sparc/include/asm/serial.h
deleted file mode 100644
index f90d61c..0000000
--- a/arch/sparc/include/asm/serial.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __SPARC_SERIAL_H
-#define __SPARC_SERIAL_H
-
-#define BASE_BAUD ( 1843200 / 16 )
-
-#endif /* __SPARC_SERIAL_H */
diff --git a/arch/sparc/include/asm/smp_32.h b/arch/sparc/include/asm/smp_32.h
index b73da3c..3c8917f 100644
--- a/arch/sparc/include/asm/smp_32.h
+++ b/arch/sparc/include/asm/smp_32.h
@@ -36,7 +36,6 @@
unsigned long, unsigned long);
void cpu_panic(void);
-extern void smp4m_irq_rotate(int cpu);
/*
* General functions that each host system must provide.
@@ -46,7 +45,6 @@
void sun4d_init_smp(void);
void smp_callin(void);
-void smp_boot_cpus(void);
void smp_store_cpu_info(int);
void smp_resched_interrupt(void);
@@ -107,9 +105,6 @@
#define raw_smp_processor_id() (current_thread_info()->cpu)
-#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
-#define prof_counter(__cpu) cpu_data(__cpu).counter
-
void smp_setup_cpu_possible_map(void);
#endif /* !(__ASSEMBLY__) */
diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h
index cad36f5..c7de332 100644
--- a/arch/sparc/include/asm/switch_to_64.h
+++ b/arch/sparc/include/asm/switch_to_64.h
@@ -18,8 +18,7 @@
* and 2 stores in this critical code path. -DaveM
*/
#define switch_to(prev, next, last) \
-do { flush_tlb_pending(); \
- save_and_clear_fpu(); \
+do { save_and_clear_fpu(); \
/* If you are tempted to conditionalize the following */ \
/* so that ASI is only written if it changes, think again. */ \
__asm__ __volatile__("wr %%g0, %0, %%asi" \
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
index 2ef4634..f0d6a97 100644
--- a/arch/sparc/include/asm/tlbflush_64.h
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -11,24 +11,40 @@
struct tlb_batch {
struct mm_struct *mm;
unsigned long tlb_nr;
+ unsigned long active;
unsigned long vaddrs[TLB_BATCH_NR];
};
extern void flush_tsb_kernel_range(unsigned long start, unsigned long end);
extern void flush_tsb_user(struct tlb_batch *tb);
+extern void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
/* TLB flush operations. */
-extern void flush_tlb_pending(void);
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+}
-#define flush_tlb_range(vma,start,end) \
- do { (void)(start); flush_tlb_pending(); } while (0)
-#define flush_tlb_page(vma,addr) flush_tlb_pending()
-#define flush_tlb_mm(mm) flush_tlb_pending()
+static inline void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long vmaddr)
+{
+}
+
+static inline void flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+}
+
+#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE
+
+extern void flush_tlb_pending(void);
+extern void arch_enter_lazy_mmu_mode(void);
+extern void arch_leave_lazy_mmu_mode(void);
+#define arch_flush_lazy_mmu_mode() do {} while (0)
/* Local cpu only. */
extern void __flush_tlb_all(void);
-
+extern void __flush_tlb_page(unsigned long context, unsigned long vaddr);
extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end);
#ifndef CONFIG_SMP
@@ -38,15 +54,24 @@
__flush_tlb_kernel_range(start,end); \
} while (0)
+static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+ __flush_tlb_page(CTX_HWBITS(mm->context), vaddr);
+}
+
#else /* CONFIG_SMP */
extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end);
+extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr);
#define flush_tlb_kernel_range(start, end) \
do { flush_tsb_kernel_range(start,end); \
smp_flush_tlb_kernel_range(start, end); \
} while (0)
+#define global_flush_tlb_page(mm, vaddr) \
+ smp_flush_tlb_page(mm, vaddr)
+
#endif /* ! CONFIG_SMP */
#endif /* _SPARC64_TLBFLUSH_H */
diff --git a/arch/sparc/include/uapi/asm/Kbuild b/arch/sparc/include/uapi/asm/Kbuild
index ce175af..b5843ee 100644
--- a/arch/sparc/include/uapi/asm/Kbuild
+++ b/arch/sparc/include/uapi/asm/Kbuild
@@ -44,7 +44,6 @@
header-y += termbits.h
header-y += termios.h
header-y += traps.h
-header-y += types.h
header-y += uctx.h
header-y += unistd.h
header-y += utrap.h
diff --git a/arch/sparc/include/uapi/asm/types.h b/arch/sparc/include/uapi/asm/types.h
deleted file mode 100644
index 383d156..0000000
--- a/arch/sparc/include/uapi/asm/types.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _SPARC_TYPES_H
-#define _SPARC_TYPES_H
-/*
- * This file is never included by application software unless
- * explicitly requested (e.g., via linux/types.h) in which case the
- * application is Linux specific so (user-) name space pollution is
- * not a major issue. However, for interoperability, libraries still
- * need to be careful to avoid a name clashes.
- */
-
-#if defined(__sparc__)
-
-#include <asm-generic/int-ll64.h>
-
-#endif /* defined(__sparc__) */
-
-#endif /* defined(_SPARC_TYPES_H) */
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 537eb66..ca64d2a 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -849,7 +849,7 @@
}
extern unsigned long xcall_flush_tlb_mm;
-extern unsigned long xcall_flush_tlb_pending;
+extern unsigned long xcall_flush_tlb_page;
extern unsigned long xcall_flush_tlb_kernel_range;
extern unsigned long xcall_fetch_glob_regs;
extern unsigned long xcall_fetch_glob_pmu;
@@ -1074,19 +1074,52 @@
put_cpu();
}
+struct tlb_pending_info {
+ unsigned long ctx;
+ unsigned long nr;
+ unsigned long *vaddrs;
+};
+
+static void tlb_pending_func(void *info)
+{
+ struct tlb_pending_info *t = info;
+
+ __flush_tlb_pending(t->ctx, t->nr, t->vaddrs);
+}
+
void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs)
{
u32 ctx = CTX_HWBITS(mm->context);
+ struct tlb_pending_info info;
+ int cpu = get_cpu();
+
+ info.ctx = ctx;
+ info.nr = nr;
+ info.vaddrs = vaddrs;
+
+ if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
+ cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
+ else
+ smp_call_function_many(mm_cpumask(mm), tlb_pending_func,
+ &info, 1);
+
+ __flush_tlb_pending(ctx, nr, vaddrs);
+
+ put_cpu();
+}
+
+void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr)
+{
+ unsigned long context = CTX_HWBITS(mm->context);
int cpu = get_cpu();
if (mm == current->mm && atomic_read(&mm->mm_users) == 1)
cpumask_copy(mm_cpumask(mm), cpumask_of(cpu));
else
- smp_cross_call_masked(&xcall_flush_tlb_pending,
- ctx, nr, (unsigned long) vaddrs,
+ smp_cross_call_masked(&xcall_flush_tlb_page,
+ context, vaddr, 0,
mm_cpumask(mm));
-
- __flush_tlb_pending(ctx, nr, vaddrs);
+ __flush_tlb_page(context, vaddr);
put_cpu();
}
diff --git a/arch/sparc/lib/bitext.c b/arch/sparc/lib/bitext.c
index 48d00e7..8ec4e9c 100644
--- a/arch/sparc/lib/bitext.c
+++ b/arch/sparc/lib/bitext.c
@@ -119,11 +119,7 @@
void bit_map_init(struct bit_map *t, unsigned long *map, int size)
{
-
- if ((size & 07) != 0)
- BUG();
- memset(map, 0, size>>3);
-
+ bitmap_zero(map, size);
memset(t, 0, sizeof *t);
spin_lock_init(&t->lock);
t->map = map;
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c
index 0f4f719..28f96f2 100644
--- a/arch/sparc/mm/iommu.c
+++ b/arch/sparc/mm/iommu.c
@@ -34,7 +34,7 @@
#define IOMMU_RNGE IOMMU_RNGE_256MB
#define IOMMU_START 0xF0000000
#define IOMMU_WINSIZE (256*1024*1024U)
-#define IOMMU_NPTES (IOMMU_WINSIZE/PAGE_SIZE) /* 64K PTEs, 265KB */
+#define IOMMU_NPTES (IOMMU_WINSIZE/PAGE_SIZE) /* 64K PTEs, 256KB */
#define IOMMU_ORDER 6 /* 4096 * (1<<6) */
/* srmmu.c */
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index c38bb72..036c279 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -280,7 +280,9 @@
SRMMU_NOCACHE_ALIGN_MAX, 0UL);
memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
- srmmu_nocache_bitmap = __alloc_bootmem(bitmap_bits >> 3, SMP_CACHE_BYTES, 0UL);
+ srmmu_nocache_bitmap =
+ __alloc_bootmem(BITS_TO_LONGS(bitmap_bits) * sizeof(long),
+ SMP_CACHE_BYTES, 0UL);
bit_map_init(&srmmu_nocache_map, srmmu_nocache_bitmap, bitmap_bits);
srmmu_swapper_pg_dir = __srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index ba6ae7f..83d89bc 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -24,11 +24,17 @@
void flush_tlb_pending(void)
{
struct tlb_batch *tb = &get_cpu_var(tlb_batch);
+ struct mm_struct *mm = tb->mm;
- if (tb->tlb_nr) {
- flush_tsb_user(tb);
+ if (!tb->tlb_nr)
+ goto out;
- if (CTX_VALID(tb->mm->context)) {
+ flush_tsb_user(tb);
+
+ if (CTX_VALID(mm->context)) {
+ if (tb->tlb_nr == 1) {
+ global_flush_tlb_page(mm, tb->vaddrs[0]);
+ } else {
#ifdef CONFIG_SMP
smp_flush_tlb_pending(tb->mm, tb->tlb_nr,
&tb->vaddrs[0]);
@@ -37,12 +43,30 @@
tb->tlb_nr, &tb->vaddrs[0]);
#endif
}
- tb->tlb_nr = 0;
}
+ tb->tlb_nr = 0;
+
+out:
put_cpu_var(tlb_batch);
}
+void arch_enter_lazy_mmu_mode(void)
+{
+ struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+ tb->active = 1;
+}
+
+void arch_leave_lazy_mmu_mode(void)
+{
+ struct tlb_batch *tb = &__get_cpu_var(tlb_batch);
+
+ if (tb->tlb_nr)
+ flush_tlb_pending();
+ tb->active = 0;
+}
+
static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
bool exec)
{
@@ -60,6 +84,12 @@
nr = 0;
}
+ if (!tb->active) {
+ global_flush_tlb_page(mm, vaddr);
+ flush_tsb_user_page(mm, vaddr);
+ goto out;
+ }
+
if (nr == 0)
tb->mm = mm;
@@ -68,6 +98,7 @@
if (nr >= TLB_BATCH_NR)
flush_tlb_pending();
+out:
put_cpu_var(tlb_batch);
}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index 428982b..2cc3bce 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -7,11 +7,10 @@
#include <linux/preempt.h>
#include <linux/slab.h>
#include <asm/page.h>
-#include <asm/tlbflush.h>
-#include <asm/tlb.h>
-#include <asm/mmu_context.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
#include <asm/tsb.h>
+#include <asm/tlb.h>
#include <asm/oplib.h>
extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES];
@@ -46,23 +45,27 @@
}
}
+static void __flush_tsb_one_entry(unsigned long tsb, unsigned long v,
+ unsigned long hash_shift,
+ unsigned long nentries)
+{
+ unsigned long tag, ent, hash;
+
+ v &= ~0x1UL;
+ hash = tsb_hash(v, hash_shift, nentries);
+ ent = tsb + (hash * sizeof(struct tsb));
+ tag = (v >> 22UL);
+
+ tsb_flush(ent, tag);
+}
+
static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift,
unsigned long tsb, unsigned long nentries)
{
unsigned long i;
- for (i = 0; i < tb->tlb_nr; i++) {
- unsigned long v = tb->vaddrs[i];
- unsigned long tag, ent, hash;
-
- v &= ~0x1UL;
-
- hash = tsb_hash(v, hash_shift, nentries);
- ent = tsb + (hash * sizeof(struct tsb));
- tag = (v >> 22UL);
-
- tsb_flush(ent, tag);
- }
+ for (i = 0; i < tb->tlb_nr; i++)
+ __flush_tsb_one_entry(tsb, tb->vaddrs[i], hash_shift, nentries);
}
void flush_tsb_user(struct tlb_batch *tb)
@@ -90,6 +93,30 @@
spin_unlock_irqrestore(&mm->context.lock, flags);
}
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+{
+ unsigned long nentries, base, flags;
+
+ spin_lock_irqsave(&mm->context.lock, flags);
+
+ base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+ nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+ if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+ base = __pa(base);
+ __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+
+#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
+ if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+ base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
+ nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
+ if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+ base = __pa(base);
+ __flush_tsb_one_entry(base, vaddr, HPAGE_SHIFT, nentries);
+ }
+#endif
+ spin_unlock_irqrestore(&mm->context.lock, flags);
+}
+
#define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_8K
#define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_8K
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index f8e13d4..432aa0c 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -53,6 +53,33 @@
nop
.align 32
+ .globl __flush_tlb_page
+__flush_tlb_page: /* 22 insns */
+ /* %o0 = context, %o1 = vaddr */
+ rdpr %pstate, %g7
+ andn %g7, PSTATE_IE, %g2
+ wrpr %g2, %pstate
+ mov SECONDARY_CONTEXT, %o4
+ ldxa [%o4] ASI_DMMU, %g2
+ stxa %o0, [%o4] ASI_DMMU
+ andcc %o1, 1, %g0
+ andn %o1, 1, %o3
+ be,pn %icc, 1f
+ or %o3, 0x10, %o3
+ stxa %g0, [%o3] ASI_IMMU_DEMAP
+1: stxa %g0, [%o3] ASI_DMMU_DEMAP
+ membar #Sync
+ stxa %g2, [%o4] ASI_DMMU
+ sethi %hi(KERNBASE), %o4
+ flush %o4
+ retl
+ wrpr %g7, 0x0, %pstate
+ nop
+ nop
+ nop
+ nop
+
+ .align 32
.globl __flush_tlb_pending
__flush_tlb_pending: /* 26 insns */
/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
@@ -203,6 +230,31 @@
retl
wrpr %g7, 0x0, %pstate
+__cheetah_flush_tlb_page: /* 22 insns */
+ /* %o0 = context, %o1 = vaddr */
+ rdpr %pstate, %g7
+ andn %g7, PSTATE_IE, %g2
+ wrpr %g2, 0x0, %pstate
+ wrpr %g0, 1, %tl
+ mov PRIMARY_CONTEXT, %o4
+ ldxa [%o4] ASI_DMMU, %g2
+ srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o3
+ sllx %o3, CTX_PGSZ1_NUC_SHIFT, %o3
+ or %o0, %o3, %o0 /* Preserve nucleus page size fields */
+ stxa %o0, [%o4] ASI_DMMU
+ andcc %o1, 1, %g0
+ be,pn %icc, 1f
+ andn %o1, 1, %o3
+ stxa %g0, [%o3] ASI_IMMU_DEMAP
+1: stxa %g0, [%o3] ASI_DMMU_DEMAP
+ membar #Sync
+ stxa %g2, [%o4] ASI_DMMU
+ sethi %hi(KERNBASE), %o4
+ flush %o4
+ wrpr %g0, 0, %tl
+ retl
+ wrpr %g7, 0x0, %pstate
+
__cheetah_flush_tlb_pending: /* 27 insns */
/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
rdpr %pstate, %g7
@@ -269,6 +321,20 @@
retl
nop
+__hypervisor_flush_tlb_page: /* 11 insns */
+ /* %o0 = context, %o1 = vaddr */
+ mov %o0, %g2
+ mov %o1, %o0 /* ARG0: vaddr + IMMU-bit */
+ mov %g2, %o1 /* ARG1: mmu context */
+ mov HV_MMU_ALL, %o2 /* ARG2: flags */
+ srlx %o0, PAGE_SHIFT, %o0
+ sllx %o0, PAGE_SHIFT, %o0
+ ta HV_MMU_UNMAP_ADDR_TRAP
+ brnz,pn %o0, __hypervisor_tlb_tl0_error
+ mov HV_MMU_UNMAP_ADDR_TRAP, %o1
+ retl
+ nop
+
__hypervisor_flush_tlb_pending: /* 16 insns */
/* %o0 = context, %o1 = nr, %o2 = vaddrs[] */
sllx %o1, 3, %g1
@@ -339,6 +405,13 @@
call tlb_patch_one
mov 19, %o2
+ sethi %hi(__flush_tlb_page), %o0
+ or %o0, %lo(__flush_tlb_page), %o0
+ sethi %hi(__cheetah_flush_tlb_page), %o1
+ or %o1, %lo(__cheetah_flush_tlb_page), %o1
+ call tlb_patch_one
+ mov 22, %o2
+
sethi %hi(__flush_tlb_pending), %o0
or %o0, %lo(__flush_tlb_pending), %o0
sethi %hi(__cheetah_flush_tlb_pending), %o1
@@ -397,10 +470,9 @@
nop
nop
- .globl xcall_flush_tlb_pending
-xcall_flush_tlb_pending: /* 21 insns */
- /* %g5=context, %g1=nr, %g7=vaddrs[] */
- sllx %g1, 3, %g1
+ .globl xcall_flush_tlb_page
+xcall_flush_tlb_page: /* 17 insns */
+ /* %g5=context, %g1=vaddr */
mov PRIMARY_CONTEXT, %g4
ldxa [%g4] ASI_DMMU, %g2
srlx %g2, CTX_PGSZ1_NUC_SHIFT, %g4
@@ -408,20 +480,16 @@
or %g5, %g4, %g5
mov PRIMARY_CONTEXT, %g4
stxa %g5, [%g4] ASI_DMMU
-1: sub %g1, (1 << 3), %g1
- ldx [%g7 + %g1], %g5
- andcc %g5, 0x1, %g0
+ andcc %g1, 0x1, %g0
be,pn %icc, 2f
-
- andn %g5, 0x1, %g5
+ andn %g1, 0x1, %g5
stxa %g0, [%g5] ASI_IMMU_DEMAP
2: stxa %g0, [%g5] ASI_DMMU_DEMAP
membar #Sync
- brnz,pt %g1, 1b
- nop
stxa %g2, [%g4] ASI_DMMU
retry
nop
+ nop
.globl xcall_flush_tlb_kernel_range
xcall_flush_tlb_kernel_range: /* 25 insns */
@@ -656,15 +724,13 @@
membar #Sync
retry
- .globl __hypervisor_xcall_flush_tlb_pending
-__hypervisor_xcall_flush_tlb_pending: /* 21 insns */
- /* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */
- sllx %g1, 3, %g1
+ .globl __hypervisor_xcall_flush_tlb_page
+__hypervisor_xcall_flush_tlb_page: /* 17 insns */
+ /* %g5=ctx, %g1=vaddr */
mov %o0, %g2
mov %o1, %g3
mov %o2, %g4
-1: sub %g1, (1 << 3), %g1
- ldx [%g7 + %g1], %o0 /* ARG0: virtual address */
+ mov %g1, %o0 /* ARG0: virtual address */
mov %g5, %o1 /* ARG1: mmu context */
mov HV_MMU_ALL, %o2 /* ARG2: flags */
srlx %o0, PAGE_SHIFT, %o0
@@ -673,8 +739,6 @@
mov HV_MMU_UNMAP_ADDR_TRAP, %g6
brnz,a,pn %o0, __hypervisor_tlb_xcall_error
mov %o0, %g5
- brnz,pt %g1, 1b
- nop
mov %g2, %o0
mov %g3, %o1
mov %g4, %o2
@@ -757,6 +821,13 @@
call tlb_patch_one
mov 10, %o2
+ sethi %hi(__flush_tlb_page), %o0
+ or %o0, %lo(__flush_tlb_page), %o0
+ sethi %hi(__hypervisor_flush_tlb_page), %o1
+ or %o1, %lo(__hypervisor_flush_tlb_page), %o1
+ call tlb_patch_one
+ mov 11, %o2
+
sethi %hi(__flush_tlb_pending), %o0
or %o0, %lo(__flush_tlb_pending), %o0
sethi %hi(__hypervisor_flush_tlb_pending), %o1
@@ -788,12 +859,12 @@
call tlb_patch_one
mov 21, %o2
- sethi %hi(xcall_flush_tlb_pending), %o0
- or %o0, %lo(xcall_flush_tlb_pending), %o0
- sethi %hi(__hypervisor_xcall_flush_tlb_pending), %o1
- or %o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1
+ sethi %hi(xcall_flush_tlb_page), %o0
+ or %o0, %lo(xcall_flush_tlb_page), %o0
+ sethi %hi(__hypervisor_xcall_flush_tlb_page), %o1
+ or %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1
call tlb_patch_one
- mov 21, %o2
+ mov 17, %o2
sethi %hi(xcall_flush_tlb_kernel_range), %o0
or %o0, %lo(xcall_flush_tlb_kernel_range), %o0
diff --git a/arch/tile/include/asm/irqflags.h b/arch/tile/include/asm/irqflags.h
index 241c0bb..c96f9bb 100644
--- a/arch/tile/include/asm/irqflags.h
+++ b/arch/tile/include/asm/irqflags.h
@@ -40,7 +40,15 @@
#include <asm/percpu.h>
#include <arch/spr_def.h>
-/* Set and clear kernel interrupt masks. */
+/*
+ * Set and clear kernel interrupt masks.
+ *
+ * NOTE: __insn_mtspr() is a compiler builtin marked as a memory
+ * clobber. We rely on it being equivalent to a compiler barrier in
+ * this code since arch_local_irq_save() and friends must act as
+ * compiler barriers. This compiler semantic is baked into enough
+ * places that the compiler will maintain it going forward.
+ */
#if CHIP_HAS_SPLIT_INTR_MASK()
#if INT_PERF_COUNT < 32 || INT_AUX_PERF_COUNT < 32 || INT_MEM_ERROR >= 32
# error Fix assumptions about which word various interrupts are in
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 70c0f3d..15b5cef 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1549,6 +1549,7 @@
config EFI
bool "EFI runtime service support"
depends on ACPI
+ select UCS2_STRING
---help---
This enables the kernel to use EFI runtime services that are
available (such as the EFI variable services).
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c205035..35ee62f 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -251,6 +251,51 @@
*size = len;
}
+static efi_status_t setup_efi_vars(struct boot_params *params)
+{
+ struct setup_data *data;
+ struct efi_var_bootdata *efidata;
+ u64 store_size, remaining_size, var_size;
+ efi_status_t status;
+
+ if (sys_table->runtime->hdr.revision < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
+
+ while (data && data->next)
+ data = (struct setup_data *)(unsigned long)data->next;
+
+ status = efi_call_phys4((void *)sys_table->runtime->query_variable_info,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS, &store_size,
+ &remaining_size, &var_size);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ status = efi_call_phys3(sys_table->boottime->allocate_pool,
+ EFI_LOADER_DATA, sizeof(*efidata), &efidata);
+
+ if (status != EFI_SUCCESS)
+ return status;
+
+ efidata->data.type = SETUP_EFI_VARS;
+ efidata->data.len = sizeof(struct efi_var_bootdata) -
+ sizeof(struct setup_data);
+ efidata->data.next = 0;
+ efidata->store_size = store_size;
+ efidata->remaining_size = remaining_size;
+ efidata->max_var_size = var_size;
+
+ if (data)
+ data->next = (unsigned long)efidata;
+ else
+ params->hdr.setup_data = (unsigned long)efidata;
+
+}
+
static efi_status_t setup_efi_pci(struct boot_params *params)
{
efi_pci_io_protocol *pci;
@@ -1157,6 +1202,8 @@
setup_graphics(boot_params);
+ setup_efi_vars(boot_params);
+
setup_efi_pci(boot_params);
status = efi_call_phys3(sys_table->boottime->allocate_pool,
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 60c89f3..2fb5d58 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -102,6 +102,13 @@
extern void efi_unmap_memmap(void);
extern void efi_memory_uc(u64 addr, unsigned long size);
+struct efi_var_bootdata {
+ struct setup_data data;
+ u64 store_size;
+ u64 remaining_size;
+ u64 max_var_size;
+};
+
#ifdef CONFIG_EFI
static inline bool efi_is_native(void)
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 5edd174..7361e47 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -703,7 +703,10 @@
PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave);
}
-void arch_flush_lazy_mmu_mode(void);
+static inline void arch_flush_lazy_mmu_mode(void)
+{
+ PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush);
+}
static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx,
phys_addr_t phys, pgprot_t flags)
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 142236e..b3b0ec1 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -91,6 +91,7 @@
/* Set deferred update mode, used for batching operations. */
void (*enter)(void);
void (*leave)(void);
+ void (*flush)(void);
};
struct pv_time_ops {
@@ -679,6 +680,7 @@
void paravirt_enter_lazy_mmu(void);
void paravirt_leave_lazy_mmu(void);
+void paravirt_flush_lazy_mmu(void);
void _paravirt_nop(void);
u32 _paravirt_ident_32(u32);
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 4fef2077..c779730 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -7,7 +7,7 @@
#define tlb_flush(tlb) \
{ \
- if (tlb->fullmm == 0) \
+ if (!tlb->fullmm && !tlb->need_flush_all) \
flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end, 0UL); \
else \
flush_tlb_mm_range(tlb->mm, 0UL, TLB_FLUSH_ALL, 0UL); \
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c15ddaf..0874424 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -6,6 +6,7 @@
#define SETUP_E820_EXT 1
#define SETUP_DTB 2
#define SETUP_PCI 3
+#define SETUP_EFI_VARS 4
/* ram_size flags */
#define RAMDISK_IMAGE_START_MASK 0x07FF
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index a7d26d8..8f4be53 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -35,13 +35,6 @@
if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
return false;
- /*
- * Xen emulates Hyper-V to support enlightened Windows.
- * Check to see first if we are on a Xen Hypervisor.
- */
- if (xen_cpuid_base())
- return false;
-
cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
&eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
@@ -82,12 +75,6 @@
if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE)
clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100);
-#if IS_ENABLED(CONFIG_HYPERV)
- /*
- * Setup the IDT for hypervisor callback.
- */
- alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
-#endif
}
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
@@ -103,6 +90,11 @@
void hv_register_vmbus_handler(int irq, irq_handler_t handler)
{
+ /*
+ * Setup the IDT for hypervisor callback.
+ */
+ alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector);
+
vmbus_irq = irq;
vmbus_isr = handler;
}
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index dab7580..cc45deb 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -153,8 +153,14 @@
};
static struct extra_reg intel_snb_extra_regs[] __read_mostly = {
- INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0),
- INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1),
+ INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0),
+ INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1),
+ EVENT_EXTRA_END
+};
+
+static struct extra_reg intel_snbep_extra_regs[] __read_mostly = {
+ INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0),
+ INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1),
EVENT_EXTRA_END
};
@@ -2097,7 +2103,10 @@
x86_pmu.event_constraints = intel_snb_event_constraints;
x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints;
x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
- x86_pmu.extra_regs = intel_snb_extra_regs;
+ if (boot_cpu_data.x86_model == 45)
+ x86_pmu.extra_regs = intel_snbep_extra_regs;
+ else
+ x86_pmu.extra_regs = intel_snb_extra_regs;
/* all extra regs are per-cpu when HT is on */
x86_pmu.er_flags |= ERF_HAS_RSP_1;
x86_pmu.er_flags |= ERF_NO_HT_SHARING;
@@ -2123,7 +2132,10 @@
x86_pmu.event_constraints = intel_ivb_event_constraints;
x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
- x86_pmu.extra_regs = intel_snb_extra_regs;
+ if (boot_cpu_data.x86_model == 62)
+ x86_pmu.extra_regs = intel_snbep_extra_regs;
+ else
+ x86_pmu.extra_regs = intel_snb_extra_regs;
/* all extra regs are per-cpu when HT is on */
x86_pmu.er_flags |= ERF_HAS_RSP_1;
x86_pmu.er_flags |= ERF_NO_HT_SHARING;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index b05a575..26830f3 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -314,10 +314,11 @@
if (top <= at)
return 0;
+ memset(®s, 0, sizeof(regs));
+
ds->bts_index = ds->bts_buffer_base;
perf_sample_data_init(&data, 0, event->hw.last_period);
- regs.ip = 0;
/*
* Prepare a generic sample, i.e. fill in the invariant fields.
diff --git a/arch/x86/kernel/microcode_core_early.c b/arch/x86/kernel/microcode_core_early.c
index 577db84..833d51d 100644
--- a/arch/x86/kernel/microcode_core_early.c
+++ b/arch/x86/kernel/microcode_core_early.c
@@ -45,9 +45,6 @@
u32 eax = 0x00000000;
u32 ebx, ecx = 0, edx;
- if (!have_cpuid_p())
- return X86_VENDOR_UNKNOWN;
-
native_cpuid(&eax, &ebx, &ecx, &edx);
if (CPUID_IS(CPUID_INTEL1, CPUID_INTEL2, CPUID_INTEL3, ebx, ecx, edx))
@@ -59,18 +56,45 @@
return X86_VENDOR_UNKNOWN;
}
+static int __cpuinit x86_family(void)
+{
+ u32 eax = 0x00000001;
+ u32 ebx, ecx = 0, edx;
+ int x86;
+
+ native_cpuid(&eax, &ebx, &ecx, &edx);
+
+ x86 = (eax >> 8) & 0xf;
+ if (x86 == 15)
+ x86 += (eax >> 20) & 0xff;
+
+ return x86;
+}
+
void __init load_ucode_bsp(void)
{
- int vendor = x86_vendor();
+ int vendor, x86;
- if (vendor == X86_VENDOR_INTEL)
+ if (!have_cpuid_p())
+ return;
+
+ vendor = x86_vendor();
+ x86 = x86_family();
+
+ if (vendor == X86_VENDOR_INTEL && x86 >= 6)
load_ucode_intel_bsp();
}
void __cpuinit load_ucode_ap(void)
{
- int vendor = x86_vendor();
+ int vendor, x86;
- if (vendor == X86_VENDOR_INTEL)
+ if (!have_cpuid_p())
+ return;
+
+ vendor = x86_vendor();
+ x86 = x86_family();
+
+ if (vendor == X86_VENDOR_INTEL && x86 >= 6)
load_ucode_intel_ap();
}
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 17fff18..8bfb335 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -263,6 +263,18 @@
leave_lazy(PARAVIRT_LAZY_MMU);
}
+void paravirt_flush_lazy_mmu(void)
+{
+ preempt_disable();
+
+ if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
+ arch_leave_lazy_mmu_mode();
+ arch_enter_lazy_mmu_mode();
+ }
+
+ preempt_enable();
+}
+
void paravirt_start_context_switch(struct task_struct *prev)
{
BUG_ON(preemptible());
@@ -292,18 +304,6 @@
return this_cpu_read(paravirt_lazy_mode);
}
-void arch_flush_lazy_mmu_mode(void)
-{
- preempt_disable();
-
- if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
- arch_leave_lazy_mmu_mode();
- arch_enter_lazy_mmu_mode();
- }
-
- preempt_enable();
-}
-
struct pv_info pv_info = {
.name = "bare hardware",
.paravirt_enabled = 0,
@@ -475,6 +475,7 @@
.lazy_mode = {
.enter = paravirt_nop,
.leave = paravirt_nop,
+ .flush = paravirt_nop,
},
.set_fixmap = native_set_fixmap,
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 90d8cc9..fae9134 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -507,11 +507,14 @@
/*
* Keep the crash kernel below this limit. On 32 bits earlier kernels
* would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64bit, old kexec-tools need to under 896MiB.
*/
#ifdef CONFIG_X86_32
-# define CRASH_KERNEL_ADDR_MAX (512 << 20)
+# define CRASH_KERNEL_ADDR_LOW_MAX (512 << 20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX (512 << 20)
#else
-# define CRASH_KERNEL_ADDR_MAX MAXMEM
+# define CRASH_KERNEL_ADDR_LOW_MAX (896UL<<20)
+# define CRASH_KERNEL_ADDR_HIGH_MAX MAXMEM
#endif
static void __init reserve_crashkernel_low(void)
@@ -521,19 +524,35 @@
unsigned long long low_base = 0, low_size = 0;
unsigned long total_low_mem;
unsigned long long base;
+ bool auto_set = false;
int ret;
total_low_mem = memblock_mem_size(1UL<<(32-PAGE_SHIFT));
+ /* crashkernel=Y,low */
ret = parse_crashkernel_low(boot_command_line, total_low_mem,
&low_size, &base);
- if (ret != 0 || low_size <= 0)
- return;
+ if (ret != 0) {
+ /*
+ * two parts from lib/swiotlb.c:
+ * swiotlb size: user specified with swiotlb= or default.
+ * swiotlb overflow buffer: now is hardcoded to 32k.
+ * We round it to 8M for other buffers that
+ * may need to stay low too.
+ */
+ low_size = swiotlb_size_or_default() + (8UL<<20);
+ auto_set = true;
+ } else {
+ /* passed with crashkernel=0,low ? */
+ if (!low_size)
+ return;
+ }
low_base = memblock_find_in_range(low_size, (1ULL<<32),
low_size, alignment);
if (!low_base) {
- pr_info("crashkernel low reservation failed - No suitable area found.\n");
+ if (!auto_set)
+ pr_info("crashkernel low reservation failed - No suitable area found.\n");
return;
}
@@ -554,14 +573,22 @@
const unsigned long long alignment = 16<<20; /* 16M */
unsigned long long total_mem;
unsigned long long crash_size, crash_base;
+ bool high = false;
int ret;
total_mem = memblock_phys_mem_size();
+ /* crashkernel=XM */
ret = parse_crashkernel(boot_command_line, total_mem,
&crash_size, &crash_base);
- if (ret != 0 || crash_size <= 0)
- return;
+ if (ret != 0 || crash_size <= 0) {
+ /* crashkernel=X,high */
+ ret = parse_crashkernel_high(boot_command_line, total_mem,
+ &crash_size, &crash_base);
+ if (ret != 0 || crash_size <= 0)
+ return;
+ high = true;
+ }
/* 0 means: find the address automatically */
if (crash_base <= 0) {
@@ -569,7 +596,9 @@
* kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
*/
crash_base = memblock_find_in_range(alignment,
- CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
+ high ? CRASH_KERNEL_ADDR_HIGH_MAX :
+ CRASH_KERNEL_ADDR_LOW_MAX,
+ crash_size, alignment);
if (!crash_base) {
pr_info("crashkernel reservation failed - No suitable area found.\n");
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index 1cbd89c..7114c63 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1334,6 +1334,7 @@
pv_mmu_ops.read_cr3 = lguest_read_cr3;
pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu;
pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode;
+ pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu;
pv_mmu_ops.pte_update = lguest_pte_update;
pv_mmu_ops.pte_update_defer = lguest_pte_update;
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 2b97525..0e88336 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -378,10 +378,12 @@
if (pgd_none(*pgd_ref))
return -1;
- if (pgd_none(*pgd))
+ if (pgd_none(*pgd)) {
set_pgd(pgd, *pgd_ref);
- else
+ arch_flush_lazy_mmu_mode();
+ } else {
BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ }
/*
* Below here mismatches are bugs because these lower tables
diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
index b008656..0e38951 100644
--- a/arch/x86/mm/pageattr-test.c
+++ b/arch/x86/mm/pageattr-test.c
@@ -68,7 +68,7 @@
s->gpg++;
i += GPS/PAGE_SIZE;
} else if (level == PG_LEVEL_2M) {
- if (!(pte_val(*pte) & _PAGE_PSE)) {
+ if ((pte_val(*pte) & _PAGE_PRESENT) && !(pte_val(*pte) & _PAGE_PSE)) {
printk(KERN_ERR
"%lx level %d but not PSE %Lx\n",
addr, level, (u64)pte_val(*pte));
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 091934e..fb4e73e 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -467,7 +467,7 @@
* We are safe now. Check whether the new pgprot is the same:
*/
old_pte = *kpte;
- old_prot = new_prot = req_prot = pte_pgprot(old_pte);
+ old_prot = req_prot = pte_pgprot(old_pte);
pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr);
pgprot_val(req_prot) |= pgprot_val(cpa->mask_set);
@@ -478,12 +478,12 @@
* a non present pmd. The canon_pgprot will clear _PAGE_GLOBAL
* for the ancient hardware that doesn't support it.
*/
- if (pgprot_val(new_prot) & _PAGE_PRESENT)
- pgprot_val(new_prot) |= _PAGE_PSE | _PAGE_GLOBAL;
+ if (pgprot_val(req_prot) & _PAGE_PRESENT)
+ pgprot_val(req_prot) |= _PAGE_PSE | _PAGE_GLOBAL;
else
- pgprot_val(new_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL);
+ pgprot_val(req_prot) &= ~(_PAGE_PSE | _PAGE_GLOBAL);
- new_prot = canon_pgprot(new_prot);
+ req_prot = canon_pgprot(req_prot);
/*
* old_pte points to the large page base address. So we need
@@ -1413,6 +1413,8 @@
* but that can deadlock->flush only current cpu:
*/
__flush_tlb_all();
+
+ arch_flush_lazy_mmu_mode();
}
#ifdef CONFIG_HIBERNATION
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 193350b..17fda6a 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -58,6 +58,13 @@
void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
{
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
+ /*
+ * NOTE! For PAE, any changes to the top page-directory-pointer-table
+ * entries need a full cr3 reload to flush.
+ */
+#ifdef CONFIG_X86_PAE
+ tlb->need_flush_all = 1;
+#endif
tlb_remove_page(tlb, virt_to_page(pmd));
}
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 901177d..305c68b 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -6,6 +6,7 @@
#include <linux/sched.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/dmi.h>
@@ -170,6 +171,16 @@
pcibios_fixup_device_resources(dev);
}
+void pcibios_add_bus(struct pci_bus *bus)
+{
+ acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+ acpi_pci_remove_bus(bus);
+}
+
/*
* Only use DMI information to set this if nothing was passed
* on the kernel command line (which was parsed earlier).
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 94e7662..4a9be6d 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -177,7 +177,7 @@
goto error;
i = 0;
list_for_each_entry(msidesc, &dev->msi_list, list) {
- irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+ irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i],
(type == PCI_CAP_ID_MSIX) ?
"pcifront-msi-x" :
"pcifront-msi",
@@ -244,7 +244,7 @@
dev_dbg(&dev->dev,
"xen: msi already bound to pirq=%d\n", pirq);
}
- irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
+ irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq,
(type == PCI_CAP_ID_MSIX) ?
"msi-x" : "msi",
DOMID_SELF);
@@ -326,7 +326,7 @@
}
ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
- map_irq.pirq, map_irq.index,
+ map_irq.pirq,
(type == PCI_CAP_ID_MSIX) ?
"msi-x" : "msi",
domid);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 5f2ecaf..e4a86a6 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -41,6 +41,7 @@
#include <linux/io.h>
#include <linux/reboot.h>
#include <linux/bcd.h>
+#include <linux/ucs2_string.h>
#include <asm/setup.h>
#include <asm/efi.h>
@@ -51,6 +52,13 @@
#define EFI_DEBUG 1
+/*
+ * There's some additional metadata associated with each
+ * variable. Intel's reference implementation is 60 bytes - bump that
+ * to account for potential alignment constraints
+ */
+#define VAR_METADATA_SIZE 64
+
struct efi __read_mostly efi = {
.mps = EFI_INVALID_TABLE_ADDR,
.acpi = EFI_INVALID_TABLE_ADDR,
@@ -69,6 +77,13 @@
static struct efi efi_phys __initdata;
static efi_system_table_t efi_systab __initdata;
+static u64 efi_var_store_size;
+static u64 efi_var_remaining_size;
+static u64 efi_var_max_var_size;
+static u64 boot_used_size;
+static u64 boot_var_size;
+static u64 active_size;
+
unsigned long x86_efi_facility;
/*
@@ -98,6 +113,15 @@
}
early_param("add_efi_memmap", setup_add_efi_memmap);
+static bool efi_no_storage_paranoia;
+
+static int __init setup_storage_paranoia(char *arg)
+{
+ efi_no_storage_paranoia = true;
+ return 0;
+}
+early_param("efi_no_storage_paranoia", setup_storage_paranoia);
+
static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{
@@ -162,8 +186,53 @@
efi_char16_t *name,
efi_guid_t *vendor)
{
- return efi_call_virt3(get_next_variable,
- name_size, name, vendor);
+ efi_status_t status;
+ static bool finished = false;
+ static u64 var_size;
+
+ status = efi_call_virt3(get_next_variable,
+ name_size, name, vendor);
+
+ if (status == EFI_NOT_FOUND) {
+ finished = true;
+ if (var_size < boot_used_size) {
+ boot_var_size = boot_used_size - var_size;
+ active_size += boot_var_size;
+ } else {
+ printk(KERN_WARNING FW_BUG "efi: Inconsistent initial sizes\n");
+ }
+ }
+
+ if (boot_used_size && !finished) {
+ unsigned long size;
+ u32 attr;
+ efi_status_t s;
+ void *tmp;
+
+ s = virt_efi_get_variable(name, vendor, &attr, &size, NULL);
+
+ if (s != EFI_BUFFER_TOO_SMALL || !size)
+ return status;
+
+ tmp = kmalloc(size, GFP_ATOMIC);
+
+ if (!tmp)
+ return status;
+
+ s = virt_efi_get_variable(name, vendor, &attr, &size, tmp);
+
+ if (s == EFI_SUCCESS && (attr & EFI_VARIABLE_NON_VOLATILE)) {
+ var_size += size;
+ var_size += ucs2_strsize(name, 1024);
+ active_size += size;
+ active_size += VAR_METADATA_SIZE;
+ active_size += ucs2_strsize(name, 1024);
+ }
+
+ kfree(tmp);
+ }
+
+ return status;
}
static efi_status_t virt_efi_set_variable(efi_char16_t *name,
@@ -172,9 +241,34 @@
unsigned long data_size,
void *data)
{
- return efi_call_virt5(set_variable,
- name, vendor, attr,
- data_size, data);
+ efi_status_t status;
+ u32 orig_attr = 0;
+ unsigned long orig_size = 0;
+
+ status = virt_efi_get_variable(name, vendor, &orig_attr, &orig_size,
+ NULL);
+
+ if (status != EFI_BUFFER_TOO_SMALL)
+ orig_size = 0;
+
+ status = efi_call_virt5(set_variable,
+ name, vendor, attr,
+ data_size, data);
+
+ if (status == EFI_SUCCESS) {
+ if (orig_size) {
+ active_size -= orig_size;
+ active_size -= ucs2_strsize(name, 1024);
+ active_size -= VAR_METADATA_SIZE;
+ }
+ if (data_size) {
+ active_size += data_size;
+ active_size += ucs2_strsize(name, 1024);
+ active_size += VAR_METADATA_SIZE;
+ }
+ }
+
+ return status;
}
static efi_status_t virt_efi_query_variable_info(u32 attr,
@@ -682,6 +776,9 @@
char vendor[100] = "unknown";
int i = 0;
void *tmp;
+ struct setup_data *data;
+ struct efi_var_bootdata *efi_var_data;
+ u64 pa_data;
#ifdef CONFIG_X86_32
if (boot_params.efi_info.efi_systab_hi ||
@@ -699,6 +796,22 @@
if (efi_systab_init(efi_phys.systab))
return;
+ pa_data = boot_params.hdr.setup_data;
+ while (pa_data) {
+ data = early_ioremap(pa_data, sizeof(*efi_var_data));
+ if (data->type == SETUP_EFI_VARS) {
+ efi_var_data = (struct efi_var_bootdata *)data;
+
+ efi_var_store_size = efi_var_data->store_size;
+ efi_var_remaining_size = efi_var_data->remaining_size;
+ efi_var_max_var_size = efi_var_data->max_var_size;
+ }
+ pa_data = data->next;
+ early_iounmap(data, sizeof(*efi_var_data));
+ }
+
+ boot_used_size = efi_var_store_size - efi_var_remaining_size;
+
set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
/*
@@ -999,3 +1112,48 @@
}
return 0;
}
+
+/*
+ * Some firmware has serious problems when using more than 50% of the EFI
+ * variable store, i.e. it triggers bugs that can brick machines. Ensure that
+ * we never use more than this safe limit.
+ *
+ * Return EFI_SUCCESS if it is safe to write 'size' bytes to the variable
+ * store.
+ */
+efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+ efi_status_t status;
+ u64 storage_size, remaining_size, max_size;
+
+ status = efi.query_variable_info(attributes, &storage_size,
+ &remaining_size, &max_size);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ if (!max_size && remaining_size > size)
+ printk_once(KERN_ERR FW_BUG "Broken EFI implementation"
+ " is returning MaxVariableSize=0\n");
+ /*
+ * Some firmware implementations refuse to boot if there's insufficient
+ * space in the variable store. We account for that by refusing the
+ * write if permitting it would reduce the available space to under
+ * 50%. However, some firmware won't reclaim variable space until
+ * after the used (not merely the actively used) space drops below
+ * a threshold. We can approximate that case with the value calculated
+ * above. If both the firmware and our calculations indicate that the
+ * available space would drop below 50%, refuse the write.
+ */
+
+ if (!storage_size || size > remaining_size ||
+ (max_size && size > max_size))
+ return EFI_OUT_OF_RESOURCES;
+
+ if (!efi_no_storage_paranoia &&
+ ((active_size + size + VAR_METADATA_SIZE > storage_size / 2) &&
+ (remaining_size - size < storage_size / 2)))
+ return EFI_OUT_OF_RESOURCES;
+
+ return EFI_SUCCESS;
+}
+EXPORT_SYMBOL_GPL(efi_query_variable_store);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c8e1c7b..ddbd54a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -31,6 +31,7 @@
#include <linux/pci.h>
#include <linux/gfp.h>
#include <linux/memblock.h>
+#include <linux/edd.h>
#include <xen/xen.h>
#include <xen/events.h>
@@ -1306,6 +1307,55 @@
.emergency_restart = xen_emergency_restart,
};
+static void __init xen_boot_params_init_edd(void)
+{
+#if IS_ENABLED(CONFIG_EDD)
+ struct xen_platform_op op;
+ struct edd_info *edd_info;
+ u32 *mbr_signature;
+ unsigned nr;
+ int ret;
+
+ edd_info = boot_params.eddbuf;
+ mbr_signature = boot_params.edd_mbr_sig_buffer;
+
+ op.cmd = XENPF_firmware_info;
+
+ op.u.firmware_info.type = XEN_FW_DISK_INFO;
+ for (nr = 0; nr < EDDMAXNR; nr++) {
+ struct edd_info *info = edd_info + nr;
+
+ op.u.firmware_info.index = nr;
+ info->params.length = sizeof(info->params);
+ set_xen_guest_handle(op.u.firmware_info.u.disk_info.edd_params,
+ &info->params);
+ ret = HYPERVISOR_dom0_op(&op);
+ if (ret)
+ break;
+
+#define C(x) info->x = op.u.firmware_info.u.disk_info.x
+ C(device);
+ C(version);
+ C(interface_support);
+ C(legacy_max_cylinder);
+ C(legacy_max_head);
+ C(legacy_sectors_per_track);
+#undef C
+ }
+ boot_params.eddbuf_entries = nr;
+
+ op.u.firmware_info.type = XEN_FW_DISK_MBR_SIGNATURE;
+ for (nr = 0; nr < EDD_MBR_SIG_MAX; nr++) {
+ op.u.firmware_info.index = nr;
+ ret = HYPERVISOR_dom0_op(&op);
+ if (ret)
+ break;
+ mbr_signature[nr] = op.u.firmware_info.u.disk_mbr_signature.mbr_signature;
+ }
+ boot_params.edd_mbr_sig_buf_entries = nr;
+#endif
+}
+
/*
* Set up the GDT and segment registers for -fstack-protector. Until
* we do this, we have to be careful not to call any stack-protected
@@ -1508,6 +1558,8 @@
/* Avoid searching for BIOS MP tables */
x86_init.mpparse.find_smp_config = x86_init_noop;
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
+
+ xen_boot_params_init_edd();
}
#ifdef CONFIG_PCI
/* PCI BIOS service won't work from a PV guest. */
@@ -1589,8 +1641,11 @@
switch (action) {
case CPU_UP_PREPARE:
xen_vcpu_setup(cpu);
- if (xen_have_vector_callback)
+ if (xen_have_vector_callback) {
xen_init_lock_cpu(cpu);
+ if (xen_feature(XENFEAT_hvm_safe_pvclock))
+ xen_setup_timer(cpu);
+ }
break;
default:
break;
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 6afbb2c..e006c18 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1748,14 +1748,18 @@
}
/* Set the page permissions on an identity-mapped pages */
-static void set_page_prot(void *addr, pgprot_t prot)
+static void set_page_prot_flags(void *addr, pgprot_t prot, unsigned long flags)
{
unsigned long pfn = __pa(addr) >> PAGE_SHIFT;
pte_t pte = pfn_pte(pfn, prot);
- if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, 0))
+ if (HYPERVISOR_update_va_mapping((unsigned long)addr, pte, flags))
BUG();
}
+static void set_page_prot(void *addr, pgprot_t prot)
+{
+ return set_page_prot_flags(addr, prot, UVMF_NONE);
+}
#ifdef CONFIG_X86_32
static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
{
@@ -1839,12 +1843,12 @@
unsigned long addr)
{
if (*pt_base == PFN_DOWN(__pa(addr))) {
- set_page_prot((void *)addr, PAGE_KERNEL);
+ set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
clear_page((void *)addr);
(*pt_base)++;
}
if (*pt_end == PFN_DOWN(__pa(addr))) {
- set_page_prot((void *)addr, PAGE_KERNEL);
+ set_page_prot_flags((void *)addr, PAGE_KERNEL, UVMF_INVLPG);
clear_page((void *)addr);
(*pt_end)--;
}
@@ -2196,6 +2200,7 @@
.lazy_mode = {
.enter = paravirt_enter_lazy_mmu,
.leave = xen_leave_lazy_mmu,
+ .flush = paravirt_flush_lazy_mmu,
},
.set_fixmap = xen_set_fixmap,
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 09ea61d..0d466d7 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -144,6 +144,13 @@
goto fail;
per_cpu(xen_callfuncsingle_irq, cpu) = rc;
+ /*
+ * The IRQ worker on PVHVM goes through the native path and uses the
+ * IPI mechanism.
+ */
+ if (xen_hvm_domain())
+ return 0;
+
callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
cpu,
@@ -167,6 +174,9 @@
if (per_cpu(xen_callfuncsingle_irq, cpu) >= 0)
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu),
NULL);
+ if (xen_hvm_domain())
+ return rc;
+
if (per_cpu(xen_irq_work, cpu) >= 0)
unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
@@ -418,7 +428,7 @@
static void xen_cpu_die(unsigned int cpu)
{
- while (HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
+ while (xen_pv_domain() && HYPERVISOR_vcpu_op(VCPUOP_is_up, cpu, NULL)) {
current->state = TASK_UNINTERRUPTIBLE;
schedule_timeout(HZ/10);
}
@@ -426,7 +436,8 @@
unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
- unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+ if (!xen_hvm_domain())
+ unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
xen_uninit_lock_cpu(cpu);
xen_teardown_timer(cpu);
}
@@ -657,11 +668,7 @@
static void xen_hvm_cpu_die(unsigned int cpu)
{
- unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
- unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
- unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
- unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
- unbind_from_irqhandler(per_cpu(xen_irq_work, cpu), NULL);
+ xen_cpu_die(cpu);
native_cpu_die(cpu);
}
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index f7a080e..8b54603 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -364,6 +364,16 @@
int irq;
const char *name;
+ WARN(per_cpu(lock_kicker_irq, cpu) > 0, "spinlock on CPU%d exists on IRQ%d!\n",
+ cpu, per_cpu(lock_kicker_irq, cpu));
+
+ /*
+ * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+ * (xen: disable PV spinlocks on HVM)
+ */
+ if (xen_hvm_domain())
+ return;
+
name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
cpu,
@@ -382,11 +392,26 @@
void xen_uninit_lock_cpu(int cpu)
{
+ /*
+ * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+ * (xen: disable PV spinlocks on HVM)
+ */
+ if (xen_hvm_domain())
+ return;
+
unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL);
+ per_cpu(lock_kicker_irq, cpu) = -1;
}
void __init xen_init_spinlocks(void)
{
+ /*
+ * See git commit f10cd522c5fbfec9ae3cc01967868c9c2401ed23
+ * (xen: disable PV spinlocks on HVM)
+ */
+ if (xen_hvm_domain())
+ return;
+
BUILD_BUG_ON(sizeof(struct xen_spinlock) > sizeof(arch_spinlock_t));
pv_lock_ops.spin_is_locked = xen_spin_is_locked;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index 0296a95..3d88bfd 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -377,7 +377,7 @@
static const struct clock_event_device *xen_clockevent =
&xen_timerop_clockevent;
-static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events);
+static DEFINE_PER_CPU(struct clock_event_device, xen_clock_events) = { .irq = -1 };
static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
{
@@ -401,6 +401,9 @@
struct clock_event_device *evt;
int irq;
+ evt = &per_cpu(xen_clock_events, cpu);
+ WARN(evt->irq >= 0, "IRQ%d for CPU%d is already allocated\n", evt->irq, cpu);
+
printk(KERN_INFO "installing Xen timer for CPU %d\n", cpu);
name = kasprintf(GFP_KERNEL, "timer%d", cpu);
@@ -413,7 +416,6 @@
IRQF_FORCE_RESUME,
name, NULL);
- evt = &per_cpu(xen_clock_events, cpu);
memcpy(evt, xen_clockevent, sizeof(*evt));
evt->cpumask = cpumask_of(cpu);
@@ -426,6 +428,7 @@
BUG_ON(cpu == 0);
evt = &per_cpu(xen_clock_events, cpu);
unbind_from_irqhandler(evt->irq, NULL);
+ evt->irq = -1;
}
void xen_setup_cpu_clockevents(void)
@@ -497,7 +500,11 @@
{
int cpu = smp_processor_id();
xen_setup_runstate_info(cpu);
- xen_setup_timer(cpu);
+ /*
+ * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence
+ * doing it xen_hvm_cpu_notify (which gets called by smp_init during
+ * early bootup and also during CPU hotplug events).
+ */
xen_setup_cpu_clockevents();
}
diff --git a/block/blk-core.c b/block/blk-core.c
index 074b758..7c28835 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -39,6 +39,7 @@
EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
DEFINE_IDA(blk_queue_ida);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 6206a93..5efc5a6 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -229,6 +229,8 @@
unsigned long val; \
ssize_t ret; \
ret = queue_var_store(&val, page, count); \
+ if (ret < 0) \
+ return ret; \
if (neg) \
val = !val; \
\
diff --git a/block/partition-generic.c b/block/partition-generic.c
index ae95ee6..789cdea 100644
--- a/block/partition-generic.c
+++ b/block/partition-generic.c
@@ -257,7 +257,6 @@
hd_struct_put(part);
}
-EXPORT_SYMBOL(delete_partition);
static ssize_t whole_disk_show(struct device *dev,
struct device_attribute *attr, char *buf)
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index ef5356c..0262210 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -161,6 +161,8 @@
else if (len < ds)
msg->msg_flags |= MSG_TRUNC;
+ msg->msg_namelen = 0;
+
lock_sock(sk);
if (ctx->more) {
ctx->more = 0;
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 6a6dfc0..a1c4f0a 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -432,6 +432,7 @@
long copied = 0;
lock_sock(sk);
+ msg->msg_namelen = 0;
for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
iovlen--, iov++) {
unsigned long seglen = iov->iov_len;
diff --git a/crypto/gcm.c b/crypto/gcm.c
index 137ad1e..13ccbda 100644
--- a/crypto/gcm.c
+++ b/crypto/gcm.c
@@ -44,6 +44,7 @@
struct crypto_rfc4543_req_ctx {
u8 auth_tag[16];
+ u8 assocbuf[32];
struct scatterlist cipher[1];
struct scatterlist payload[2];
struct scatterlist assoc[2];
@@ -1133,9 +1134,19 @@
scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2);
assoclen += 8 + req->cryptlen - (enc ? 0 : authsize);
- sg_init_table(assoc, 2);
- sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
- req->assoc->offset);
+ if (req->assoc->length == req->assoclen) {
+ sg_init_table(assoc, 2);
+ sg_set_page(assoc, sg_page(req->assoc), req->assoc->length,
+ req->assoc->offset);
+ } else {
+ BUG_ON(req->assoclen > sizeof(rctx->assocbuf));
+
+ scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0,
+ req->assoclen, 0);
+
+ sg_init_table(assoc, 2);
+ sg_set_buf(assoc, rctx->assocbuf, req->assoclen);
+ }
scatterwalk_crypto_chain(assoc, payload, 0, 2);
aead_request_set_tfm(subreq, ctx->child);
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 6ae5e44..ac8688b 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -65,44 +65,12 @@
.detach = acpi_pci_root_remove,
};
-/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
+/* Lock to protect both acpi_pci_roots lists */
static DEFINE_MUTEX(acpi_pci_root_lock);
static LIST_HEAD(acpi_pci_roots);
-static LIST_HEAD(acpi_pci_drivers);
static DEFINE_MUTEX(osc_lock);
-int acpi_pci_register_driver(struct acpi_pci_driver *driver)
-{
- int n = 0;
- struct acpi_pci_root *root;
-
- mutex_lock(&acpi_pci_root_lock);
- list_add_tail(&driver->node, &acpi_pci_drivers);
- if (driver->add)
- list_for_each_entry(root, &acpi_pci_roots, node) {
- driver->add(root);
- n++;
- }
- mutex_unlock(&acpi_pci_root_lock);
-
- return n;
-}
-EXPORT_SYMBOL(acpi_pci_register_driver);
-
-void acpi_pci_unregister_driver(struct acpi_pci_driver *driver)
-{
- struct acpi_pci_root *root;
-
- mutex_lock(&acpi_pci_root_lock);
- list_del(&driver->node);
- if (driver->remove)
- list_for_each_entry(root, &acpi_pci_roots, node)
- driver->remove(root);
- mutex_unlock(&acpi_pci_root_lock);
-}
-EXPORT_SYMBOL(acpi_pci_unregister_driver);
-
/**
* acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge
* @handle - the ACPI CA node in question.
@@ -413,7 +381,6 @@
acpi_status status;
int result;
struct acpi_pci_root *root;
- struct acpi_pci_driver *driver;
u32 flags, base_flags;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
@@ -571,12 +538,6 @@
pci_assign_unassigned_bus_resources(root->bus);
}
- mutex_lock(&acpi_pci_root_lock);
- list_for_each_entry(driver, &acpi_pci_drivers, node)
- if (driver->add)
- driver->add(root);
- mutex_unlock(&acpi_pci_root_lock);
-
/* need to after hot-added ioapic is registered */
if (system_state != SYSTEM_BOOTING)
pci_enable_bridges(root->bus);
@@ -597,16 +558,9 @@
static void acpi_pci_root_remove(struct acpi_device *device)
{
struct acpi_pci_root *root = acpi_driver_data(device);
- struct acpi_pci_driver *driver;
pci_stop_root_bus(root->bus);
- mutex_lock(&acpi_pci_root_lock);
- list_for_each_entry_reverse(driver, &acpi_pci_drivers, node)
- if (driver->remove)
- driver->remove(root);
- mutex_unlock(&acpi_pci_root_lock);
-
device_set_run_wake(root->bus->bridge, false);
pci_acpi_remove_bus_pm_notifier(device);
diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c
index cd1434e..033d117 100644
--- a/drivers/acpi/pci_slot.c
+++ b/drivers/acpi/pci_slot.c
@@ -9,6 +9,9 @@
* Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P.
* Alex Chiang <achiang@hp.com>
*
+ * Copyright (C) 2013 Huawei Tech. Co., Ltd.
+ * Jiang Liu <jiang.liu@huawei.com>
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
@@ -28,10 +31,9 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/list.h>
#include <linux/pci.h>
#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
#include <linux/dmi.h>
static bool debug;
@@ -61,20 +63,12 @@
#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */
struct acpi_pci_slot {
- acpi_handle root_handle; /* handle of the root bridge */
struct pci_slot *pci_slot; /* corresponding pci_slot */
struct list_head list; /* node in the list of slots */
};
-static int acpi_pci_slot_add(struct acpi_pci_root *root);
-static void acpi_pci_slot_remove(struct acpi_pci_root *root);
-
static LIST_HEAD(slot_list);
static DEFINE_MUTEX(slot_list_lock);
-static struct acpi_pci_driver acpi_pci_slot_driver = {
- .add = acpi_pci_slot_add,
- .remove = acpi_pci_slot_remove,
-};
static int
check_slot(acpi_handle handle, unsigned long long *sun)
@@ -113,21 +107,8 @@
return device;
}
-struct callback_args {
- acpi_walk_callback user_function; /* only for walk_p2p_bridge */
- struct pci_bus *pci_bus;
- acpi_handle root_handle;
-};
-
/*
- * register_slot
- *
- * Called once for each SxFy object in the namespace. Don't worry about
- * calling pci_create_slot multiple times for the same pci_bus:device,
- * since each subsequent call simply bumps the refcount on the pci_slot.
- *
- * The number of calls to pci_destroy_slot from unregister_slot is
- * symmetrical.
+ * Check whether handle has an associated slot and create PCI slot if it has.
*/
static acpi_status
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -137,13 +118,22 @@
char name[SLOT_NAME_SIZE];
struct acpi_pci_slot *slot;
struct pci_slot *pci_slot;
- struct callback_args *parent_context = context;
- struct pci_bus *pci_bus = parent_context->pci_bus;
+ struct pci_bus *pci_bus = context;
device = check_slot(handle, &sun);
if (device < 0)
return AE_OK;
+ /*
+ * There may be multiple PCI functions associated with the same slot.
+ * Check whether PCI slot has already been created for this PCI device.
+ */
+ list_for_each_entry(slot, &slot_list, list) {
+ pci_slot = slot->pci_slot;
+ if (pci_slot->bus == pci_bus && pci_slot->number == device)
+ return AE_OK;
+ }
+
slot = kmalloc(sizeof(*slot), GFP_KERNEL);
if (!slot) {
err("%s: cannot allocate memory\n", __func__);
@@ -158,12 +148,8 @@
return AE_OK;
}
- slot->root_handle = parent_context->root_handle;
slot->pci_slot = pci_slot;
- INIT_LIST_HEAD(&slot->list);
- mutex_lock(&slot_list_lock);
list_add(&slot->list, &slot_list);
- mutex_unlock(&slot_list_lock);
get_device(&pci_bus->dev);
@@ -173,131 +159,24 @@
return AE_OK;
}
-/*
- * walk_p2p_bridge - discover and walk p2p bridges
- * @handle: points to an acpi_pci_root
- * @context: p2p_bridge_context pointer
- *
- * Note that when we call ourselves recursively, we pass a different
- * value of pci_bus in the child_context.
- */
-static acpi_status
-walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
+void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle)
{
- int device, function;
- unsigned long long adr;
- acpi_status status;
- acpi_handle dummy_handle;
- acpi_walk_callback user_function;
-
- struct pci_dev *dev;
- struct pci_bus *pci_bus;
- struct callback_args child_context;
- struct callback_args *parent_context = context;
-
- pci_bus = parent_context->pci_bus;
- user_function = parent_context->user_function;
-
- status = acpi_get_handle(handle, "_ADR", &dummy_handle);
- if (ACPI_FAILURE(status))
- return AE_OK;
-
- status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
- if (ACPI_FAILURE(status))
- return AE_OK;
-
- device = (adr >> 16) & 0xffff;
- function = adr & 0xffff;
-
- dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));
- if (!dev || !dev->subordinate)
- goto out;
-
- child_context.pci_bus = dev->subordinate;
- child_context.user_function = user_function;
- child_context.root_handle = parent_context->root_handle;
-
- dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number);
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- user_function, NULL, &child_context, NULL);
- if (ACPI_FAILURE(status))
- goto out;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- walk_p2p_bridge, NULL, &child_context, NULL);
-out:
- pci_dev_put(dev);
- return AE_OK;
+ mutex_lock(&slot_list_lock);
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+ register_slot, NULL, bus, NULL);
+ mutex_unlock(&slot_list_lock);
}
-/*
- * walk_root_bridge - generic root bridge walker
- * @root: poiner of an acpi_pci_root
- * @user_function: user callback for slot objects
- *
- * Call user_function for all objects underneath this root bridge.
- * Walk p2p bridges underneath us and call user_function on those too.
- */
-static int
-walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function)
-{
- acpi_status status;
- acpi_handle handle = root->device->handle;
- struct pci_bus *pci_bus = root->bus;
- struct callback_args context;
-
- context.pci_bus = pci_bus;
- context.user_function = user_function;
- context.root_handle = handle;
-
- dbg("root bridge walk, pci_bus = %x\n", pci_bus->number);
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- user_function, NULL, &context, NULL);
- if (ACPI_FAILURE(status))
- return status;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- walk_p2p_bridge, NULL, &context, NULL);
- if (ACPI_FAILURE(status))
- err("%s: walk_p2p_bridge failure - %d\n", __func__, status);
-
- return status;
-}
-
-/*
- * acpi_pci_slot_add
- * @handle: points to an acpi_pci_root
- */
-static int
-acpi_pci_slot_add(struct acpi_pci_root *root)
-{
- acpi_status status;
-
- status = walk_root_bridge(root, register_slot);
- if (ACPI_FAILURE(status))
- err("%s: register_slot failure - %d\n", __func__, status);
-
- return status;
-}
-
-/*
- * acpi_pci_slot_remove
- * @handle: points to an acpi_pci_root
- */
-static void
-acpi_pci_slot_remove(struct acpi_pci_root *root)
+void acpi_pci_slot_remove(struct pci_bus *bus)
{
struct acpi_pci_slot *slot, *tmp;
- struct pci_bus *pbus;
- acpi_handle handle = root->device->handle;
mutex_lock(&slot_list_lock);
list_for_each_entry_safe(slot, tmp, &slot_list, list) {
- if (slot->root_handle == handle) {
+ if (slot->pci_slot->bus == bus) {
list_del(&slot->list);
- pbus = slot->pci_slot->bus;
pci_destroy_slot(slot->pci_slot);
- put_device(&pbus->dev);
+ put_device(&bus->dev);
kfree(slot);
}
}
@@ -332,5 +211,4 @@
void __init acpi_pci_slot_init(void)
{
dmi_check_system(acpi_pci_slot_dmi_table);
- acpi_pci_register_driver(&acpi_pci_slot_driver);
}
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5e7e991..f54d198 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1790,7 +1790,6 @@
acpi_platform_init();
acpi_csrt_init();
acpi_container_init();
- acpi_pci_slot_init();
mutex_lock(&acpi_scan_lock);
/*
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6a67b07..251e57d 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -415,17 +415,17 @@
/* Marvell */
{ PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */
{ PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */
- { PCI_DEVICE(0x1b4b, 0x9123),
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123),
.class = PCI_CLASS_STORAGE_SATA_AHCI,
.class_mask = 0xffffff,
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
- { PCI_DEVICE(0x1b4b, 0x9125),
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125),
.driver_data = board_ahci_yes_fbs }, /* 88se9125 */
- { PCI_DEVICE(0x1b4b, 0x917a),
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
.driver_data = board_ahci_yes_fbs }, /* 88se9172 */
- { PCI_DEVICE(0x1b4b, 0x9192),
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
.driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */
- { PCI_DEVICE(0x1b4b, 0x91a3),
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3),
.driver_data = board_ahci_yes_fbs },
/* Promise */
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ffdd32d..2f48123 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -150,6 +150,7 @@
tolapai_sata,
piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */
ich8_sata_snb,
+ ich8_2port_sata_snb,
};
struct piix_map_db {
@@ -304,7 +305,7 @@
/* SATA Controller IDE (Lynx Point) */
{ 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
/* SATA Controller IDE (Lynx Point) */
- { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+ { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
/* SATA Controller IDE (Lynx Point) */
{ 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
/* SATA Controller IDE (Lynx Point-LP) */
@@ -439,6 +440,7 @@
[ich8m_apple_sata] = &ich8m_apple_map_db,
[tolapai_sata] = &tolapai_map_db,
[ich8_sata_snb] = &ich8_map_db,
+ [ich8_2port_sata_snb] = &ich8_2port_map_db,
};
static struct pci_bits piix_enable_bits[] = {
@@ -1242,6 +1244,16 @@
.udma_mask = ATA_UDMA6,
.port_ops = &piix_sata_ops,
},
+
+ [ich8_2port_sata_snb] =
+ {
+ .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR
+ | PIIX_FLAG_PIO16,
+ .pio_mask = ATA_PIO4,
+ .mwdma_mask = ATA_MWDMA2,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &piix_sata_ops,
+ },
};
#define AHCI_PCI_BAR 5
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 497adea..63c743b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2329,7 +2329,7 @@
* from SATA Settings page of Identify Device Data Log.
*/
if (ata_id_has_devslp(dev->id)) {
- u8 sata_setting[ATA_SECT_SIZE];
+ u8 *sata_setting = ap->sector_buf;
int i, j;
dev->flags |= ATA_DFLAG_DEVSLP;
@@ -2439,6 +2439,9 @@
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
+ if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
+ dev->max_sectors = ATA_MAX_SECTORS_LBA48;
+
if (ap->ops->dev_config)
ap->ops->dev_config(dev);
@@ -4100,6 +4103,7 @@
/* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
{ "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA },
+ { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 },
/* Devices we expect to fail diagnostics */
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 318b413..ff44787 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -532,8 +532,8 @@
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
&sshdr);
- if (sshdr.sense_key == 0 &&
- sshdr.asc == 0 && sshdr.ascq == 0)
+ if (sshdr.sense_key == RECOVERED_ERROR &&
+ sshdr.asc == 0 && sshdr.ascq == 0x1d)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
@@ -618,8 +618,8 @@
struct scsi_sense_hdr sshdr;
scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE,
&sshdr);
- if (sshdr.sense_key == 0 &&
- sshdr.asc == 0 && sshdr.ascq == 0)
+ if (sshdr.sense_key == RECOVERED_ERROR &&
+ sshdr.asc == 0 && sshdr.ascq == 0x1d)
cmd_result &= ~SAM_STAT_CHECK_CONDITION;
}
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index d34adef..58cfb32 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -943,7 +943,8 @@
unsigned int ival;
int val_bytes = map->format.val_bytes;
for (i = 0; i < val_len / val_bytes; i++) {
- ival = map->format.parse_val(val + (i * val_bytes));
+ memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
+ ival = map->format.parse_val(map->work_buf);
ret = regcache_write(map, reg + (i * map->reg_stride),
ival);
if (ret) {
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 2c127f9..dfe7583 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1051,29 +1051,12 @@
lo->lo_state = Lo_unbound;
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
+ if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
+ ioctl_by_bdev(bdev, BLKRRPART, 0);
lo->lo_flags = 0;
if (!part_shift)
lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
mutex_unlock(&lo->lo_ctl_mutex);
-
- /*
- * Remove all partitions, since BLKRRPART won't remove user
- * added partitions when max_part=0
- */
- if (bdev) {
- struct disk_part_iter piter;
- struct hd_struct *part;
-
- mutex_lock_nested(&bdev->bd_mutex, 1);
- invalidate_partition(bdev->bd_disk, 0);
- disk_part_iter_init(&piter, bdev->bd_disk,
- DISK_PITER_INCL_EMPTY);
- while ((part = disk_part_iter_next(&piter)))
- delete_partition(bdev->bd_disk, part->partno);
- disk_part_iter_exit(&piter);
- mutex_unlock(&bdev->bd_mutex);
- }
-
/*
* Need not hold lo_ctl_mutex to fput backing file.
* Calling fput holding lo_ctl_mutex triggers a circular
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 92250af..32c6780 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -81,12 +81,17 @@
/* Device instance number, incremented each time a device is probed. */
static int instance;
+struct list_head online_list;
+struct list_head removing_list;
+spinlock_t dev_lock;
+
/*
* Global variable used to hold the major block device number
* allocated in mtip_init().
*/
static int mtip_major;
static struct dentry *dfs_parent;
+static struct dentry *dfs_device_status;
static u32 cpu_use[NR_CPUS];
@@ -243,40 +248,31 @@
/*
* Reset the HBA (without sleeping)
*
- * Just like hba_reset, except does not call sleep, so can be
- * run from interrupt/tasklet context.
- *
* @dd Pointer to the driver data structure.
*
* return value
* 0 The reset was successful.
* -1 The HBA Reset bit did not clear.
*/
-static int hba_reset_nosleep(struct driver_data *dd)
+static int mtip_hba_reset(struct driver_data *dd)
{
unsigned long timeout;
- /* Chip quirk: quiesce any chip function */
- mdelay(10);
-
/* Set the reset bit */
writel(HOST_RESET, dd->mmio + HOST_CTL);
/* Flush */
readl(dd->mmio + HOST_CTL);
- /*
- * Wait 10ms then spin for up to 1 second
- * waiting for reset acknowledgement
- */
- timeout = jiffies + msecs_to_jiffies(1000);
- mdelay(10);
- while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
- && time_before(jiffies, timeout))
- mdelay(1);
+ /* Spin for up to 2 seconds, waiting for reset acknowledgement */
+ timeout = jiffies + msecs_to_jiffies(2000);
+ do {
+ mdelay(10);
+ if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
+ return -1;
- if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag))
- return -1;
+ } while ((readl(dd->mmio + HOST_CTL) & HOST_RESET)
+ && time_before(jiffies, timeout));
if (readl(dd->mmio + HOST_CTL) & HOST_RESET)
return -1;
@@ -481,7 +477,7 @@
dev_warn(&port->dd->pdev->dev,
"PxCMD.CR not clear, escalating reset\n");
- if (hba_reset_nosleep(port->dd))
+ if (mtip_hba_reset(port->dd))
dev_err(&port->dd->pdev->dev,
"HBA reset escalation failed.\n");
@@ -527,6 +523,26 @@
}
+static int mtip_device_reset(struct driver_data *dd)
+{
+ int rv = 0;
+
+ if (mtip_check_surprise_removal(dd->pdev))
+ return 0;
+
+ if (mtip_hba_reset(dd) < 0)
+ rv = -EFAULT;
+
+ mdelay(1);
+ mtip_init_port(dd->port);
+ mtip_start_port(dd->port);
+
+ /* Enable interrupts on the HBA. */
+ writel(readl(dd->mmio + HOST_CTL) | HOST_IRQ_EN,
+ dd->mmio + HOST_CTL);
+ return rv;
+}
+
/*
* Helper function for tag logging
*/
@@ -632,7 +648,7 @@
if (cmdto_cnt) {
print_tags(port->dd, "timed out", tagaccum, cmdto_cnt);
if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
- mtip_restart_port(port);
+ mtip_device_reset(port->dd);
wake_up_interruptible(&port->svc_wait);
}
clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
@@ -1283,11 +1299,11 @@
int rv = 0, ready2go = 1;
struct mtip_cmd *int_cmd = &port->commands[MTIP_TAG_INTERNAL];
unsigned long to;
+ struct driver_data *dd = port->dd;
/* Make sure the buffer is 8 byte aligned. This is asic specific. */
if (buffer & 0x00000007) {
- dev_err(&port->dd->pdev->dev,
- "SG buffer is not 8 byte aligned\n");
+ dev_err(&dd->pdev->dev, "SG buffer is not 8 byte aligned\n");
return -EFAULT;
}
@@ -1300,23 +1316,21 @@
mdelay(100);
} while (time_before(jiffies, to));
if (!ready2go) {
- dev_warn(&port->dd->pdev->dev,
+ dev_warn(&dd->pdev->dev,
"Internal cmd active. new cmd [%02X]\n", fis->command);
return -EBUSY;
}
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);
+ clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+ clear_bit(MTIP_PF_DM_ACTIVE_BIT, &port->flags);
if (atomic == GFP_KERNEL) {
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,
+ dev_warn(&dd->pdev->dev,
"Failed to quiesce IO\n");
release_slot(port, MTIP_TAG_INTERNAL);
clear_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
@@ -1361,58 +1375,84 @@
/* Issue the command to the hardware */
mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
- /* Poll if atomic, wait_for_completion otherwise */
if (atomic == GFP_KERNEL) {
/* Wait for the command to complete or timeout. */
- if (wait_for_completion_timeout(
+ if (wait_for_completion_interruptible_timeout(
&wait,
- msecs_to_jiffies(timeout)) == 0) {
- dev_err(&port->dd->pdev->dev,
- "Internal command did not complete [%d] "
- "within timeout of %lu ms\n",
- atomic, timeout);
- if (mtip_check_surprise_removal(port->dd->pdev) ||
+ msecs_to_jiffies(timeout)) <= 0) {
+ if (rv == -ERESTARTSYS) { /* interrupted */
+ dev_err(&dd->pdev->dev,
+ "Internal command [%02X] was interrupted after %lu ms\n",
+ fis->command, timeout);
+ rv = -EINTR;
+ goto exec_ic_exit;
+ } else if (rv == 0) /* timeout */
+ dev_err(&dd->pdev->dev,
+ "Internal command did not complete [%02X] within timeout of %lu ms\n",
+ fis->command, timeout);
+ else
+ dev_err(&dd->pdev->dev,
+ "Internal command [%02X] wait returned code [%d] after %lu ms - unhandled\n",
+ fis->command, rv, timeout);
+
+ if (mtip_check_surprise_removal(dd->pdev) ||
test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
- &port->dd->dd_flag)) {
+ &dd->dd_flag)) {
+ dev_err(&dd->pdev->dev,
+ "Internal command [%02X] wait returned due to SR\n",
+ fis->command);
rv = -ENXIO;
goto exec_ic_exit;
}
+ mtip_device_reset(dd); /* recover from timeout issue */
rv = -EAGAIN;
+ goto exec_ic_exit;
}
} else {
+ u32 hba_stat, port_stat;
+
/* 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)) {
- if (mtip_check_surprise_removal(port->dd->pdev)) {
+ if (mtip_check_surprise_removal(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)) {
+ &dd->dd_flag)) {
rv = -ENXIO;
goto exec_ic_exit;
}
- if (readl(port->mmio + PORT_IRQ_STAT) & PORT_IRQ_ERR) {
- atomic_inc(&int_cmd->active); /* error */
- break;
+ port_stat = readl(port->mmio + PORT_IRQ_STAT);
+ if (!port_stat)
+ continue;
+
+ if (port_stat & PORT_IRQ_ERR) {
+ dev_err(&dd->pdev->dev,
+ "Internal command [%02X] failed\n",
+ fis->command);
+ mtip_device_reset(dd);
+ rv = -EIO;
+ goto exec_ic_exit;
+ } else {
+ writel(port_stat, port->mmio + PORT_IRQ_STAT);
+ hba_stat = readl(dd->mmio + HOST_IRQ_STAT);
+ if (hba_stat)
+ writel(hba_stat,
+ dd->mmio + HOST_IRQ_STAT);
}
+ break;
}
}
- if (atomic_read(&int_cmd->active) > 1) {
- dev_err(&port->dd->pdev->dev,
- "Internal command [%02X] failed\n", fis->command);
- rv = -EIO;
- }
if (readl(port->cmd_issue[MTIP_TAG_INTERNAL])
& (1 << MTIP_TAG_INTERNAL)) {
rv = -ENXIO;
- if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT,
- &port->dd->dd_flag)) {
- mtip_restart_port(port);
+ if (!test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag)) {
+ mtip_device_reset(dd);
rv = -EAGAIN;
}
}
@@ -1724,7 +1764,8 @@
* -EINVAL Invalid parameters passed in, trim not supported
* -EIO Error submitting trim request to hw
*/
-static int mtip_send_trim(struct driver_data *dd, unsigned int lba, unsigned int len)
+static int mtip_send_trim(struct driver_data *dd, unsigned int lba,
+ unsigned int len)
{
int i, rv = 0;
u64 tlba, tlen, sect_left;
@@ -1811,45 +1852,6 @@
}
/*
- * Reset the HBA.
- *
- * Resets the HBA by setting the HBA Reset bit in the Global
- * HBA Control register. After setting the HBA Reset bit the
- * function waits for 1 second before reading the HBA Reset
- * bit to make sure it has cleared. If HBA Reset is not clear
- * an error is returned. Cannot be used in non-blockable
- * context.
- *
- * @dd Pointer to the driver data structure.
- *
- * return value
- * 0 The reset was successful.
- * -1 The HBA Reset bit did not clear.
- */
-static int mtip_hba_reset(struct driver_data *dd)
-{
- mtip_deinit_port(dd->port);
-
- /* Set the reset bit */
- writel(HOST_RESET, dd->mmio + HOST_CTL);
-
- /* Flush */
- readl(dd->mmio + HOST_CTL);
-
- /* Wait for reset to clear */
- ssleep(1);
-
- /* Check the bit has cleared */
- if (readl(dd->mmio + HOST_CTL) & HOST_RESET) {
- dev_err(&dd->pdev->dev,
- "Reset bit did not clear.\n");
- return -1;
- }
-
- return 0;
-}
-
-/*
* Display the identify command data.
*
* @port Pointer to the port data structure.
@@ -2710,6 +2712,100 @@
static DEVICE_ATTR(status, S_IRUGO, mtip_hw_show_status, NULL);
+/* debugsfs entries */
+
+static ssize_t show_device_status(struct device_driver *drv, char *buf)
+{
+ int size = 0;
+ struct driver_data *dd, *tmp;
+ unsigned long flags;
+ char id_buf[42];
+ u16 status = 0;
+
+ spin_lock_irqsave(&dev_lock, flags);
+ size += sprintf(&buf[size], "Devices Present:\n");
+ list_for_each_entry_safe(dd, tmp, &online_list, online_list) {
+ if (dd->pdev) {
+ if (dd->port &&
+ dd->port->identify &&
+ dd->port->identify_valid) {
+ strlcpy(id_buf,
+ (char *) (dd->port->identify + 10), 21);
+ status = *(dd->port->identify + 141);
+ } else {
+ memset(id_buf, 0, 42);
+ status = 0;
+ }
+
+ if (dd->port &&
+ test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+ size += sprintf(&buf[size],
+ " device %s %s (ftl rebuild %d %%)\n",
+ dev_name(&dd->pdev->dev),
+ id_buf,
+ status);
+ } else {
+ size += sprintf(&buf[size],
+ " device %s %s\n",
+ dev_name(&dd->pdev->dev),
+ id_buf);
+ }
+ }
+ }
+
+ size += sprintf(&buf[size], "Devices Being Removed:\n");
+ list_for_each_entry_safe(dd, tmp, &removing_list, remove_list) {
+ if (dd->pdev) {
+ if (dd->port &&
+ dd->port->identify &&
+ dd->port->identify_valid) {
+ strlcpy(id_buf,
+ (char *) (dd->port->identify+10), 21);
+ status = *(dd->port->identify + 141);
+ } else {
+ memset(id_buf, 0, 42);
+ status = 0;
+ }
+
+ if (dd->port &&
+ test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags)) {
+ size += sprintf(&buf[size],
+ " device %s %s (ftl rebuild %d %%)\n",
+ dev_name(&dd->pdev->dev),
+ id_buf,
+ status);
+ } else {
+ size += sprintf(&buf[size],
+ " device %s %s\n",
+ dev_name(&dd->pdev->dev),
+ id_buf);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&dev_lock, flags);
+
+ return size;
+}
+
+static ssize_t mtip_hw_read_device_status(struct file *f, char __user *ubuf,
+ size_t len, loff_t *offset)
+{
+ int size = *offset;
+ char buf[MTIP_DFS_MAX_BUF_SIZE];
+
+ if (!len || *offset)
+ return 0;
+
+ size += show_device_status(NULL, buf);
+
+ *offset = size <= len ? size : len;
+ size = copy_to_user(ubuf, buf, *offset);
+ if (size)
+ return -EFAULT;
+
+ return *offset;
+}
+
static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
size_t len, loff_t *offset)
{
@@ -2804,6 +2900,13 @@
return *offset;
}
+static const struct file_operations mtip_device_status_fops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
+ .read = mtip_hw_read_device_status,
+ .llseek = no_llseek,
+};
+
static const struct file_operations mtip_regs_fops = {
.owner = THIS_MODULE,
.open = simple_open,
@@ -4161,6 +4264,7 @@
const struct cpumask *node_mask;
int cpu, i = 0, j = 0;
int my_node = NUMA_NO_NODE;
+ unsigned long flags;
/* Allocate memory for this devices private data. */
my_node = pcibus_to_node(pdev->bus);
@@ -4218,6 +4322,9 @@
dd->pdev = pdev;
dd->numa_node = my_node;
+ INIT_LIST_HEAD(&dd->online_list);
+ INIT_LIST_HEAD(&dd->remove_list);
+
memset(dd->workq_name, 0, 32);
snprintf(dd->workq_name, 31, "mtipq%d", dd->instance);
@@ -4305,6 +4412,14 @@
instance++;
if (rv != MTIP_FTL_REBUILD_MAGIC)
set_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag);
+ else
+ rv = 0; /* device in rebuild state, return 0 from probe */
+
+ /* Add to online list even if in ftl rebuild */
+ spin_lock_irqsave(&dev_lock, flags);
+ list_add(&dd->online_list, &online_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+
goto done;
block_initialize_err:
@@ -4338,9 +4453,15 @@
{
struct driver_data *dd = pci_get_drvdata(pdev);
int counter = 0;
+ unsigned long flags;
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
+ spin_lock_irqsave(&dev_lock, flags);
+ list_del_init(&dd->online_list);
+ list_add(&dd->remove_list, &removing_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+
if (mtip_check_surprise_removal(pdev)) {
while (!test_bit(MTIP_DDF_CLEANUP_BIT, &dd->dd_flag)) {
counter++;
@@ -4366,6 +4487,10 @@
pci_disable_msi(pdev);
+ spin_lock_irqsave(&dev_lock, flags);
+ list_del_init(&dd->remove_list);
+ spin_unlock_irqrestore(&dev_lock, flags);
+
kfree(dd);
pcim_iounmap_regions(pdev, 1 << MTIP_ABAR);
}
@@ -4513,6 +4638,11 @@
pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
+ spin_lock_init(&dev_lock);
+
+ INIT_LIST_HEAD(&online_list);
+ INIT_LIST_HEAD(&removing_list);
+
/* Allocate a major block device number to use with this driver. */
error = register_blkdev(0, MTIP_DRV_NAME);
if (error <= 0) {
@@ -4522,11 +4652,18 @@
}
mtip_major = error;
- if (!dfs_parent) {
- dfs_parent = debugfs_create_dir("rssd", NULL);
- if (IS_ERR_OR_NULL(dfs_parent)) {
- pr_warn("Error creating debugfs parent\n");
- dfs_parent = NULL;
+ dfs_parent = debugfs_create_dir("rssd", NULL);
+ if (IS_ERR_OR_NULL(dfs_parent)) {
+ pr_warn("Error creating debugfs parent\n");
+ dfs_parent = NULL;
+ }
+ if (dfs_parent) {
+ dfs_device_status = debugfs_create_file("device_status",
+ S_IRUGO, dfs_parent, NULL,
+ &mtip_device_status_fops);
+ if (IS_ERR_OR_NULL(dfs_device_status)) {
+ pr_err("Error creating device_status node\n");
+ dfs_device_status = NULL;
}
}
diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h
index 3bffff5..8e8334c 100644
--- a/drivers/block/mtip32xx/mtip32xx.h
+++ b/drivers/block/mtip32xx/mtip32xx.h
@@ -129,9 +129,9 @@
MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */
MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */
MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */
- MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) | \
- (1 << MTIP_PF_EH_ACTIVE_BIT) | \
- (1 << MTIP_PF_SE_ACTIVE_BIT) | \
+ 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)),
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
@@ -144,9 +144,9 @@
MTIP_DDF_REMOVE_PENDING_BIT = 1,
MTIP_DDF_OVER_TEMP_BIT = 2,
MTIP_DDF_WRITE_PROTECT_BIT = 3,
- MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
- (1 << MTIP_DDF_SEC_LOCK_BIT) | \
- (1 << MTIP_DDF_OVER_TEMP_BIT) | \
+ MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
+ (1 << MTIP_DDF_SEC_LOCK_BIT) |
+ (1 << MTIP_DDF_OVER_TEMP_BIT) |
(1 << MTIP_DDF_WRITE_PROTECT_BIT)),
MTIP_DDF_CLEANUP_BIT = 5,
@@ -180,7 +180,7 @@
#define MTIP_TRIM_TIMEOUT_MS 240000
#define MTIP_MAX_TRIM_ENTRIES 8
-#define MTIP_MAX_TRIM_ENTRY_LEN 0xfff8
+#define MTIP_MAX_TRIM_ENTRY_LEN 0xfff8
struct mtip_trim_entry {
u32 lba; /* starting lba of region */
@@ -501,6 +501,10 @@
atomic_t irq_workers_active;
int isr_binding;
+
+ struct list_head online_list; /* linkage for online list */
+
+ struct list_head remove_list; /* linkage for removing list */
};
#endif
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index f556f8a..b7b7a88 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1742,9 +1742,10 @@
struct rbd_device *rbd_dev = img_request->rbd_dev;
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct rbd_obj_request *obj_request;
+ struct rbd_obj_request *next_obj_request;
dout("%s: img %p\n", __func__, img_request);
- for_each_obj_request(img_request, obj_request) {
+ for_each_obj_request_safe(img_request, obj_request, next_obj_request) {
int ret;
obj_request->callback = rbd_img_obj_callback;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index e3f9a99..d784650 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -373,26 +373,14 @@
struct hpet_dev *devp;
unsigned long addr;
- if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
- return -EINVAL;
-
devp = file->private_data;
addr = devp->hd_hpets->hp_hpet_phys;
if (addr & (PAGE_SIZE - 1))
return -ENOSYS;
- vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot)) {
- printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
- __func__);
- return -EAGAIN;
- }
-
- return 0;
+ return vm_iomap_memory(vma, addr, PAGE_SIZE);
#else
return -ENOSYS;
#endif
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index ad72922..6133ef5 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -502,7 +502,6 @@
sample_time = cpu->pstate_policy->sample_rate_ms;
delay = msecs_to_jiffies(sample_time);
- delay -= jiffies % delay;
mod_timer_pinned(&cpu->timer, jiffies + delay);
}
diff --git a/drivers/crypto/ux500/cryp/cryp_core.c b/drivers/crypto/ux500/cryp/cryp_core.c
index 8bc5fef..22c9063 100644
--- a/drivers/crypto/ux500/cryp/cryp_core.c
+++ b/drivers/crypto/ux500/cryp/cryp_core.c
@@ -1750,7 +1750,7 @@
.shutdown = ux500_cryp_shutdown,
.driver = {
.owner = THIS_MODULE,
- .name = "cryp1"
+ .name = "cryp1",
.pm = &ux500_cryp_pm,
}
};
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 6e13f26..88cfc61 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -310,8 +310,6 @@
dev_vdbg(chan2dev(&atchan->chan_common), "complete all\n");
- BUG_ON(atc_chan_is_enabled(atchan));
-
/*
* Submit queued descriptors ASAP, i.e. before we go through
* the completed ones.
@@ -368,6 +366,9 @@
{
dev_vdbg(chan2dev(&atchan->chan_common), "advance_work\n");
+ if (atc_chan_is_enabled(atchan))
+ return;
+
if (list_empty(&atchan->active_list) ||
list_is_singular(&atchan->active_list)) {
atc_complete_all(atchan);
@@ -1078,9 +1079,7 @@
return;
spin_lock_irqsave(&atchan->lock, flags);
- if (!atc_chan_is_enabled(atchan)) {
- atc_advance_work(atchan);
- }
+ atc_advance_work(atchan);
spin_unlock_irqrestore(&atchan->lock, flags);
}
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index c4b4fd2..08b43bf 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -276,12 +276,20 @@
spin_lock_irqsave(&c->vc.lock, flags);
if (vchan_issue_pending(&c->vc) && !c->desc) {
- struct omap_dmadev *d = to_omap_dma_dev(chan->device);
- spin_lock(&d->lock);
- if (list_empty(&c->node))
- list_add_tail(&c->node, &d->pending);
- spin_unlock(&d->lock);
- tasklet_schedule(&d->task);
+ /*
+ * c->cyclic is used only by audio and in this case the DMA need
+ * to be started without delay.
+ */
+ if (!c->cyclic) {
+ struct omap_dmadev *d = to_omap_dma_dev(chan->device);
+ spin_lock(&d->lock);
+ if (list_empty(&c->node))
+ list_add_tail(&c->node, &d->pending);
+ spin_unlock(&d->lock);
+ tasklet_schedule(&d->task);
+ } else {
+ omap_dma_start_desc(c);
+ }
}
spin_unlock_irqrestore(&c->vc.lock, flags);
}
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 7181531..5dbc594 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2882,7 +2882,7 @@
{
struct dma_pl330_platdata *pdat;
struct dma_pl330_dmac *pdmac;
- struct dma_pl330_chan *pch;
+ struct dma_pl330_chan *pch, *_p;
struct pl330_info *pi;
struct dma_device *pd;
struct resource *res;
@@ -2984,7 +2984,16 @@
ret = dma_async_device_register(pd);
if (ret) {
dev_err(&adev->dev, "unable to register DMAC\n");
- goto probe_err2;
+ goto probe_err3;
+ }
+
+ if (adev->dev.of_node) {
+ ret = of_dma_controller_register(adev->dev.of_node,
+ of_dma_pl330_xlate, pdmac);
+ if (ret) {
+ dev_err(&adev->dev,
+ "unable to register DMA to the generic DT DMA helpers\n");
+ }
}
dev_info(&adev->dev,
@@ -2995,16 +3004,21 @@
pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan,
pi->pcfg.num_peri, pi->pcfg.num_events);
- ret = of_dma_controller_register(adev->dev.of_node,
- of_dma_pl330_xlate, pdmac);
- if (ret) {
- dev_err(&adev->dev,
- "unable to register DMA to the generic DT DMA helpers\n");
- goto probe_err2;
- }
-
return 0;
+probe_err3:
+ amba_set_drvdata(adev, NULL);
+ /* Idle the DMAC */
+ list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels,
+ chan.device_node) {
+
+ /* Remove the channel */
+ list_del(&pch->chan.device_node);
+
+ /* Flush the channel */
+ pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0);
+ pl330_free_chan_resources(&pch->chan);
+ }
probe_err2:
pl330_del(pi);
probe_err1:
@@ -3023,8 +3037,10 @@
if (!pdmac)
return 0;
- of_dma_controller_free(adev->dev.of_node);
+ if (adev->dev.of_node)
+ of_dma_controller_free(adev->dev.of_node);
+ dma_async_device_unregister(&pdmac->ddma);
amba_set_drvdata(adev, NULL);
/* Idle the DMAC */
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 806c77b..272a3ec 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -275,19 +275,18 @@
}
if (slot) {
- edev->res[i].name = NULL;
edev->res[i].start = SLOT_ADDRESS(root, slot)
+ (i * 0x400);
edev->res[i].end = edev->res[i].start + 0xff;
edev->res[i].flags = IORESOURCE_IO;
} else {
- edev->res[i].name = NULL;
edev->res[i].start = SLOT_ADDRESS(root, slot)
+ EISA_VENDOR_ID_OFFSET;
edev->res[i].end = edev->res[i].start + 3;
- edev->res[i].flags = IORESOURCE_BUSY;
+ edev->res[i].flags = IORESOURCE_IO | IORESOURCE_BUSY;
}
+ dev_printk(KERN_DEBUG, &edev->dev, "%pR\n", &edev->res[i]);
if (request_resource(root->res, &edev->res[i]))
goto failed;
}
@@ -314,41 +313,40 @@
{
int i, c;
struct eisa_device *edev;
+ char *enabled_str;
- printk(KERN_INFO "EISA: Probing bus %d at %s\n",
- root->bus_nr, dev_name(root->dev));
+ dev_info(root->dev, "Probing EISA bus %d\n", root->bus_nr);
/* First try to get hold of slot 0. If there is no device
* here, simply fail, unless root->force_probe is set. */
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev) {
- printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+ dev_err(root->dev, "EISA: Couldn't allocate mainboard slot\n");
return -ENOMEM;
}
- if (eisa_request_resources(root, edev, 0)) {
- printk(KERN_WARNING \
- "EISA: Cannot allocate resource for mainboard\n");
- kfree(edev);
- if (!root->force_probe)
- return -EBUSY;
- goto force_probe;
- }
-
if (eisa_init_device(root, edev, 0)) {
- eisa_release_resources(edev);
kfree(edev);
if (!root->force_probe)
return -ENODEV;
goto force_probe;
}
- printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+ if (eisa_request_resources(root, edev, 0)) {
+ dev_warn(root->dev,
+ "EISA: Cannot allocate resource for mainboard\n");
+ kfree(edev);
+ if (!root->force_probe)
+ return -EBUSY;
+ goto force_probe;
+ }
+
+ dev_info(&edev->dev, "EISA: Mainboard %s detected\n", edev->id.sig);
if (eisa_register_device(edev)) {
- printk(KERN_ERR "EISA: Failed to register %s\n",
- edev->id.sig);
+ dev_err(&edev->dev, "EISA: Failed to register %s\n",
+ edev->id.sig);
eisa_release_resources(edev);
kfree(edev);
}
@@ -358,55 +356,47 @@
for (c = 0, i = 1; i <= root->slots; i++) {
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev) {
- printk(KERN_ERR "EISA: Out of memory for slot %d\n", i);
- continue;
- }
-
- if (eisa_request_resources(root, edev, i)) {
- printk(KERN_WARNING \
- "Cannot allocate resource for EISA slot %d\n",
- i);
- kfree(edev);
+ dev_err(root->dev, "EISA: Out of memory for slot %d\n",
+ i);
continue;
}
if (eisa_init_device(root, edev, i)) {
- eisa_release_resources(edev);
kfree(edev);
continue;
}
-
- printk(KERN_INFO "EISA: slot %d : %s detected",
- i, edev->id.sig);
-
- switch (edev->state) {
- case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
- printk(" (forced enabled)");
- break;
- case EISA_CONFIG_FORCED:
- printk(" (forced disabled)");
- break;
-
- case 0:
- printk(" (disabled)");
- break;
+ if (eisa_request_resources(root, edev, i)) {
+ dev_warn(root->dev,
+ "Cannot allocate resource for EISA slot %d\n",
+ i);
+ kfree(edev);
+ continue;
}
-
- printk (".\n");
+
+ if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED))
+ enabled_str = " (forced enabled)";
+ else if (edev->state == EISA_CONFIG_FORCED)
+ enabled_str = " (forced disabled)";
+ else if (edev->state == 0)
+ enabled_str = " (disabled)";
+ else
+ enabled_str = "";
+
+ dev_info(&edev->dev, "EISA: slot %d: %s detected%s\n", i,
+ edev->id.sig, enabled_str);
c++;
if (eisa_register_device(edev)) {
- printk(KERN_ERR "EISA: Failed to register %s\n",
- edev->id.sig);
+ dev_err(&edev->dev, "EISA: Failed to register %s\n",
+ edev->id.sig);
eisa_release_resources(edev);
kfree(edev);
}
}
- printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
-
+ dev_info(root->dev, "EISA: Detected %d card%s\n", c, c == 1 ? "" : "s");
return 0;
}
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 6c3fca9..a333bf3 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -25,8 +25,7 @@
struct resource *res, *bus_res = NULL;
if ((rc = pci_enable_device (pdev))) {
- printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
- pci_name(pdev));
+ dev_err(&pdev->dev, "Could not enable device\n");
return rc;
}
@@ -59,7 +58,7 @@
dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
if (eisa_root_register (&pci_eisa_root)) {
- printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
+ dev_err(&pdev->dev, "Could not register EISA root\n");
return -1;
}
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 42c759a..3e53200 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -39,6 +39,7 @@
config EFI_VARS
tristate "EFI Variable Support via sysfs"
depends on EFI
+ select UCS2_STRING
default n
help
If you say Y here, you are able to get EFI (Extensible Firmware
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 7acafb8..f4baa11 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -80,6 +80,7 @@
#include <linux/slab.h>
#include <linux/pstore.h>
#include <linux/ctype.h>
+#include <linux/ucs2_string.h>
#include <linux/fs.h>
#include <linux/ramfs.h>
@@ -172,51 +173,6 @@
static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
static bool efivar_wq_enabled = true;
-/* Return the number of unicode characters in data */
-static unsigned long
-utf16_strnlen(efi_char16_t *s, size_t maxlength)
-{
- unsigned long length = 0;
-
- while (*s++ != 0 && length < maxlength)
- length++;
- return length;
-}
-
-static inline unsigned long
-utf16_strlen(efi_char16_t *s)
-{
- return utf16_strnlen(s, ~0UL);
-}
-
-/*
- * Return the number of bytes is the length of this string
- * Note: this is NOT the same as the number of unicode characters
- */
-static inline unsigned long
-utf16_strsize(efi_char16_t *data, unsigned long maxlength)
-{
- return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
-}
-
-static inline int
-utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
-{
- while (1) {
- if (len == 0)
- return 0;
- if (*a < *b)
- return -1;
- if (*a > *b)
- return 1;
- if (*a == 0) /* implies *b == 0 */
- return 0;
- a++;
- b++;
- len--;
- }
-}
-
static bool
validate_device_path(struct efi_variable *var, int match, u8 *buffer,
unsigned long len)
@@ -268,7 +224,7 @@
u16 filepathlength;
int i, desclength = 0, namelen;
- namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
+ namelen = ucs2_strnlen(var->VariableName, sizeof(var->VariableName));
/* Either "Boot" or "Driver" followed by four digits of hex */
for (i = match; i < match+4; i++) {
@@ -291,7 +247,7 @@
* 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;
+ desclength = ucs2_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
/* Each boot entry must have a descriptor */
if (!desclength)
@@ -436,24 +392,12 @@
check_var_size_locked(struct efivars *efivars, u32 attributes,
unsigned long size)
{
- u64 storage_size, remaining_size, max_size;
- efi_status_t status;
const struct efivar_operations *fops = efivars->ops;
- if (!efivars->ops->query_variable_info)
+ if (!efivars->ops->query_variable_store)
return EFI_UNSUPPORTED;
- status = fops->query_variable_info(attributes, &storage_size,
- &remaining_size, &max_size);
-
- if (status != EFI_SUCCESS)
- return status;
-
- if (!storage_size || size > remaining_size || size > max_size ||
- (remaining_size - size) < (storage_size / 2))
- return EFI_OUT_OF_RESOURCES;
-
- return status;
+ return fops->query_variable_store(attributes, size);
}
@@ -593,7 +537,7 @@
spin_lock_irq(&efivars->lock);
status = check_var_size_locked(efivars, new_var->Attributes,
- new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+ new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED)
status = efivars->ops->set_variable(new_var->VariableName,
@@ -771,7 +715,7 @@
* QueryVariableInfo() isn't supported by the firmware.
*/
- varsize = datasize + utf16_strsize(var->var.VariableName, 1024);
+ varsize = datasize + ucs2_strsize(var->var.VariableName, 1024);
status = check_var_size(efivars, attributes, varsize);
if (status != EFI_SUCCESS) {
@@ -1223,7 +1167,7 @@
inode = NULL;
- len = utf16_strlen(entry->var.VariableName);
+ len = ucs2_strlen(entry->var.VariableName);
/* name, plus '-', plus GUID, plus NUL*/
name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
@@ -1481,8 +1425,8 @@
if (efi_guidcmp(entry->var.VendorGuid, vendor))
continue;
- if (utf16_strncmp(entry->var.VariableName, efi_name,
- utf16_strlen(efi_name))) {
+ if (ucs2_strncmp(entry->var.VariableName, efi_name,
+ ucs2_strlen(efi_name))) {
/*
* Check if an old format,
* which doesn't support holding
@@ -1494,8 +1438,8 @@
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name_old[i] = name_old[i];
- if (utf16_strncmp(entry->var.VariableName, efi_name_old,
- utf16_strlen(efi_name_old)))
+ if (ucs2_strncmp(entry->var.VariableName, efi_name_old,
+ ucs2_strlen(efi_name_old)))
continue;
}
@@ -1573,8 +1517,8 @@
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf16_strsize(new_var->VariableName, 1024);
+ strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = ucs2_strsize(new_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
new_var->VariableName, strsize1) &&
@@ -1590,7 +1534,7 @@
}
status = check_var_size_locked(efivars, new_var->Attributes,
- new_var->DataSize + utf16_strsize(new_var->VariableName, 1024));
+ new_var->DataSize + ucs2_strsize(new_var->VariableName, 1024));
if (status && status != EFI_UNSUPPORTED) {
spin_unlock_irq(&efivars->lock);
@@ -1614,7 +1558,7 @@
/* Create the entry in sysfs. Locking is not required here */
status = efivar_create_sysfs_entry(efivars,
- utf16_strsize(new_var->VariableName,
+ ucs2_strsize(new_var->VariableName,
1024),
new_var->VariableName,
&new_var->VendorGuid);
@@ -1644,8 +1588,8 @@
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf16_strsize(del_var->VariableName, 1024);
+ strsize1 = ucs2_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = ucs2_strsize(del_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
del_var->VariableName, strsize1) &&
@@ -1684,16 +1628,17 @@
return count;
}
-static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
+static bool variable_is_present(struct efivars *efivars,
+ efi_char16_t *variable_name,
+ efi_guid_t *vendor)
{
struct efivar_entry *entry, *n;
- struct efivars *efivars = &__efivars;
unsigned long strsize1, strsize2;
bool found = false;
- strsize1 = utf16_strsize(variable_name, 1024);
+ strsize1 = ucs2_strsize(variable_name, 1024);
list_for_each_entry_safe(entry, n, &efivars->list, list) {
- strsize2 = utf16_strsize(entry->var.VariableName, 1024);
+ strsize2 = ucs2_strsize(entry->var.VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(variable_name, &(entry->var.VariableName),
strsize2) &&
@@ -1759,8 +1704,8 @@
if (status != EFI_SUCCESS) {
break;
} else {
- if (!variable_is_present(variable_name,
- &vendor)) {
+ if (!variable_is_present(efivars,
+ variable_name, &vendor)) {
found = true;
break;
}
@@ -2064,7 +2009,8 @@
* we'll ever see a different variable name,
* and may end up looping here forever.
*/
- if (variable_is_present(variable_name, &vendor_guid)) {
+ if (variable_is_present(efivars, variable_name,
+ &vendor_guid)) {
dup_variable_bug(variable_name, &vendor_guid,
variable_name_size);
status = EFI_NOT_FOUND;
@@ -2131,7 +2077,7 @@
ops.get_variable = efi.get_variable;
ops.set_variable = efi.set_variable;
ops.get_next_variable = efi.get_next_variable;
- ops.query_variable_info = efi.query_variable_info;
+ ops.query_variable_store = efi_query_variable_store;
error = register_efivars(&__efivars, &ops, efi_kobj);
if (error)
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 2405946..9391cf1 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -575,7 +575,7 @@
chip->gpio_chip.ngpio,
irq_base,
&pca953x_irq_simple_ops,
- NULL);
+ chip);
if (!chip->domain)
return -ENODEV;
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index b820869..d7008df 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/bitops.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
@@ -22,6 +23,7 @@
#include <linux/amba/bus.h>
#include <linux/amba/pl061.h>
#include <linux/slab.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pm.h>
#include <asm/mach/irq.h>
@@ -51,8 +53,7 @@
spinlock_t lock;
void __iomem *base;
- int irq_base;
- struct irq_chip_generic *irq_gc;
+ struct irq_domain *domain;
struct gpio_chip gc;
#ifdef CONFIG_PM
@@ -60,6 +61,24 @@
#endif
};
+static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ /*
+ * Map back to global GPIO space and request muxing, the direction
+ * parameter does not matter for this controller.
+ */
+ int gpio = chip->base + offset;
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void pl061_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+ int gpio = chip->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -122,24 +141,20 @@
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
- if (chip->irq_base <= 0)
- return -EINVAL;
-
- return chip->irq_base + offset;
+ return irq_create_mapping(chip->domain, offset);
}
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
{
- struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
- struct pl061_gpio *chip = gc->private;
- int offset = d->irq - chip->irq_base;
+ struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+ int offset = irqd_to_hwirq(d);
unsigned long flags;
u8 gpiois, gpioibe, gpioiev;
if (offset < 0 || offset >= PL061_GPIO_NR)
return -EINVAL;
- raw_spin_lock_irqsave(&gc->lock, flags);
+ spin_lock_irqsave(&chip->lock, flags);
gpioiev = readb(chip->base + GPIOIEV);
@@ -168,7 +183,7 @@
writeb(gpioiev, chip->base + GPIOIEV);
- raw_spin_unlock_irqrestore(&gc->lock, flags);
+ spin_unlock_irqrestore(&chip->lock, flags);
return 0;
}
@@ -192,31 +207,61 @@
chained_irq_exit(irqchip, desc);
}
-static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
+static void pl061_irq_mask(struct irq_data *d)
{
- struct irq_chip_type *ct;
+ struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+ u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+ u8 gpioie;
- chip->irq_gc = irq_alloc_generic_chip("gpio-pl061", 1, irq_base,
- chip->base, handle_simple_irq);
- chip->irq_gc->private = chip;
-
- ct = chip->irq_gc->chip_types;
- ct->chip.irq_mask = irq_gc_mask_clr_bit;
- ct->chip.irq_unmask = irq_gc_mask_set_bit;
- ct->chip.irq_set_type = pl061_irq_type;
- ct->chip.irq_set_wake = irq_gc_set_wake;
- ct->regs.mask = GPIOIE;
-
- irq_setup_generic_chip(chip->irq_gc, IRQ_MSK(PL061_GPIO_NR),
- IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
+ spin_lock(&chip->lock);
+ gpioie = readb(chip->base + GPIOIE) & ~mask;
+ writeb(gpioie, chip->base + GPIOIE);
+ spin_unlock(&chip->lock);
}
+static void pl061_irq_unmask(struct irq_data *d)
+{
+ struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
+ u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
+ u8 gpioie;
+
+ spin_lock(&chip->lock);
+ gpioie = readb(chip->base + GPIOIE) | mask;
+ writeb(gpioie, chip->base + GPIOIE);
+ spin_unlock(&chip->lock);
+}
+
+static struct irq_chip pl061_irqchip = {
+ .name = "pl061 gpio",
+ .irq_mask = pl061_irq_mask,
+ .irq_unmask = pl061_irq_unmask,
+ .irq_set_type = pl061_irq_type,
+};
+
+static int pl061_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct pl061_gpio *chip = d->host_data;
+
+ irq_set_chip_and_handler_name(virq, &pl061_irqchip, handle_simple_irq,
+ "pl061");
+ irq_set_chip_data(virq, chip);
+ irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static const struct irq_domain_ops pl061_domain_ops = {
+ .map = pl061_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
struct pl061_platform_data *pdata = dev->platform_data;
struct pl061_gpio *chip;
- int ret, irq, i;
+ int ret, irq, i, irq_base;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -224,24 +269,32 @@
if (pdata) {
chip->gc.base = pdata->gpio_base;
- chip->irq_base = pdata->irq_base;
- } else if (adev->dev.of_node) {
+ irq_base = pdata->irq_base;
+ if (irq_base <= 0)
+ return -ENODEV;
+ } else {
chip->gc.base = -1;
- chip->irq_base = 0;
- } else
- return -ENODEV;
+ irq_base = 0;
+ }
if (!devm_request_mem_region(dev, adev->res.start,
- resource_size(&adev->res), "pl061"))
+ resource_size(&adev->res), "pl061"))
return -EBUSY;
chip->base = devm_ioremap(dev, adev->res.start,
- resource_size(&adev->res));
- if (chip->base == NULL)
+ resource_size(&adev->res));
+ if (!chip->base)
return -ENOMEM;
+ chip->domain = irq_domain_add_simple(adev->dev.of_node, PL061_GPIO_NR,
+ irq_base, &pl061_domain_ops, chip);
+ if (!chip->domain)
+ return -ENODEV;
+
spin_lock_init(&chip->lock);
+ chip->gc.request = pl061_gpio_request;
+ chip->gc.free = pl061_gpio_free;
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
chip->gc.get = pl061_get_value;
@@ -259,12 +312,6 @@
/*
* irq_chip support
*/
-
- if (chip->irq_base <= 0)
- return 0;
-
- pl061_init_gc(chip, chip->irq_base);
-
writeb(0, chip->base + GPIOIE); /* disable irqs */
irq = adev->irq[0];
if (irq < 0)
diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c
index 9cc108d..8325f58 100644
--- a/drivers/gpio/gpio-pxa.c
+++ b/drivers/gpio/gpio-pxa.c
@@ -642,7 +642,12 @@
.of_match_table = of_match_ptr(pxa_gpio_dt_ids),
},
};
-module_platform_driver(pxa_gpio_driver);
+
+static int __init pxa_gpio_init(void)
+{
+ return platform_driver_register(&pxa_gpio_driver);
+}
+postcore_initcall(pxa_gpio_init);
#ifdef CONFIG_PM
static int pxa_gpio_suspend(void)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 5150df6..465f4ca 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -203,22 +203,11 @@
if (!pctldev)
break;
- /*
- * This assumes that the n GPIO pins are consecutive in the
- * GPIO number space, and that the pins are also consecutive
- * in their local number space. Currently it is not possible
- * to add different ranges for one and the same GPIO chip,
- * as the code assumes that we have one consecutive range
- * on both, mapping 1-to-1.
- *
- * TODO: make the OF bindings handle multiple sparse ranges
- * on the same GPIO chip.
- */
ret = gpiochip_add_pin_range(chip,
pinctrl_dev_get_devname(pctldev),
- 0, /* offset in gpiochip */
pinspec.args[0],
- pinspec.args[1]);
+ pinspec.args[1],
+ pinspec.args[2]);
if (ret)
break;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 59d6b9b..892ff9f 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1544,10 +1544,10 @@
if (!fb_helper->fb)
return 0;
- drm_modeset_lock_all(dev);
+ mutex_lock(&fb_helper->dev->mode_config.mutex);
if (!drm_fb_helper_is_bound(fb_helper)) {
fb_helper->delayed_hotplug = true;
- drm_modeset_unlock_all(dev);
+ mutex_unlock(&fb_helper->dev->mode_config.mutex);
return 0;
}
DRM_DEBUG_KMS("\n");
@@ -1558,9 +1558,11 @@
count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
max_height);
+ mutex_unlock(&fb_helper->dev->mode_config.mutex);
+
+ drm_modeset_lock_all(dev);
drm_setup_crtcs(fb_helper);
drm_modeset_unlock_all(dev);
-
drm_fb_helper_set_par(fb_helper->fbdev);
return 0;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 04fa6f1..f83f071 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -506,7 +506,7 @@
}
EXPORT_SYMBOL(drm_gtf_mode);
-#if IS_ENABLED(CONFIG_VIDEOMODE)
+#ifdef CONFIG_VIDEOMODE_HELPERS
int drm_display_mode_from_videomode(const struct videomode *vm,
struct drm_display_mode *dmode)
{
@@ -523,26 +523,25 @@
dmode->clock = vm->pixelclock / 1000;
dmode->flags = 0;
- if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+ if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
dmode->flags |= DRM_MODE_FLAG_PHSYNC;
- else if (vm->dmt_flags & VESA_DMT_HSYNC_LOW)
+ else if (vm->flags & DISPLAY_FLAGS_HSYNC_LOW)
dmode->flags |= DRM_MODE_FLAG_NHSYNC;
- if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
+ if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
dmode->flags |= DRM_MODE_FLAG_PVSYNC;
- else if (vm->dmt_flags & VESA_DMT_VSYNC_LOW)
+ else if (vm->flags & DISPLAY_FLAGS_VSYNC_LOW)
dmode->flags |= DRM_MODE_FLAG_NVSYNC;
- if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+ if (vm->flags & DISPLAY_FLAGS_INTERLACED)
dmode->flags |= DRM_MODE_FLAG_INTERLACE;
- if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+ if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
drm_mode_set_name(dmode);
return 0;
}
EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
-#endif
-#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+#ifdef CONFIG_OF
/**
* of_get_drm_display_mode - get a drm_display_mode from devicetree
* @np: device_node with the timing specification
@@ -572,7 +571,8 @@
return 0;
}
EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
-#endif
+#endif /* CONFIG_OF */
+#endif /* CONFIG_VIDEOMODE_HELPERS */
/**
* drm_mode_set_name - set the name on a mode
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index fe22bb7..78d8e919 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -751,8 +751,6 @@
int i;
unsigned char misc = 0;
unsigned char ext_vga[6];
- unsigned char ext_vga_index24;
- unsigned char dac_index90 = 0;
u8 bppshift;
static unsigned char dacvalue[] = {
@@ -803,7 +801,6 @@
option2 = 0x0000b000;
break;
case G200_ER:
- dac_index90 = 0;
break;
}
@@ -852,10 +849,8 @@
WREG_DAC(i, dacvalue[i]);
}
- if (mdev->type == G200_ER) {
- WREG_DAC(0x90, dac_index90);
- }
-
+ if (mdev->type == G200_ER)
+ WREG_DAC(0x90, 0);
if (option)
pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
@@ -952,8 +947,6 @@
if (mdev->type == G200_WB)
ext_vga[1] |= 0x88;
- ext_vga_index24 = 0x05;
-
/* Set pixel clocks */
misc = 0x2d;
WREG8(MGA_MISC_OUT, misc);
@@ -965,7 +958,7 @@
}
if (mdev->type == G200_ER)
- WREG_ECRT(24, ext_vga_index24);
+ WREG_ECRT(0x24, 0x5);
if (mdev->type == G200_EV) {
WREG_ECRT(6, 0);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7f0e6c3..1ddc03e 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -479,7 +479,7 @@
{
struct nv50_display_flip *flip = data;
if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) ==
- flip->chan->data);
+ flip->chan->data)
return true;
usleep_range(1, 2);
return false;
diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig
index d24d040..e461e99 100644
--- a/drivers/gpu/drm/tilcdc/Kconfig
+++ b/drivers/gpu/drm/tilcdc/Kconfig
@@ -4,8 +4,7 @@
select DRM_KMS_HELPER
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
- select OF_VIDEOMODE
- select OF_DISPLAY_TIMING
+ select VIDEOMODE_HELPERS
select BACKLIGHT_CLASS_DEVICE
help
Choose this option if you have an TI SoC with LCDC display
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 580b74e..90ee497 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -173,7 +173,7 @@
struct drm_display_mode *mode = drm_mode_create(dev);
struct videomode vm;
- if (videomode_from_timing(timings, &vm, i))
+ if (videomode_from_timings(timings, &vm, i))
break;
drm_display_mode_from_videomode(&vm, mode);
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index fe5cdbcf..b44d548 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -61,6 +61,10 @@
int ret;
edid = (struct edid *)udl_get_edid(udl);
+ if (!edid) {
+ drm_mode_connector_update_edid_property(connector, NULL);
+ return 0;
+ }
/*
* We only read the main block, but if the monitor reports extension
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index db713c0..461a0d7 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -416,6 +416,8 @@
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "%s: can't power on device\n", __func__);
+ pm_runtime_put_noidle(dev);
+ module_put(dev->driver->owner);
return ret;
}
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 5d66750..1a38dd7 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -465,6 +465,7 @@
ICPU(0x3c, idle_cpu_hsw),
ICPU(0x3f, idle_cpu_hsw),
ICPU(0x45, idle_cpu_hsw),
+ ICPU(0x46, idle_cpu_hsw),
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index 1daa979..0bfd8cf 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -359,7 +359,7 @@
case 0x802: /* Intuos4 General Pen */
case 0x804: /* Intuos4 Marker Pen */
case 0x40802: /* Intuos4 Classic Pen */
- case 0x18803: /* DTH2242 Grip Pen */
+ case 0x18802: /* DTH2242 Grip Pen */
case 0x022:
wacom->tool[idx] = BTN_TOOL_PEN;
break;
@@ -1912,7 +1912,7 @@
{ "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047,
63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0xBC =
- { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047,
+ { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40640, 25400, 2047,
63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
static const struct wacom_features wacom_features_0x26 =
{ "Wacom Intuos5 touch S", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047,
@@ -2144,7 +2144,7 @@
{ USB_DEVICE_WACOM(0x44) },
{ USB_DEVICE_WACOM(0x45) },
{ USB_DEVICE_WACOM(0x59) },
- { USB_DEVICE_WACOM(0x5D) },
+ { USB_DEVICE_DETAILED(0x5D, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0xB0) },
{ USB_DEVICE_WACOM(0xB1) },
{ USB_DEVICE_WACOM(0xB2) },
@@ -2209,7 +2209,7 @@
{ USB_DEVICE_WACOM(0x47) },
{ USB_DEVICE_WACOM(0xF4) },
{ USB_DEVICE_WACOM(0xF8) },
- { USB_DEVICE_WACOM(0xF6) },
+ { USB_DEVICE_DETAILED(0xF6, USB_CLASS_HID, 0, 0) },
{ USB_DEVICE_WACOM(0xFA) },
{ USB_DEVICE_LENOVO(0x6004) },
{ }
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b287ca3..8301837 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -173,7 +173,7 @@
{
struct pci_dev *pdev = to_pci_dev(dev);
- return calc_devid(pdev->bus->number, pdev->devfn);
+ return PCI_DEVID(pdev->bus->number, pdev->devfn);
}
static struct iommu_dev_data *get_dev_data(struct device *dev)
@@ -649,26 +649,26 @@
case EVENT_TYPE_ILL_DEV:
printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x "
"address=0x%016llx flags=0x%04x]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
address, flags);
dump_dte_entry(devid);
break;
case EVENT_TYPE_IO_FAULT:
printk("IO_PAGE_FAULT device=%02x:%02x.%x "
"domain=0x%04x address=0x%016llx flags=0x%04x]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
domid, address, flags);
break;
case EVENT_TYPE_DEV_TAB_ERR:
printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
"address=0x%016llx flags=0x%04x]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
address, flags);
break;
case EVENT_TYPE_PAGE_TAB_ERR:
printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x "
"domain=0x%04x address=0x%016llx flags=0x%04x]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
domid, address, flags);
break;
case EVENT_TYPE_ILL_CMD:
@@ -682,13 +682,13 @@
case EVENT_TYPE_IOTLB_INV_TO:
printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x "
"address=0x%016llx]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
address);
break;
case EVENT_TYPE_INV_DEV_REQ:
printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x "
"address=0x%016llx flags=0x%04x]\n",
- PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid),
+ PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid),
address, flags);
break;
default:
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index e3c2d74..2f46881 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -406,7 +406,7 @@
u32 cap;
cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET);
- update_last_devid(calc_devid(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
+ update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap)));
return 0;
}
@@ -423,7 +423,7 @@
p += sizeof(*h);
end += h->length;
- find_last_devid_on_pci(PCI_BUS(h->devid),
+ find_last_devid_on_pci(PCI_BUS_NUM(h->devid),
PCI_SLOT(h->devid),
PCI_FUNC(h->devid),
h->cap_ptr);
@@ -784,10 +784,10 @@
DUMP_printk(" DEV_ALL\t\t\t first devid: %02x:%02x.%x"
" last device %02x:%02x.%x flags: %02x\n",
- PCI_BUS(iommu->first_device),
+ PCI_BUS_NUM(iommu->first_device),
PCI_SLOT(iommu->first_device),
PCI_FUNC(iommu->first_device),
- PCI_BUS(iommu->last_device),
+ PCI_BUS_NUM(iommu->last_device),
PCI_SLOT(iommu->last_device),
PCI_FUNC(iommu->last_device),
e->flags);
@@ -801,7 +801,7 @@
DUMP_printk(" DEV_SELECT\t\t\t devid: %02x:%02x.%x "
"flags: %02x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags);
@@ -813,7 +813,7 @@
DUMP_printk(" DEV_SELECT_RANGE_START\t "
"devid: %02x:%02x.%x flags: %02x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags);
@@ -827,11 +827,11 @@
DUMP_printk(" DEV_ALIAS\t\t\t devid: %02x:%02x.%x "
"flags: %02x devid_to: %02x:%02x.%x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags,
- PCI_BUS(e->ext >> 8),
+ PCI_BUS_NUM(e->ext >> 8),
PCI_SLOT(e->ext >> 8),
PCI_FUNC(e->ext >> 8));
@@ -846,11 +846,11 @@
DUMP_printk(" DEV_ALIAS_RANGE\t\t "
"devid: %02x:%02x.%x flags: %02x "
"devid_to: %02x:%02x.%x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags,
- PCI_BUS(e->ext >> 8),
+ PCI_BUS_NUM(e->ext >> 8),
PCI_SLOT(e->ext >> 8),
PCI_FUNC(e->ext >> 8));
@@ -864,7 +864,7 @@
DUMP_printk(" DEV_EXT_SELECT\t\t devid: %02x:%02x.%x "
"flags: %02x ext: %08x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags, e->ext);
@@ -877,7 +877,7 @@
DUMP_printk(" DEV_EXT_SELECT_RANGE\t devid: "
"%02x:%02x.%x flags: %02x ext: %08x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid),
e->flags, e->ext);
@@ -890,7 +890,7 @@
case IVHD_DEV_RANGE_END:
DUMP_printk(" DEV_RANGE_END\t\t devid: %02x:%02x.%x\n",
- PCI_BUS(e->devid),
+ PCI_BUS_NUM(e->devid),
PCI_SLOT(e->devid),
PCI_FUNC(e->devid));
@@ -924,7 +924,7 @@
DUMP_printk(" DEV_SPECIAL(%s[%d])\t\tdevid: %02x:%02x.%x\n",
var, (int)handle,
- PCI_BUS(devid),
+ PCI_BUS_NUM(devid),
PCI_SLOT(devid),
PCI_FUNC(devid));
@@ -1086,7 +1086,7 @@
DUMP_printk("device: %02x:%02x.%01x cap: %04x "
"seg: %d flags: %01x info %04x\n",
- PCI_BUS(h->devid), PCI_SLOT(h->devid),
+ PCI_BUS_NUM(h->devid), PCI_SLOT(h->devid),
PCI_FUNC(h->devid), h->cap_ptr,
h->pci_seg, h->flags, h->info);
DUMP_printk(" mmio-addr: %016llx\n",
@@ -1116,7 +1116,7 @@
int cap_ptr = iommu->cap_ptr;
u32 range, misc, low, high;
- iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid),
+ iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid),
iommu->devid & 0xff);
if (!iommu->dev)
return -ENODEV;
@@ -1128,9 +1128,9 @@
pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET,
&misc);
- iommu->first_device = calc_devid(MMIO_GET_BUS(range),
+ iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range),
MMIO_GET_FD(range));
- iommu->last_device = calc_devid(MMIO_GET_BUS(range),
+ iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range),
MMIO_GET_LD(range));
if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB)))
@@ -1388,8 +1388,8 @@
DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x"
" range_start: %016llx range_end: %016llx flags: %x\n", s,
- PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start),
- PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end),
+ PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start),
+ PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end),
PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end),
e->address_start, e->address_end, m->flags);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index e38ab43..ec36cf6 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -24,6 +24,7 @@
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/spinlock.h>
+#include <linux/pci.h>
/*
* Maximum number of IOMMUs supported
@@ -315,9 +316,6 @@
#define MAX_DOMAIN_ID 65536
-/* FIXME: move this macro to <linux/pci.h> */
-#define PCI_BUS(x) (((x) >> 8) & 0xff)
-
/* Protection domain flags */
#define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */
#define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops
@@ -703,13 +701,6 @@
*/
extern void iommu_flush_all_caches(struct amd_iommu *iommu);
-/* takes bus and device/function and returns the device id
- * FIXME: should that be in generic PCI code? */
-static inline u16 calc_devid(u8 bus, u8 devfn)
-{
- return (((u16)bus) << 8) | devfn;
-}
-
static inline int get_ioapic_devid(int id)
{
struct devid_map *entry;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index a32e0d5..fc6aebf 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -236,7 +236,8 @@
if (gic_arch_extn.irq_retrigger)
return gic_arch_extn.irq_retrigger(d);
- return -ENXIO;
+ /* the genirq layer expects 0 if we can't retrigger in hardware */
+ return 0;
}
#ifdef CONFIG_SMP
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7e46926..9a0bdad 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -611,6 +611,7 @@
queue_io(md, bio);
} else {
/* done with normal IO or empty flush */
+ trace_block_bio_complete(md->queue, bio, io_error);
bio_endio(bio, io_error);
}
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 24909eb..f4e87bf 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -184,6 +184,8 @@
return_bi = bi->bi_next;
bi->bi_next = NULL;
bi->bi_size = 0;
+ trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+ bi, 0);
bio_endio(bi, 0);
bi = return_bi;
}
@@ -3914,6 +3916,8 @@
rdev_dec_pending(rdev, conf->mddev);
if (!error && uptodate) {
+ trace_block_bio_complete(bdev_get_queue(raid_bi->bi_bdev),
+ raid_bi, 0);
bio_endio(raid_bi, 0);
if (atomic_dec_and_test(&conf->active_aligned_reads))
wake_up(&conf->wait_for_stripe);
@@ -4382,6 +4386,8 @@
if ( rw == WRITE )
md_write_end(mddev);
+ trace_block_bio_complete(bdev_get_queue(bi->bi_bdev),
+ bi, 0);
bio_endio(bi, 0);
}
}
@@ -4758,8 +4764,11 @@
handled++;
}
remaining = raid5_dec_bi_active_stripes(raid_bio);
- if (remaining == 0)
+ if (remaining == 0) {
+ trace_block_bio_complete(bdev_get_queue(raid_bio->bi_bdev),
+ raid_bio, 0);
bio_endio(raid_bio, 0);
+ }
if (atomic_dec_and_test(&conf->active_aligned_reads))
wake_up(&conf->wait_for_stripe);
return handled;
diff --git a/drivers/media/dvb-frontends/mb86a20s.c b/drivers/media/dvb-frontends/mb86a20s.c
index f19cd73..4faaf80 100644
--- a/drivers/media/dvb-frontends/mb86a20s.c
+++ b/drivers/media/dvb-frontends/mb86a20s.c
@@ -610,7 +610,7 @@
__func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000,
rate, rate);
- state->estimated_rate[i] = rate;
+ state->estimated_rate[layer] = rate;
}
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index d4de021..31ce769 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -461,7 +461,7 @@
spin_lock_init(&dev->slock);
- for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) {
+ for (i = 0; i < VID_CHANNEL_NUM; ++i) {
cx25821_init_controls(dev, i);
cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper,
diff --git a/drivers/misc/vmw_vmci/Kconfig b/drivers/misc/vmw_vmci/Kconfig
index 39c2eca..ea98f7e 100644
--- a/drivers/misc/vmw_vmci/Kconfig
+++ b/drivers/misc/vmw_vmci/Kconfig
@@ -4,7 +4,7 @@
config VMWARE_VMCI
tristate "VMware VMCI Driver"
- depends on X86 && PCI
+ depends on X86 && PCI && NET
help
This is VMware's Virtual Machine Communication Interface. It enables
high-speed communication between host and guest in a virtual
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 92ab30a..dc571eb 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1123,33 +1123,6 @@
}
#endif
-static inline unsigned long get_vm_size(struct vm_area_struct *vma)
-{
- return vma->vm_end - vma->vm_start;
-}
-
-static inline resource_size_t get_vm_offset(struct vm_area_struct *vma)
-{
- return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT;
-}
-
-/*
- * Set a new vm offset.
- *
- * Verify that the incoming offset really works as a page offset,
- * and that the offset and size fit in a resource_size_t.
- */
-static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off)
-{
- pgoff_t pgoff = off >> PAGE_SHIFT;
- if (off != (resource_size_t) pgoff << PAGE_SHIFT)
- return -EINVAL;
- if (off + get_vm_size(vma) - 1 < off)
- return -EINVAL;
- vma->vm_pgoff = pgoff;
- return 0;
-}
-
/*
* set up a mapping for shared memory segments
*/
@@ -1159,45 +1132,17 @@
struct mtd_file_info *mfi = file->private_data;
struct mtd_info *mtd = mfi->mtd;
struct map_info *map = mtd->priv;
- resource_size_t start, off;
- unsigned long len, vma_len;
/* This is broken because it assumes the MTD device is map-based
and that mtd->priv is a valid struct map_info. It should be
replaced with something that uses the mtd_get_unmapped_area()
operation properly. */
if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) {
- off = get_vm_offset(vma);
- start = map->phys;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
- start &= PAGE_MASK;
- vma_len = get_vm_size(vma);
-
- /* Overflow in off+len? */
- if (vma_len + off < off)
- return -EINVAL;
- /* Does it fit in the mapping? */
- if (vma_len + off > len)
- return -EINVAL;
-
- off += start;
- /* Did that overflow? */
- if (off < start)
- return -EINVAL;
- if (set_vm_offset(vma, off) < 0)
- return -EINVAL;
- vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
-
#ifdef pgprot_noncached
- if (file->f_flags & O_DSYNC || off >= __pa(high_memory))
+ if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory))
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif
- if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
+ return vm_iomap_memory(vma, map->phys, map->size);
}
return -ENOSYS;
#else
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 171b10f1..dbbea0e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -846,8 +846,10 @@
if (bond->dev->flags & IFF_ALLMULTI)
dev_set_allmulti(old_active->dev, -1);
+ netif_addr_lock_bh(bond->dev);
netdev_for_each_mc_addr(ha, bond->dev)
dev_mc_del(old_active->dev, ha->addr);
+ netif_addr_unlock_bh(bond->dev);
}
if (new_active) {
@@ -858,8 +860,10 @@
if (bond->dev->flags & IFF_ALLMULTI)
dev_set_allmulti(new_active->dev, 1);
+ netif_addr_lock_bh(bond->dev);
netdev_for_each_mc_addr(ha, bond->dev)
dev_mc_add(new_active->dev, ha->addr);
+ netif_addr_unlock_bh(bond->dev);
}
}
@@ -1901,11 +1905,29 @@
bond_destroy_slave_symlinks(bond_dev, slave_dev);
err_detach:
+ if (!USES_PRIMARY(bond->params.mode)) {
+ netif_addr_lock_bh(bond_dev);
+ bond_mc_list_flush(bond_dev, slave_dev);
+ netif_addr_unlock_bh(bond_dev);
+ }
+ bond_del_vlans_from_slave(bond, slave_dev);
write_lock_bh(&bond->lock);
bond_detach_slave(bond, new_slave);
+ if (bond->primary_slave == new_slave)
+ bond->primary_slave = NULL;
write_unlock_bh(&bond->lock);
+ if (bond->curr_active_slave == new_slave) {
+ read_lock(&bond->lock);
+ write_lock_bh(&bond->curr_slave_lock);
+ bond_change_active_slave(bond, NULL);
+ bond_select_active_slave(bond);
+ write_unlock_bh(&bond->curr_slave_lock);
+ read_unlock(&bond->lock);
+ }
+ slave_disable_netpoll(new_slave);
err_close:
+ slave_dev->priv_flags &= ~IFF_BONDING;
dev_close(slave_dev);
err_unset_master:
@@ -3168,11 +3190,20 @@
struct net_device *slave_dev)
{
struct slave *slave = bond_slave_get_rtnl(slave_dev);
- struct bonding *bond = slave->bond;
- struct net_device *bond_dev = slave->bond->dev;
+ struct bonding *bond;
+ struct net_device *bond_dev;
u32 old_speed;
u8 old_duplex;
+ /* A netdev event can be generated while enslaving a device
+ * before netdev_rx_handler_register is called in which case
+ * slave will be NULL
+ */
+ if (!slave)
+ return NOTIFY_DONE;
+ bond_dev = slave->bond->dev;
+ bond = slave->bond;
+
switch (event) {
case NETDEV_UNREGISTER:
if (bond->setup_by_slave)
@@ -3286,20 +3317,22 @@
*/
static int bond_xmit_hash_policy_l23(struct sk_buff *skb, int count)
{
- struct ethhdr *data = (struct ethhdr *)skb->data;
- struct iphdr *iph;
- struct ipv6hdr *ipv6h;
+ const struct ethhdr *data;
+ const struct iphdr *iph;
+ const struct ipv6hdr *ipv6h;
u32 v6hash;
- __be32 *s, *d;
+ const __be32 *s, *d;
if (skb->protocol == htons(ETH_P_IP) &&
- skb_network_header_len(skb) >= sizeof(*iph)) {
+ pskb_network_may_pull(skb, sizeof(*iph))) {
iph = ip_hdr(skb);
+ data = (struct ethhdr *)skb->data;
return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
(data->h_dest[5] ^ data->h_source[5])) % count;
} else if (skb->protocol == htons(ETH_P_IPV6) &&
- skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+ pskb_network_may_pull(skb, sizeof(*ipv6h))) {
ipv6h = ipv6_hdr(skb);
+ data = (struct ethhdr *)skb->data;
s = &ipv6h->saddr.s6_addr32[0];
d = &ipv6h->daddr.s6_addr32[0];
v6hash = (s[1] ^ d[1]) ^ (s[2] ^ d[2]) ^ (s[3] ^ d[3]);
@@ -3318,33 +3351,36 @@
static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
{
u32 layer4_xor = 0;
- struct iphdr *iph;
- struct ipv6hdr *ipv6h;
- __be32 *s, *d;
- __be16 *layer4hdr;
+ const struct iphdr *iph;
+ const struct ipv6hdr *ipv6h;
+ const __be32 *s, *d;
+ const __be16 *l4 = NULL;
+ __be16 _l4[2];
+ int noff = skb_network_offset(skb);
+ int poff;
if (skb->protocol == htons(ETH_P_IP) &&
- skb_network_header_len(skb) >= sizeof(*iph)) {
+ pskb_may_pull(skb, noff + sizeof(*iph))) {
iph = ip_hdr(skb);
- if (!ip_is_fragment(iph) &&
- (iph->protocol == IPPROTO_TCP ||
- iph->protocol == IPPROTO_UDP) &&
- (skb_headlen(skb) - skb_network_offset(skb) >=
- iph->ihl * sizeof(u32) + sizeof(*layer4hdr) * 2)) {
- layer4hdr = (__be16 *)((u32 *)iph + iph->ihl);
- layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+ poff = proto_ports_offset(iph->protocol);
+
+ if (!ip_is_fragment(iph) && poff >= 0) {
+ l4 = skb_header_pointer(skb, noff + (iph->ihl << 2) + poff,
+ sizeof(_l4), &_l4);
+ if (l4)
+ layer4_xor = ntohs(l4[0] ^ l4[1]);
}
return (layer4_xor ^
((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
} else if (skb->protocol == htons(ETH_P_IPV6) &&
- skb_network_header_len(skb) >= sizeof(*ipv6h)) {
+ pskb_may_pull(skb, noff + sizeof(*ipv6h))) {
ipv6h = ipv6_hdr(skb);
- if ((ipv6h->nexthdr == IPPROTO_TCP ||
- ipv6h->nexthdr == IPPROTO_UDP) &&
- (skb_headlen(skb) - skb_network_offset(skb) >=
- sizeof(*ipv6h) + sizeof(*layer4hdr) * 2)) {
- layer4hdr = (__be16 *)(ipv6h + 1);
- layer4_xor = ntohs(*layer4hdr ^ *(layer4hdr + 1));
+ poff = proto_ports_offset(ipv6h->nexthdr);
+ if (poff >= 0) {
+ l4 = skb_header_pointer(skb, noff + sizeof(*ipv6h) + poff,
+ sizeof(_l4), &_l4);
+ if (l4)
+ layer4_xor = ntohs(l4[0] ^ l4[1]);
}
s = &ipv6h->saddr.s6_addr32[0];
d = &ipv6h->daddr.s6_addr32[0];
@@ -4846,9 +4882,18 @@
static void __net_exit bond_net_exit(struct net *net)
{
struct bond_net *bn = net_generic(net, bond_net_id);
+ struct bonding *bond, *tmp_bond;
+ LIST_HEAD(list);
bond_destroy_sysfs(bn);
bond_destroy_proc_dir(bn);
+
+ /* Kill off any bonds created after unregistering bond rtnl ops */
+ rtnl_lock();
+ list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list)
+ unregister_netdevice_queue(bond->dev, &list);
+ unregister_netdevice_many(&list);
+ rtnl_unlock();
}
static struct pernet_operations bond_net_ops = {
@@ -4902,8 +4947,8 @@
bond_destroy_debugfs();
- unregister_pernet_subsys(&bond_net_ops);
rtnl_link_unregister(&bond_link_ops);
+ unregister_pernet_subsys(&bond_net_ops);
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c
index f32b9fc..9aa0c64 100644
--- a/drivers/net/can/mcp251x.c
+++ b/drivers/net/can/mcp251x.c
@@ -929,6 +929,7 @@
struct mcp251x_priv *priv = netdev_priv(net);
struct spi_device *spi = priv->spi;
struct mcp251x_platform_data *pdata = spi->dev.platform_data;
+ unsigned long flags;
int ret;
ret = open_candev(net);
@@ -945,9 +946,14 @@
priv->tx_skb = NULL;
priv->tx_len = 0;
+ flags = IRQF_ONESHOT;
+ if (pdata->irq_flags)
+ flags |= pdata->irq_flags;
+ else
+ flags |= IRQF_TRIGGER_FALLING;
+
ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
- pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
- DEVICE_NAME, priv);
+ flags, DEVICE_NAME, priv);
if (ret) {
dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
if (pdata->transceiver_enable)
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c
index 6433b81..8e0c4a0 100644
--- a/drivers/net/can/sja1000/sja1000_of_platform.c
+++ b/drivers/net/can/sja1000/sja1000_of_platform.c
@@ -96,8 +96,8 @@
struct net_device *dev;
struct sja1000_priv *priv;
struct resource res;
- const u32 *prop;
- int err, irq, res_size, prop_size;
+ u32 prop;
+ int err, irq, res_size;
void __iomem *base;
err = of_address_to_resource(np, 0, &res);
@@ -138,27 +138,27 @@
priv->read_reg = sja1000_ofp_read_reg;
priv->write_reg = sja1000_ofp_write_reg;
- prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->can.clock.freq = *prop / 2;
+ err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop);
+ if (!err)
+ priv->can.clock.freq = prop / 2;
else
priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */
- prop = of_get_property(np, "nxp,tx-output-mode", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= *prop & OCR_MODE_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-mode", &prop);
+ if (!err)
+ priv->ocr |= prop & OCR_MODE_MASK;
else
priv->ocr |= OCR_MODE_NORMAL; /* default */
- prop = of_get_property(np, "nxp,tx-output-config", &prop_size);
- if (prop && (prop_size == sizeof(u32)))
- priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK;
+ err = of_property_read_u32(np, "nxp,tx-output-config", &prop);
+ if (!err)
+ priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK;
else
priv->ocr |= OCR_TX0_PULLDOWN; /* default */
- prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size);
- if (prop && (prop_size == sizeof(u32)) && *prop) {
- u32 divider = priv->can.clock.freq * 2 / *prop;
+ err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop);
+ if (!err && prop) {
+ u32 divider = priv->can.clock.freq * 2 / prop;
if (divider > 1)
priv->cdr |= divider / 2 - 1;
@@ -168,8 +168,7 @@
priv->cdr |= CDR_CLK_OFF; /* default */
}
- prop = of_get_property(np, "nxp,no-comparator-bypass", NULL);
- if (!prop)
+ if (!of_property_read_bool(np, "nxp,no-comparator-bypass"))
priv->cdr |= CDR_CBP; /* default */
priv->irq_flags = IRQF_SHARED;
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
index cab306a..e1d2643 100644
--- a/drivers/net/ethernet/8390/ax88796.c
+++ b/drivers/net/ethernet/8390/ax88796.c
@@ -828,7 +828,7 @@
struct ei_device *ei_local;
struct ax_device *ax;
struct resource *irq, *mem, *mem2;
- resource_size_t mem_size, mem2_size = 0;
+ unsigned long mem_size, mem2_size = 0;
int ret = 0;
dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 4046f97..57619dd 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2614,6 +2614,9 @@
}
}
+ /* initialize FW coalescing state machines in RAM */
+ bnx2x_update_coalesce(bp);
+
/* setup the leading queue */
rc = bnx2x_setup_leading(bp);
if (rc) {
@@ -4580,11 +4583,11 @@
u32 enable_flag = disable ? 0 : (1 << HC_INDEX_DATA_HC_ENABLED_SHIFT);
u32 addr = BAR_CSTRORM_INTMEM +
CSTORM_STATUS_BLOCK_DATA_FLAGS_OFFSET(fw_sb_id, sb_index);
- u16 flags = REG_RD16(bp, addr);
+ u8 flags = REG_RD8(bp, addr);
/* clear and set */
flags &= ~HC_INDEX_DATA_HC_ENABLED;
flags |= enable_flag;
- REG_WR16(bp, addr, flags);
+ REG_WR8(bp, addr, flags);
DP(NETIF_MSG_IFUP,
"port %x fw_sb_id %d sb_index %d disable %d\n",
port, fw_sb_id, sb_index, disable);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index 77ebae0..0283f34 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -13437,13 +13437,7 @@
{
struct bnx2x *bp = params->bp;
u16 base_page, next_page, not_kr2_device, lane;
- int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
-
- if (!sigdet) {
- if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
- bnx2x_kr2_recovery(params, vars, phy);
- return;
- }
+ int sigdet;
/* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
* since some switches tend to reinit the AN process and clear the
@@ -13454,6 +13448,16 @@
vars->check_kr2_recovery_cnt--;
return;
}
+
+ sigdet = bnx2x_warpcore_get_sigdet(phy, params);
+ if (!sigdet) {
+ if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+ bnx2x_kr2_recovery(params, vars, phy);
+ DP(NETIF_MSG_LINK, "No sigdet\n");
+ }
+ return;
+ }
+
lane = bnx2x_get_warpcore_lane(phy, params);
CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
MDIO_AER_BLOCK_AER_REG, lane);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index e81a747..c50696b 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -4947,7 +4947,7 @@
q);
}
- if (!NO_FCOE(bp)) {
+ if (!NO_FCOE(bp) && CNIC_ENABLED(bp)) {
fp = &bp->fp[FCOE_IDX(bp)];
queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
@@ -9878,6 +9878,10 @@
REG_RD(bp, NIG_REG_NIG_INT_STS_CLR_0);
}
}
+ if (!CHIP_IS_E1x(bp))
+ /* block FW from writing to host */
+ REG_WR(bp, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
+
/* wait until BRB is empty */
tmp_reg = REG_RD(bp, BRB1_REG_NUM_OF_FULL_BLOCKS);
while (timer_count) {
@@ -13354,6 +13358,7 @@
RCU_INIT_POINTER(bp->cnic_ops, NULL);
mutex_unlock(&bp->cnic_mutex);
synchronize_rcu();
+ bp->cnic_enabled = false;
kfree(bp->cnic_kwq);
bp->cnic_kwq = NULL;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 08e54f3..2886c9b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -759,8 +759,9 @@
if (vlan_tx_tag_present(skb)) {
vlan_tag = be_get_tx_vlan_tag(adapter, skb);
- __vlan_put_tag(skb, vlan_tag);
- skb->vlan_tci = 0;
+ skb = __vlan_put_tag(skb, vlan_tag);
+ if (skb)
+ skb->vlan_tci = 0;
}
return skb;
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
index f292c3a..73195f6 100644
--- a/drivers/net/ethernet/freescale/fec.c
+++ b/drivers/net/ethernet/freescale/fec.c
@@ -1002,6 +1002,7 @@
} else {
if (fep->link) {
fec_stop(ndev);
+ fep->link = phy_dev->link;
status_change = 1;
}
}
diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c
index ec800b0..d2bea3f 100644
--- a/drivers/net/ethernet/intel/e100.c
+++ b/drivers/net/ethernet/intel/e100.c
@@ -870,7 +870,7 @@
}
static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
- void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
+ int (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
{
struct cb *cb;
unsigned long flags;
@@ -888,10 +888,13 @@
nic->cbs_avail--;
cb->skb = skb;
+ err = cb_prepare(nic, cb, skb);
+ if (err)
+ goto err_unlock;
+
if (unlikely(!nic->cbs_avail))
err = -ENOSPC;
- cb_prepare(nic, cb, skb);
/* Order is important otherwise we'll be in a race with h/w:
* set S-bit in current first, then clear S-bit in previous. */
@@ -1091,7 +1094,7 @@
nic->mii.mdio_write = mdio_write;
}
-static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
struct config *config = &cb->u.config;
u8 *c = (u8 *)config;
@@ -1181,6 +1184,7 @@
netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
"[16-23]=%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+ return 0;
}
/*************************************************************************
@@ -1331,7 +1335,7 @@
return fw;
}
-static void e100_setup_ucode(struct nic *nic, struct cb *cb,
+static int e100_setup_ucode(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
const struct firmware *fw = (void *)skb;
@@ -1358,6 +1362,7 @@
cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
cb->command = cpu_to_le16(cb_ucode | cb_el);
+ return 0;
}
static inline int e100_load_ucode_wait(struct nic *nic)
@@ -1400,18 +1405,20 @@
return err;
}
-static void e100_setup_iaaddr(struct nic *nic, struct cb *cb,
+static int e100_setup_iaaddr(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = cpu_to_le16(cb_iaaddr);
memcpy(cb->u.iaaddr, nic->netdev->dev_addr, ETH_ALEN);
+ return 0;
}
-static void e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_dump(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
cb->command = cpu_to_le16(cb_dump);
cb->u.dump_buffer_addr = cpu_to_le32(nic->dma_addr +
offsetof(struct mem, dump_buf));
+ return 0;
}
static int e100_phy_check_without_mii(struct nic *nic)
@@ -1581,7 +1588,7 @@
return 0;
}
-static void e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+static int e100_multi(struct nic *nic, struct cb *cb, struct sk_buff *skb)
{
struct net_device *netdev = nic->netdev;
struct netdev_hw_addr *ha;
@@ -1596,6 +1603,7 @@
memcpy(&cb->u.multi.addr[i++ * ETH_ALEN], &ha->addr,
ETH_ALEN);
}
+ return 0;
}
static void e100_set_multicast_list(struct net_device *netdev)
@@ -1756,11 +1764,18 @@
round_jiffies(jiffies + E100_WATCHDOG_PERIOD));
}
-static void e100_xmit_prepare(struct nic *nic, struct cb *cb,
+static int e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
+ dma_addr_t dma_addr;
cb->command = nic->tx_command;
+ dma_addr = pci_map_single(nic->pdev,
+ skb->data, skb->len, PCI_DMA_TODEVICE);
+ /* If we can't map the skb, have the upper layer try later */
+ if (pci_dma_mapping_error(nic->pdev, dma_addr))
+ return -ENOMEM;
+
/*
* Use the last 4 bytes of the SKB payload packet as the CRC, used for
* testing, ie sending frames with bad CRC.
@@ -1777,11 +1792,10 @@
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
- cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
- skb->data, skb->len, PCI_DMA_TODEVICE));
- /* check for mapping failure? */
+ cb->u.tcb.tbd.buf_addr = cpu_to_le32(dma_addr);
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
skb_tx_timestamp(skb);
+ return 0;
}
static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 2515140..ab577a7 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -284,18 +284,10 @@
enum e1000_ring_flags_t {
IGB_RING_FLAG_RX_SCTP_CSUM,
IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
- IGB_RING_FLAG_RX_BUILD_SKB_ENABLED,
IGB_RING_FLAG_TX_CTX_IDX,
IGB_RING_FLAG_TX_DETECT_HANG
};
-#define ring_uses_build_skb(ring) \
- test_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-#define set_ring_build_skb_enabled(ring) \
- set_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-#define clear_ring_build_skb_enabled(ring) \
- clear_bit(IGB_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
-
#define IGB_TXD_DCMD (E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_RS)
#define IGB_RX_DESC(R, i) \
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 8496adf..64f7529 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3350,20 +3350,6 @@
wr32(E1000_RXDCTL(reg_idx), rxdctl);
}
-static void igb_set_rx_buffer_len(struct igb_adapter *adapter,
- struct igb_ring *rx_ring)
-{
-#define IGB_MAX_BUILD_SKB_SIZE \
- (SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) - \
- (NET_SKB_PAD + NET_IP_ALIGN + IGB_TS_HDR_LEN))
-
- /* set build_skb flag */
- if (adapter->max_frame_size <= IGB_MAX_BUILD_SKB_SIZE)
- set_ring_build_skb_enabled(rx_ring);
- else
- clear_ring_build_skb_enabled(rx_ring);
-}
-
/**
* igb_configure_rx - Configure receive Unit after Reset
* @adapter: board private structure
@@ -3383,11 +3369,8 @@
/* Setup the HW Rx Head and Tail Descriptor Pointers and
* the Base and Length of the Rx Descriptor Ring */
- for (i = 0; i < adapter->num_rx_queues; i++) {
- struct igb_ring *rx_ring = adapter->rx_ring[i];
- igb_set_rx_buffer_len(adapter, rx_ring);
- igb_configure_rx_ring(adapter, rx_ring);
- }
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ igb_configure_rx_ring(adapter, adapter->rx_ring[i]);
}
/**
@@ -6203,78 +6186,6 @@
return igb_can_reuse_rx_page(rx_buffer, page, truesize);
}
-static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
- union e1000_adv_rx_desc *rx_desc)
-{
- struct igb_rx_buffer *rx_buffer;
- struct sk_buff *skb;
- struct page *page;
- void *page_addr;
- unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
-#if (PAGE_SIZE < 8192)
- unsigned int truesize = IGB_RX_BUFSZ;
-#else
- unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
- SKB_DATA_ALIGN(NET_SKB_PAD +
- NET_IP_ALIGN +
- size);
-#endif
-
- /* If we spanned a buffer we have a huge mess so test for it */
- BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)));
-
- rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
- page = rx_buffer->page;
- prefetchw(page);
-
- page_addr = page_address(page) + rx_buffer->page_offset;
-
- /* prefetch first cache line of first page */
- prefetch(page_addr + NET_SKB_PAD + NET_IP_ALIGN);
-#if L1_CACHE_BYTES < 128
- prefetch(page_addr + L1_CACHE_BYTES + NET_SKB_PAD + NET_IP_ALIGN);
-#endif
-
- /* build an skb to around the page buffer */
- skb = build_skb(page_addr, truesize);
- if (unlikely(!skb)) {
- rx_ring->rx_stats.alloc_failed++;
- return NULL;
- }
-
- /* we are reusing so sync this buffer for CPU use */
- dma_sync_single_range_for_cpu(rx_ring->dev,
- rx_buffer->dma,
- rx_buffer->page_offset,
- IGB_RX_BUFSZ,
- DMA_FROM_DEVICE);
-
- /* update pointers within the skb to store the data */
- skb_reserve(skb, NET_IP_ALIGN + NET_SKB_PAD);
- __skb_put(skb, size);
-
- /* pull timestamp out of packet data */
- if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
- igb_ptp_rx_pktstamp(rx_ring->q_vector, skb->data, skb);
- __skb_pull(skb, IGB_TS_HDR_LEN);
- }
-
- if (igb_can_reuse_rx_page(rx_buffer, page, truesize)) {
- /* hand second half of page back to the ring */
- igb_reuse_rx_page(rx_ring, rx_buffer);
- } else {
- /* we are not reusing the buffer so unmap it */
- dma_unmap_page(rx_ring->dev, rx_buffer->dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
- }
-
- /* clear contents of buffer_info */
- rx_buffer->dma = 0;
- rx_buffer->page = NULL;
-
- return skb;
-}
-
static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
@@ -6690,10 +6601,7 @@
rmb();
/* retrieve a buffer from the ring */
- if (ring_uses_build_skb(rx_ring))
- skb = igb_build_rx_buffer(rx_ring, rx_desc);
- else
- skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
+ skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
/* exit if we failed to retrieve a buffer */
if (!skb)
@@ -6780,14 +6688,6 @@
return true;
}
-static inline unsigned int igb_rx_offset(struct igb_ring *rx_ring)
-{
- if (ring_uses_build_skb(rx_ring))
- return NET_SKB_PAD + NET_IP_ALIGN;
- else
- return 0;
-}
-
/**
* igb_alloc_rx_buffers - Replace used receive buffers; packet split
* @adapter: address of board private structure
@@ -6814,9 +6714,7 @@
* Refresh the desc even if buffer_addrs didn't change
* because each write-back erases this info.
*/
- rx_desc->read.pkt_addr = cpu_to_le64(bi->dma +
- bi->page_offset +
- igb_rx_offset(rx_ring));
+ rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
rx_desc++;
bi++;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index d44b4d2..97e3366 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1049,6 +1049,12 @@
if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7))
return -EINVAL;
if (vlan || qos) {
+ if (adapter->vfinfo[vf].pf_vlan)
+ err = ixgbe_set_vf_vlan(adapter, false,
+ adapter->vfinfo[vf].pf_vlan,
+ vf);
+ if (err)
+ goto out;
err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
if (err)
goto out;
diff --git a/drivers/net/ethernet/marvell/Kconfig b/drivers/net/ethernet/marvell/Kconfig
index edfba93..434e33c 100644
--- a/drivers/net/ethernet/marvell/Kconfig
+++ b/drivers/net/ethernet/marvell/Kconfig
@@ -33,6 +33,7 @@
config MVMDIO
tristate "Marvell MDIO interface support"
+ select PHYLIB
---help---
This driver supports the MDIO interface found in the network
interface units of the Marvell EBU SoCs (Kirkwood, Orion5x,
@@ -45,7 +46,6 @@
config MVNETA
tristate "Marvell Armada 370/XP network interface support"
depends on MACH_ARMADA_370_XP
- select PHYLIB
select MVMDIO
---help---
This driver supports the network interface units in the
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index cd345b8..a47a097 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -374,7 +374,6 @@
static int txq_number = 8;
static int rxq_def;
-static int txq_def;
#define MVNETA_DRIVER_NAME "mvneta"
#define MVNETA_DRIVER_VERSION "1.0"
@@ -1475,7 +1474,8 @@
static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
{
struct mvneta_port *pp = netdev_priv(dev);
- struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
+ u16 txq_id = skb_get_queue_mapping(skb);
+ struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
struct mvneta_tx_desc *tx_desc;
struct netdev_queue *nq;
int frags = 0;
@@ -1485,7 +1485,7 @@
goto out;
frags = skb_shinfo(skb)->nr_frags + 1;
- nq = netdev_get_tx_queue(dev, txq_def);
+ nq = netdev_get_tx_queue(dev, txq_id);
/* Get a descriptor for the first part of the packet */
tx_desc = mvneta_txq_next_desc_get(txq);
@@ -2689,7 +2689,7 @@
return -EINVAL;
}
- dev = alloc_etherdev_mq(sizeof(struct mvneta_port), 8);
+ dev = alloc_etherdev_mqs(sizeof(struct mvneta_port), txq_number, rxq_number);
if (!dev)
return -ENOMEM;
@@ -2771,16 +2771,17 @@
netif_napi_add(dev, &pp->napi, mvneta_poll, pp->weight);
+ dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
+ dev->hw_features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ dev->vlan_features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ dev->priv_flags |= IFF_UNICAST_FLT;
+
err = register_netdev(dev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register\n");
goto err_deinit;
}
- dev->features = NETIF_F_SG | NETIF_F_IP_CSUM;
- dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM;
- dev->priv_flags |= IFF_UNICAST_FLT;
-
netdev_info(dev, "mac: %pM\n", dev->dev_addr);
platform_set_drvdata(pdev, pp->dev);
@@ -2843,4 +2844,3 @@
module_param(txq_number, int, S_IRUGO);
module_param(rxq_def, int, S_IRUGO);
-module_param(txq_def, int, S_IRUGO);
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index cd5ae88..edd63f1 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -1500,6 +1500,12 @@
}
} while ((adapter->ahw->linkup && ahw->has_link_events) != 1);
+ /* Make sure carrier is off and queue is stopped during loopback */
+ if (netif_running(netdev)) {
+ netif_carrier_off(netdev);
+ netif_stop_queue(netdev);
+ }
+
ret = qlcnic_do_lb_test(adapter, mode);
qlcnic_83xx_clear_lb_mode(adapter, mode);
@@ -2780,6 +2786,7 @@
void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data)
{
struct qlcnic_cmd_args cmd;
+ struct net_device *netdev = adapter->netdev;
int ret = 0;
qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS);
@@ -2789,7 +2796,7 @@
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
QLC_83XX_STAT_TX, &ret);
if (ret) {
- dev_info(&adapter->pdev->dev, "Error getting MAC stats\n");
+ netdev_err(netdev, "Error getting Tx stats\n");
goto out;
}
/* Get MAC stats */
@@ -2799,8 +2806,7 @@
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
QLC_83XX_STAT_MAC, &ret);
if (ret) {
- dev_info(&adapter->pdev->dev,
- "Error getting Rx stats\n");
+ netdev_err(netdev, "Error getting MAC stats\n");
goto out;
}
/* Get Rx stats */
@@ -2810,8 +2816,7 @@
data = qlcnic_83xx_fill_stats(adapter, &cmd, data,
QLC_83XX_STAT_RX, &ret);
if (ret)
- dev_info(&adapter->pdev->dev,
- "Error getting Tx stats\n");
+ netdev_err(netdev, "Error getting Rx stats\n");
out:
qlcnic_free_mbx_args(&cmd);
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
index 0e63006..5fa847f 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
@@ -358,8 +358,7 @@
memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
}
opcode = TX_ETHER_PKT;
- if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
- skb_shinfo(skb)->gso_size > 0) {
+ if (skb_is_gso(skb)) {
hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
first_desc->total_hdr_length = hdr_len;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 987fb6f..5ef328a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -200,10 +200,10 @@
}
err = qlcnic_config_led(adapter, b_state, b_rate);
- if (!err)
+ if (!err) {
err = len;
- else
ahw->beacon_state = b_state;
+ }
if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h
index a131d7b..7e8d682 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge.h
+++ b/drivers/net/ethernet/qlogic/qlge/qlge.h
@@ -18,7 +18,7 @@
*/
#define DRV_NAME "qlge"
#define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver "
-#define DRV_VERSION "v1.00.00.31"
+#define DRV_VERSION "v1.00.00.32"
#define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
index 6f316ab..0780e03 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c
@@ -379,13 +379,13 @@
ecmd->supported = SUPPORTED_10000baseT_Full;
ecmd->advertising = ADVERTISED_10000baseT_Full;
- ecmd->autoneg = AUTONEG_ENABLE;
ecmd->transceiver = XCVR_EXTERNAL;
if ((qdev->link_status & STS_LINK_TYPE_MASK) ==
STS_LINK_TYPE_10GBASET) {
ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
ecmd->advertising |= (ADVERTISED_TP | ADVERTISED_Autoneg);
ecmd->port = PORT_TP;
+ ecmd->autoneg = AUTONEG_ENABLE;
} else {
ecmd->supported |= SUPPORTED_FIBRE;
ecmd->advertising |= ADVERTISED_FIBRE;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b13ab54..8033555 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -1434,11 +1434,13 @@
}
/* Categorizing receive firmware frame errors */
-static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err)
+static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err,
+ struct rx_ring *rx_ring)
{
struct nic_stats *stats = &qdev->nic_stats;
stats->rx_err_count++;
+ rx_ring->rx_errors++;
switch (rx_err & IB_MAC_IOCB_RSP_ERR_MASK) {
case IB_MAC_IOCB_RSP_ERR_CODE_ERR:
@@ -1474,6 +1476,12 @@
struct bq_desc *lbq_desc = ql_get_curr_lchunk(qdev, rx_ring);
struct napi_struct *napi = &rx_ring->napi;
+ /* Frame error, so drop the packet. */
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+ ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+ put_page(lbq_desc->p.pg_chunk.page);
+ return;
+ }
napi->dev = qdev->ndev;
skb = napi_get_frags(napi);
@@ -1529,6 +1537,12 @@
addr = lbq_desc->p.pg_chunk.va;
prefetch(addr);
+ /* Frame error, so drop the packet. */
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+ ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+ goto err_out;
+ }
+
/* The max framesize filter on this chip is set higher than
* MTU since FCoE uses 2k frames.
*/
@@ -1614,6 +1628,13 @@
memcpy(skb_put(new_skb, length), skb->data, length);
skb = new_skb;
+ /* Frame error, so drop the packet. */
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+ ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
/* loopback self test for ethtool */
if (test_bit(QL_SELFTEST, &qdev->flags)) {
ql_check_lb_frame(qdev, skb);
@@ -1919,6 +1940,13 @@
return;
}
+ /* Frame error, so drop the packet. */
+ if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
+ ql_categorize_rx_err(qdev, ib_mac_rsp->flags2, rx_ring);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
/* The max framesize filter on this chip is set higher than
* MTU since FCoE uses 2k frames.
*/
@@ -2000,12 +2028,6 @@
QL_DUMP_IB_MAC_RSP(ib_mac_rsp);
- /* Frame error, so drop the packet. */
- if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) {
- ql_categorize_rx_err(qdev, ib_mac_rsp->flags2);
- return (unsigned long)length;
- }
-
if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) {
/* The data and headers are split into
* separate buffers.
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
index 0c74a70..50617c5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c
@@ -149,6 +149,7 @@
{
writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
+ writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_IPC_INTR_MASK);
}
/* This reads the MAC core counters (if actaully supported).
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 80cad06..4781d3d 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1380,7 +1380,7 @@
memcpy(slave_data->mac_addr, mac_addr, ETH_ALEN);
if (data->dual_emac) {
- if (of_property_read_u32(node, "dual_emac_res_vlan",
+ if (of_property_read_u32(slave_node, "dual_emac_res_vlan",
&prop)) {
pr_err("Missing dual_emac_res_vlan in DT.\n");
slave_data->dual_emac_res_vlan = i+1;
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 1cd7748..f5f0f09 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -470,8 +470,10 @@
packet->trans_id;
/* Notify the layer above us */
- nvsc_packet->completion.send.send_completion(
- nvsc_packet->completion.send.send_completion_ctx);
+ if (nvsc_packet)
+ nvsc_packet->completion.send.send_completion(
+ nvsc_packet->completion.send.
+ send_completion_ctx);
num_outstanding_sends =
atomic_dec_return(&net_device->num_outstanding_sends);
@@ -498,6 +500,7 @@
int ret = 0;
struct nvsp_message sendMessage;
struct net_device *ndev;
+ u64 req_id;
net_device = get_outbound_net_device(device);
if (!net_device)
@@ -518,20 +521,24 @@
0xFFFFFFFF;
sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
+ if (packet->completion.send.send_completion)
+ req_id = (u64)packet;
+ else
+ req_id = 0;
+
if (packet->page_buf_cnt) {
ret = vmbus_sendpacket_pagebuffer(device->channel,
packet->page_buf,
packet->page_buf_cnt,
&sendMessage,
sizeof(struct nvsp_message),
- (unsigned long)packet);
+ req_id);
} else {
ret = vmbus_sendpacket(device->channel, &sendMessage,
sizeof(struct nvsp_message),
- (unsigned long)packet,
+ req_id,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
-
}
if (ret == 0) {
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 5f85205..8341b62 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -241,13 +241,11 @@
if (status == 1) {
netif_carrier_on(net);
- netif_wake_queue(net);
ndev_ctx = netdev_priv(net);
schedule_delayed_work(&ndev_ctx->dwork, 0);
schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20));
} else {
netif_carrier_off(net);
- netif_tx_disable(net);
}
}
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 2b657d4..0775f0a 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -61,9 +61,6 @@
static void rndis_filter_send_completion(void *ctx);
-static void rndis_filter_send_request_completion(void *ctx);
-
-
static struct rndis_device *get_rndis_device(void)
{
@@ -241,10 +238,7 @@
packet->page_buf[0].len;
}
- packet->completion.send.send_completion_ctx = req;/* packet; */
- packet->completion.send.send_completion =
- rndis_filter_send_request_completion;
- packet->completion.send.send_completion_tid = (unsigned long)dev;
+ packet->completion.send.send_completion = NULL;
ret = netvsc_send(dev->net_dev->dev, packet);
return ret;
@@ -999,9 +993,3 @@
/* Pass it back to the original handler */
filter_pkt->completion(filter_pkt->completion_ctx);
}
-
-
-static void rndis_filter_send_request_completion(void *ctx)
-{
- /* Noop */
-}
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index b7c457a..729ed53 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1594,7 +1594,7 @@
if (tun->flags & TUN_TAP_MQ &&
(tun->numqueues + tun->numdisabled > 1))
- return err;
+ return -EBUSY;
}
else {
char *name;
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 16c8429..6bd9167 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -134,7 +134,7 @@
goto error;
if (skb) {
- if (skb->len <= sizeof(ETH_HLEN))
+ if (skb->len <= ETH_HLEN)
goto error;
/* mapping VLANs to MBIM sessions:
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 968d5d5..2a3579f 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
#include <linux/mii.h>
#include <linux/usb.h>
#include <linux/usb/cdc.h>
@@ -52,6 +53,96 @@
struct usb_interface *data;
};
+/* default ethernet address used by the modem */
+static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3};
+
+/* Make up an ethernet header if the packet doesn't have one.
+ *
+ * A firmware bug common among several devices cause them to send raw
+ * IP packets under some circumstances. There is no way for the
+ * driver/host to know when this will happen. And even when the bug
+ * hits, some packets will still arrive with an intact header.
+ *
+ * The supported devices are only capably of sending IPv4, IPv6 and
+ * ARP packets on a point-to-point link. Any packet with an ethernet
+ * header will have either our address or a broadcast/multicast
+ * address as destination. ARP packets will always have a header.
+ *
+ * This means that this function will reliably add the appropriate
+ * header iff necessary, provided our hardware address does not start
+ * with 4 or 6.
+ *
+ * Another common firmware bug results in all packets being addressed
+ * to 00:a0:c6:00:00:00 despite the host address being different.
+ * This function will also fixup such packets.
+ */
+static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ __be16 proto;
+
+ /* usbnet rx_complete guarantees that skb->len is at least
+ * hard_header_len, so we can inspect the dest address without
+ * checking skb->len
+ */
+ switch (skb->data[0] & 0xf0) {
+ case 0x40:
+ proto = htons(ETH_P_IP);
+ break;
+ case 0x60:
+ proto = htons(ETH_P_IPV6);
+ break;
+ case 0x00:
+ if (is_multicast_ether_addr(skb->data))
+ return 1;
+ /* possibly bogus destination - rewrite just in case */
+ skb_reset_mac_header(skb);
+ goto fix_dest;
+ default:
+ /* pass along other packets without modifications */
+ return 1;
+ }
+ if (skb_headroom(skb) < ETH_HLEN)
+ return 0;
+ skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ eth_hdr(skb)->h_proto = proto;
+ memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+fix_dest:
+ memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+ return 1;
+}
+
+/* very simplistic detection of IPv4 or IPv6 headers */
+static bool possibly_iphdr(const char *data)
+{
+ return (data[0] & 0xd0) == 0x40;
+}
+
+/* disallow addresses which may be confused with IP headers */
+static int qmi_wwan_mac_addr(struct net_device *dev, void *p)
+{
+ int ret;
+ struct sockaddr *addr = p;
+
+ ret = eth_prepare_mac_addr_change(dev, p);
+ if (ret < 0)
+ return ret;
+ if (possibly_iphdr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+ eth_commit_mac_addr_change(dev, p);
+ return 0;
+}
+
+static const struct net_device_ops qmi_wwan_netdev_ops = {
+ .ndo_open = usbnet_open,
+ .ndo_stop = usbnet_stop,
+ .ndo_start_xmit = usbnet_start_xmit,
+ .ndo_tx_timeout = usbnet_tx_timeout,
+ .ndo_change_mtu = usbnet_change_mtu,
+ .ndo_set_mac_address = qmi_wwan_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
/* using a counter to merge subdriver requests with our own into a combined state */
static int qmi_wwan_manage_power(struct usbnet *dev, int on)
{
@@ -229,6 +320,18 @@
usb_driver_release_interface(driver, info->data);
}
+ /* Never use the same address on both ends of the link, even
+ * if the buggy firmware told us to.
+ */
+ if (!compare_ether_addr(dev->net->dev_addr, default_modem_addr))
+ eth_hw_addr_random(dev->net);
+
+ /* make MAC addr easily distinguishable from an IP header */
+ if (possibly_iphdr(dev->net->dev_addr)) {
+ dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */
+ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */
+ }
+ dev->net->netdev_ops = &qmi_wwan_netdev_ops;
err:
return status;
}
@@ -307,6 +410,7 @@
.bind = qmi_wwan_bind,
.unbind = qmi_wwan_unbind,
.manage_power = qmi_wwan_manage_power,
+ .rx_fixup = qmi_wwan_rx_fixup,
};
#define HUAWEI_VENDOR_ID 0x12D1
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
index 28fd992..bdee2ed 100644
--- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
@@ -519,7 +519,7 @@
{0x00008258, 0x00000000},
{0x0000825c, 0x40000000},
{0x00008260, 0x00080922},
- {0x00008264, 0x9bc00010},
+ {0x00008264, 0x9d400010},
{0x00008268, 0xffffffff},
{0x0000826c, 0x0000ffff},
{0x00008270, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
index 467b600..73fe8d6 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pattern_detector.c
@@ -143,14 +143,14 @@
u32 sz, i;
struct channel_detector *cd;
- cd = kmalloc(sizeof(*cd), GFP_KERNEL);
+ cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
if (cd == NULL)
goto fail;
INIT_LIST_HEAD(&cd->head);
cd->freq = freq;
sz = sizeof(cd->detectors) * dpd->num_radar_types;
- cd->detectors = kzalloc(sz, GFP_KERNEL);
+ cd->detectors = kzalloc(sz, GFP_ATOMIC);
if (cd->detectors == NULL)
goto fail;
diff --git a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
index 91b8dce..5e48c55 100644
--- a/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
+++ b/drivers/net/wireless/ath/ath9k/dfs_pri_detector.c
@@ -218,7 +218,7 @@
{
struct pulse_elem *p = pool_get_pulse_elem();
if (p == NULL) {
- p = kmalloc(sizeof(*p), GFP_KERNEL);
+ p = kmalloc(sizeof(*p), GFP_ATOMIC);
if (p == NULL) {
DFS_POOL_STAT_INC(pulse_alloc_error);
return false;
@@ -299,7 +299,7 @@
ps.deadline_ts = ps.first_ts + ps.dur;
new_ps = pool_get_pseq_elem();
if (new_ps == NULL) {
- new_ps = kmalloc(sizeof(*new_ps), GFP_KERNEL);
+ new_ps = kmalloc(sizeof(*new_ps), GFP_ATOMIC);
if (new_ps == NULL) {
DFS_POOL_STAT_INC(pseq_alloc_error);
return false;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 716058b..a47f5e0 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -796,7 +796,7 @@
* required version.
*/
if (priv->fw_version_major != MAJOR_VERSION_REQ ||
- priv->fw_version_minor != MINOR_VERSION_REQ) {
+ priv->fw_version_minor < MINOR_VERSION_REQ) {
dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n",
MAJOR_VERSION_REQ, MINOR_VERSION_REQ);
return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6e66f9c..988372d 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -280,6 +280,10 @@
if (r) {
ath_err(common,
"Unable to reset channel, reset status %d\n", r);
+
+ ath9k_hw_enable_interrupts(ah);
+ ath9k_queue_reset(sc, RESET_TYPE_BB_HANG);
+
goto out;
}
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index e8486c1..b70f220 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -5165,7 +5165,8 @@
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
- /* FIXME */
+ ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco,
+ avoid);
break;
#endif
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 4469321..35fc68b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3317,15 +3317,15 @@
goto err;
}
- /* External image takes precedence if specified */
if (brcmf_sdbrcm_download_code_file(bus)) {
brcmf_err("dongle image file download failed\n");
goto err;
}
- /* External nvram takes precedence if specified */
- if (brcmf_sdbrcm_download_nvram(bus))
+ if (brcmf_sdbrcm_download_nvram(bus)) {
brcmf_err("dongle nvram file download failed\n");
+ goto err;
+ }
/* Take arm out of reset */
if (brcmf_sdbrcm_download_state(bus, false)) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 2af9c0f..78da3ef 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -1891,8 +1891,10 @@
brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
u8 key_idx, const u8 *mac_addr, struct key_params *params)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_wsec_key key;
s32 err = 0;
+ u8 keybuf[8];
memset(&key, 0, sizeof(key));
key.index = (u32) key_idx;
@@ -1916,8 +1918,9 @@
brcmf_dbg(CONN, "Setting the key index %d\n", key.index);
memcpy(key.data, params->key, key.len);
- if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
- u8 keybuf[8];
+ if ((ifp->vif->mode != WL_MODE_AP) &&
+ (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
+ brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2013,7 +2016,7 @@
break;
case WLAN_CIPHER_SUITE_TKIP:
if (ifp->vif->mode != WL_MODE_AP) {
- brcmf_dbg(CONN, "Swapping key\n");
+ brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
@@ -2118,8 +2121,7 @@
err = -EAGAIN;
goto done;
}
- switch (wsec & ~SES_OW_ENABLED) {
- case WEP_ENABLED:
+ if (wsec & WEP_ENABLED) {
sec = &profile->sec;
if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
params.cipher = WLAN_CIPHER_SUITE_WEP40;
@@ -2128,16 +2130,13 @@
params.cipher = WLAN_CIPHER_SUITE_WEP104;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
}
- break;
- case TKIP_ENABLED:
+ } else if (wsec & TKIP_ENABLED) {
params.cipher = WLAN_CIPHER_SUITE_TKIP;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
- break;
- case AES_ENABLED:
+ } else if (wsec & AES_ENABLED) {
params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
- break;
- default:
+ } else {
brcmf_err("Invalid algo (0x%x)\n", wsec);
err = -EINVAL;
goto done;
@@ -3824,8 +3823,9 @@
static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_if *ifp = netdev_priv(ndev);
- s32 err = -EPERM;
+ s32 err;
struct brcmf_fil_bss_enable_le bss_enable;
+ struct brcmf_join_params join_params;
brcmf_dbg(TRACE, "Enter\n");
@@ -3833,16 +3833,21 @@
/* Due to most likely deauths outstanding we sleep */
/* first to make sure they get processed by fw. */
msleep(400);
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
- if (err < 0) {
- brcmf_err("setting AP mode failed %d\n", err);
- goto exit;
- }
+
+ memset(&join_params, 0, sizeof(join_params));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
+ &join_params, sizeof(join_params));
+ if (err < 0)
+ brcmf_err("SET SSID error (%d)\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
- if (err < 0) {
+ if (err < 0)
brcmf_err("BRCMF_C_UP error %d\n", err);
- goto exit;
- }
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
+ if (err < 0)
+ brcmf_err("setting AP mode failed %d\n", err);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
+ if (err < 0)
+ brcmf_err("setting INFRA mode failed %d\n", err);
} else {
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
bss_enable.enable = cpu_to_le32(0);
@@ -3855,7 +3860,6 @@
set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state);
clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
-exit:
return err;
}
@@ -4124,10 +4128,6 @@
},
{
.max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
- },
- {
- .max = 1,
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO)
},
@@ -4183,8 +4183,7 @@
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO) |
- BIT(NL80211_IFTYPE_P2P_DEVICE);
+ BIT(NL80211_IFTYPE_P2P_GO);
wiphy->iface_combinations = brcmf_iface_combos;
wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c6..e2340b2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -274,6 +274,130 @@
}
}
+/**
+ * This function frees the WL per-device resources.
+ *
+ * This function frees resources owned by the WL device pointed to
+ * by the wl parameter.
+ *
+ * precondition: can both be called locked and unlocked
+ *
+ */
+static void brcms_free(struct brcms_info *wl)
+{
+ struct brcms_timer *t, *next;
+
+ /* free ucode data */
+ if (wl->fw.fw_cnt)
+ brcms_ucode_data_free(&wl->ucode);
+ if (wl->irq)
+ free_irq(wl->irq, wl);
+
+ /* kill dpc */
+ tasklet_kill(&wl->tasklet);
+
+ if (wl->pub) {
+ brcms_debugfs_detach(wl->pub);
+ brcms_c_module_unregister(wl->pub, "linux", wl);
+ }
+
+ /* free common resources */
+ if (wl->wlc) {
+ brcms_c_detach(wl->wlc);
+ wl->wlc = NULL;
+ wl->pub = NULL;
+ }
+
+ /* virtual interface deletion is deferred so we cannot spinwait */
+
+ /* wait for all pending callbacks to complete */
+ while (atomic_read(&wl->callbacks) > 0)
+ schedule();
+
+ /* free timers */
+ for (t = wl->timers; t; t = next) {
+ next = t->next;
+#ifdef DEBUG
+ kfree(t->name);
+#endif
+ kfree(t);
+ }
+}
+
+/*
+* called from both kernel as from this kernel module (error flow on attach)
+* precondition: perimeter lock is not acquired.
+*/
+static void brcms_remove(struct bcma_device *pdev)
+{
+ struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
+ struct brcms_info *wl = hw->priv;
+
+ if (wl->wlc) {
+ wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
+ wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+ ieee80211_unregister_hw(hw);
+ }
+
+ brcms_free(wl);
+
+ bcma_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(hw);
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static void brcms_release_fw(struct brcms_info *wl)
+{
+ int i;
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ release_firmware(wl->fw.fw_bin[i]);
+ release_firmware(wl->fw.fw_hdr[i]);
+ }
+}
+
+/*
+ * Precondition: Since this function is called in brcms_pci_probe() context,
+ * no locking is required.
+ */
+static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
+{
+ int status;
+ struct device *device = &pdev->dev;
+ char fw_name[100];
+ int i;
+
+ memset(&wl->fw, 0, sizeof(struct brcms_firmware));
+ for (i = 0; i < MAX_FW_IMAGES; i++) {
+ if (brcms_firmwares[i] == NULL)
+ break;
+ sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
+ UCODE_LOADER_API_VER);
+ status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
+ if (status) {
+ wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
+ KBUILD_MODNAME, fw_name);
+ return status;
+ }
+ wl->fw.hdr_num_entries[i] =
+ wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
+ }
+ wl->fw.fw_cnt = i;
+ status = brcms_ucode_data_init(wl, &wl->ucode);
+ brcms_release_fw(wl);
+ return status;
+}
+
static void brcms_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -306,6 +430,14 @@
if (!blocked)
wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
+ if (!wl->ucode.bcm43xx_bomminor) {
+ err = brcms_request_fw(wl, wl->wlc->hw->d11core);
+ if (err) {
+ brcms_remove(wl->wlc->hw->d11core);
+ return -ENOENT;
+ }
+ }
+
spin_lock_bh(&wl->lock);
/* avoid acknowledging frames before a non-monitor device is added */
wl->mute_tx = true;
@@ -793,128 +925,6 @@
wake_up(&wl->tx_flush_wq);
}
-/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev)
-{
- int status;
- struct device *device = &pdev->dev;
- char fw_name[100];
- int i;
-
- memset(&wl->fw, 0, sizeof(struct brcms_firmware));
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- if (brcms_firmwares[i] == NULL)
- break;
- sprintf(fw_name, "%s-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_bin[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- sprintf(fw_name, "%s_hdr-%d.fw", brcms_firmwares[i],
- UCODE_LOADER_API_VER);
- status = request_firmware(&wl->fw.fw_hdr[i], fw_name, device);
- if (status) {
- wiphy_err(wl->wiphy, "%s: fail to load firmware %s\n",
- KBUILD_MODNAME, fw_name);
- return status;
- }
- wl->fw.hdr_num_entries[i] =
- wl->fw.fw_hdr[i]->size / (sizeof(struct firmware_hdr));
- }
- wl->fw.fw_cnt = i;
- return brcms_ucode_data_init(wl, &wl->ucode);
-}
-
-/*
- * Precondition: Since this function is called in brcms_pci_probe() context,
- * no locking is required.
- */
-static void brcms_release_fw(struct brcms_info *wl)
-{
- int i;
- for (i = 0; i < MAX_FW_IMAGES; i++) {
- release_firmware(wl->fw.fw_bin[i]);
- release_firmware(wl->fw.fw_hdr[i]);
- }
-}
-
-/**
- * This function frees the WL per-device resources.
- *
- * This function frees resources owned by the WL device pointed to
- * by the wl parameter.
- *
- * precondition: can both be called locked and unlocked
- *
- */
-static void brcms_free(struct brcms_info *wl)
-{
- struct brcms_timer *t, *next;
-
- /* free ucode data */
- if (wl->fw.fw_cnt)
- brcms_ucode_data_free(&wl->ucode);
- if (wl->irq)
- free_irq(wl->irq, wl);
-
- /* kill dpc */
- tasklet_kill(&wl->tasklet);
-
- if (wl->pub) {
- brcms_debugfs_detach(wl->pub);
- brcms_c_module_unregister(wl->pub, "linux", wl);
- }
-
- /* free common resources */
- if (wl->wlc) {
- brcms_c_detach(wl->wlc);
- wl->wlc = NULL;
- wl->pub = NULL;
- }
-
- /* virtual interface deletion is deferred so we cannot spinwait */
-
- /* wait for all pending callbacks to complete */
- while (atomic_read(&wl->callbacks) > 0)
- schedule();
-
- /* free timers */
- for (t = wl->timers; t; t = next) {
- next = t->next;
-#ifdef DEBUG
- kfree(t->name);
-#endif
- kfree(t);
- }
-}
-
-/*
-* called from both kernel as from this kernel module (error flow on attach)
-* precondition: perimeter lock is not acquired.
-*/
-static void brcms_remove(struct bcma_device *pdev)
-{
- struct ieee80211_hw *hw = bcma_get_drvdata(pdev);
- struct brcms_info *wl = hw->priv;
-
- if (wl->wlc) {
- wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
- wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
- ieee80211_unregister_hw(hw);
- }
-
- brcms_free(wl);
-
- bcma_set_drvdata(pdev, NULL);
- ieee80211_free_hw(hw);
-}
-
static irqreturn_t brcms_isr(int irq, void *dev_id)
{
struct brcms_info *wl;
@@ -1047,18 +1057,8 @@
spin_lock_init(&wl->lock);
spin_lock_init(&wl->isr_lock);
- /* prepare ucode */
- if (brcms_request_fw(wl, pdev) < 0) {
- wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in "
- "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm");
- brcms_release_fw(wl);
- brcms_remove(pdev);
- return NULL;
- }
-
/* common load-time initialization */
wl->wlc = brcms_c_attach((void *)wl, pdev, unit, false, &err);
- brcms_release_fw(wl);
if (!wl->wlc) {
wiphy_err(wl->wiphy, "%s: attach() failed with code %d\n",
KBUILD_MODNAME, err);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index d215b4d..e7f6dea 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1393,8 +1393,10 @@
queue_work(adapter->workqueue, &adapter->main_work);
/* Perform internal scan synchronously */
- if (!priv->scan_request)
+ if (!priv->scan_request) {
+ dev_dbg(adapter->dev, "wait internal scan\n");
mwifiex_wait_queue_complete(adapter, cmd_node);
+ }
} else {
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
@@ -1793,7 +1795,12 @@
/* Need to indicate IOCTL complete */
if (adapter->curr_cmd->wait_q_enabled) {
adapter->cmd_wait_q.status = 0;
- mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+ if (!priv->scan_request) {
+ dev_dbg(adapter->dev,
+ "complete internal scan\n");
+ mwifiex_complete_cmd(adapter,
+ adapter->curr_cmd);
+ }
}
if (priv->report_scan_result)
priv->report_scan_result = false;
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 2bf4efa..76cd47e 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -20,6 +20,7 @@
config RT2400PCI
tristate "Ralink rt2400 (PCI/PCMCIA) support"
depends on PCI
+ select RT2X00_LIB_MMIO
select RT2X00_LIB_PCI
select EEPROM_93CX6
---help---
@@ -31,6 +32,7 @@
config RT2500PCI
tristate "Ralink rt2500 (PCI/PCMCIA) support"
depends on PCI
+ select RT2X00_LIB_MMIO
select RT2X00_LIB_PCI
select EEPROM_93CX6
---help---
@@ -43,6 +45,7 @@
tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"
depends on PCI
select RT2X00_LIB_PCI
+ select RT2X00_LIB_MMIO
select RT2X00_LIB_FIRMWARE
select RT2X00_LIB_CRYPTO
select CRC_ITU_T
@@ -57,6 +60,7 @@
tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
depends on PCI || SOC_RT288X || SOC_RT305X
select RT2800_LIB
+ select RT2X00_LIB_MMIO
select RT2X00_LIB_PCI if PCI
select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
select RT2X00_LIB_FIRMWARE
@@ -185,6 +189,9 @@
config RT2800_LIB
tristate
+config RT2X00_LIB_MMIO
+ tristate
+
config RT2X00_LIB_PCI
tristate
select RT2X00_LIB
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 349d5b8..f069d8b 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -9,6 +9,7 @@
rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o
obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
+obj-$(CONFIG_RT2X00_LIB_MMIO) += rt2x00mmio.o
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o
obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 221beaa..dcfb54e 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include "rt2x00.h"
+#include "rt2x00mmio.h"
#include "rt2x00pci.h"
#include "rt2400pci.h"
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 39edc59..e1d2dc9 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -34,6 +34,7 @@
#include <linux/slab.h>
#include "rt2x00.h"
+#include "rt2x00mmio.h"
#include "rt2x00pci.h"
#include "rt2500pci.h"
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index ded73da..ba5a056 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -41,6 +41,7 @@
#include <linux/eeprom_93cx6.h>
#include "rt2x00.h"
+#include "rt2x00mmio.h"
#include "rt2x00pci.h"
#include "rt2x00soc.h"
#include "rt2800lib.h"
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c
new file mode 100644
index 0000000..d84a680
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: rt2x00mmio
+ Abstract: rt2x00 generic mmio device routines.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "rt2x00.h"
+#include "rt2x00mmio.h"
+
+/*
+ * Register access.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg)
+{
+ unsigned int i;
+
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ return 0;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2x00pci_register_read(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field32(*reg, field))
+ return 1;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ printk_once(KERN_ERR "%s() Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg);
+ *reg = ~0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue = rt2x00dev->rx;
+ struct queue_entry *entry;
+ struct queue_entry_priv_pci *entry_priv;
+ struct skb_frame_desc *skbdesc;
+ int max_rx = 16;
+
+ while (--max_rx) {
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
+ entry_priv = entry->priv_data;
+
+ if (rt2x00dev->ops->lib->get_entry_state(entry))
+ break;
+
+ /*
+ * Fill in desc fields of the skb descriptor
+ */
+ skbdesc = get_skb_frame_desc(entry->skb);
+ skbdesc->desc = entry_priv->desc;
+ skbdesc->desc_len = entry->queue->desc_size;
+
+ /*
+ * DMA is already done, notify rt2x00lib that
+ * it finished successfully.
+ */
+ rt2x00lib_dmastart(entry);
+ rt2x00lib_dmadone(entry);
+
+ /*
+ * Send the frame to rt2x00lib for further processing.
+ */
+ rt2x00lib_rxdone(entry, GFP_ATOMIC);
+ }
+
+ return !max_rx;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
+{
+ unsigned int i;
+
+ for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
+ msleep(10);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
+
+/*
+ * Device initialization handlers.
+ */
+static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
+{
+ struct queue_entry_priv_pci *entry_priv;
+ void *addr;
+ dma_addr_t dma;
+ unsigned int i;
+
+ /*
+ * Allocate DMA memory for descriptor and buffer.
+ */
+ addr = dma_alloc_coherent(rt2x00dev->dev,
+ queue->limit * queue->desc_size,
+ &dma, GFP_KERNEL);
+ if (!addr)
+ return -ENOMEM;
+
+ memset(addr, 0, queue->limit * queue->desc_size);
+
+ /*
+ * Initialize all queue entries to contain valid addresses.
+ */
+ for (i = 0; i < queue->limit; i++) {
+ entry_priv = queue->entries[i].priv_data;
+ entry_priv->desc = addr + i * queue->desc_size;
+ entry_priv->desc_dma = dma + i * queue->desc_size;
+ }
+
+ return 0;
+}
+
+static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
+ struct data_queue *queue)
+{
+ struct queue_entry_priv_pci *entry_priv =
+ queue->entries[0].priv_data;
+
+ if (entry_priv->desc)
+ dma_free_coherent(rt2x00dev->dev,
+ queue->limit * queue->desc_size,
+ entry_priv->desc, entry_priv->desc_dma);
+ entry_priv->desc = NULL;
+}
+
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+ int status;
+
+ /*
+ * Allocate DMA
+ */
+ queue_for_each(rt2x00dev, queue) {
+ status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
+ if (status)
+ goto exit;
+ }
+
+ /*
+ * Register interrupt handler.
+ */
+ status = request_irq(rt2x00dev->irq,
+ rt2x00dev->ops->lib->irq_handler,
+ IRQF_SHARED, rt2x00dev->name, rt2x00dev);
+ if (status) {
+ ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
+ rt2x00dev->irq, status);
+ goto exit;
+ }
+
+ return 0;
+
+exit:
+ queue_for_each(rt2x00dev, queue)
+ rt2x00pci_free_queue_dma(rt2x00dev, queue);
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
+
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_queue *queue;
+
+ /*
+ * Free irq line.
+ */
+ free_irq(rt2x00dev->irq, rt2x00dev);
+
+ /*
+ * Free DMA
+ */
+ queue_for_each(rt2x00dev, queue)
+ rt2x00pci_free_queue_dma(rt2x00dev, queue);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
+
+/*
+ * rt2x00mmio module information.
+ */
+MODULE_AUTHOR(DRV_PROJECT);
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION("rt2x00 mmio library");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h
new file mode 100644
index 0000000..4ecaf60
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h
@@ -0,0 +1,119 @@
+/*
+ Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+ <http://rt2x00.serialmonkey.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ Module: rt2x00mmio
+ Abstract: Data structures for the rt2x00mmio module.
+ */
+
+#ifndef RT2X00MMIO_H
+#define RT2X00MMIO_H
+
+#include <linux/io.h>
+
+/*
+ * Register access.
+ */
+static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
+{
+ *value = readl(rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void *value, const u32 length)
+{
+ memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
+}
+
+static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
+{
+ writel(value, rt2x00dev->csr.base + offset);
+}
+
+static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const void *value,
+ const u32 length)
+{
+ __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
+}
+
+/**
+ * rt2x00pci_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg);
+
+/**
+ * struct queue_entry_priv_pci: Per entry PCI specific information
+ *
+ * @desc: Pointer to device descriptor
+ * @desc_dma: DMA pointer to &desc.
+ * @data: Pointer to device's entry memory.
+ * @data_dma: DMA pointer to &data.
+ */
+struct queue_entry_priv_pci {
+ __le32 *desc;
+ dma_addr_t desc_dma;
+};
+
+/**
+ * rt2x00pci_rxdone - Handle RX done events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ *
+ * Returns true if there are still rx frames pending and false if all
+ * pending rx frames were processed.
+ */
+bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+
+/**
+ * rt2x00pci_flush_queue - Flush data queue
+ * @queue: Data queue to stop
+ * @drop: True to drop all pending frames.
+ *
+ * This will wait for a maximum of 100ms, waiting for the queues
+ * to become empty.
+ */
+void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
+
+/*
+ * Device initialization handlers.
+ */
+int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
+
+#endif /* RT2X00MMIO_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index a0c8cae..e87865e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -33,182 +33,6 @@
#include "rt2x00pci.h"
/*
- * Register access.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg)
-{
- unsigned int i;
-
- if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
- return 0;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, offset, reg);
- if (!rt2x00_get_field32(*reg, field))
- return 1;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "Indirect register access failed: "
- "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
- *reg = ~0;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
-
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue = rt2x00dev->rx;
- struct queue_entry *entry;
- struct queue_entry_priv_pci *entry_priv;
- struct skb_frame_desc *skbdesc;
- int max_rx = 16;
-
- while (--max_rx) {
- entry = rt2x00queue_get_entry(queue, Q_INDEX);
- entry_priv = entry->priv_data;
-
- if (rt2x00dev->ops->lib->get_entry_state(entry))
- break;
-
- /*
- * Fill in desc fields of the skb descriptor
- */
- skbdesc = get_skb_frame_desc(entry->skb);
- skbdesc->desc = entry_priv->desc;
- skbdesc->desc_len = entry->queue->desc_size;
-
- /*
- * DMA is already done, notify rt2x00lib that
- * it finished successfully.
- */
- rt2x00lib_dmastart(entry);
- rt2x00lib_dmadone(entry);
-
- /*
- * Send the frame to rt2x00lib for further processing.
- */
- rt2x00lib_rxdone(entry, GFP_ATOMIC);
- }
-
- return !max_rx;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
-
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop)
-{
- unsigned int i;
-
- for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++)
- msleep(10);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_flush_queue);
-
-/*
- * Device initialization handlers.
- */
-static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
-{
- struct queue_entry_priv_pci *entry_priv;
- void *addr;
- dma_addr_t dma;
- unsigned int i;
-
- /*
- * Allocate DMA memory for descriptor and buffer.
- */
- addr = dma_alloc_coherent(rt2x00dev->dev,
- queue->limit * queue->desc_size,
- &dma, GFP_KERNEL);
- if (!addr)
- return -ENOMEM;
-
- memset(addr, 0, queue->limit * queue->desc_size);
-
- /*
- * Initialize all queue entries to contain valid addresses.
- */
- for (i = 0; i < queue->limit; i++) {
- entry_priv = queue->entries[i].priv_data;
- entry_priv->desc = addr + i * queue->desc_size;
- entry_priv->desc_dma = dma + i * queue->desc_size;
- }
-
- return 0;
-}
-
-static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
- struct data_queue *queue)
-{
- struct queue_entry_priv_pci *entry_priv =
- queue->entries[0].priv_data;
-
- if (entry_priv->desc)
- dma_free_coherent(rt2x00dev->dev,
- queue->limit * queue->desc_size,
- entry_priv->desc, entry_priv->desc_dma);
- entry_priv->desc = NULL;
-}
-
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
- int status;
-
- /*
- * Allocate DMA
- */
- queue_for_each(rt2x00dev, queue) {
- status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue);
- if (status)
- goto exit;
- }
-
- /*
- * Register interrupt handler.
- */
- status = request_irq(rt2x00dev->irq,
- rt2x00dev->ops->lib->irq_handler,
- IRQF_SHARED, rt2x00dev->name, rt2x00dev);
- if (status) {
- ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
- rt2x00dev->irq, status);
- goto exit;
- }
-
- return 0;
-
-exit:
- queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
-
- return status;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_initialize);
-
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue;
-
- /*
- * Free irq line.
- */
- free_irq(rt2x00dev->irq, rt2x00dev);
-
- /*
- * Free DMA
- */
- queue_for_each(rt2x00dev, queue)
- rt2x00pci_free_queue_dma(rt2x00dev, queue);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
-
-/*
* PCI driver handlers.
*/
static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index e2c99f2..60d90b2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -36,94 +36,6 @@
#define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops)
/*
- * Register access.
- */
-static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 *value)
-{
- *value = readl(rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- void *value, const u32 length)
-{
- memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
-}
-
-static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- u32 value)
-{
- writel(value, rt2x00dev->csr.base + offset);
-}
-
-static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const void *value,
- const u32 length)
-{
- __iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
-}
-
-/**
- * rt2x00pci_regbusy_read - Read from register with busy check
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- * @offset: Register offset
- * @field: Field to check if register is busy
- * @reg: Pointer to where register contents should be stored
- *
- * This function will read the given register, and checks if the
- * register is busy. If it is, it will sleep for a couple of
- * microseconds before reading the register again. If the register
- * is not read after a certain timeout, this function will return
- * FALSE.
- */
-int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- const struct rt2x00_field32 field,
- u32 *reg);
-
-/**
- * struct queue_entry_priv_pci: Per entry PCI specific information
- *
- * @desc: Pointer to device descriptor
- * @desc_dma: DMA pointer to &desc.
- * @data: Pointer to device's entry memory.
- * @data_dma: DMA pointer to &data.
- */
-struct queue_entry_priv_pci {
- __le32 *desc;
- dma_addr_t desc_dma;
-};
-
-/**
- * rt2x00pci_rxdone - Handle RX done events
- * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
- *
- * Returns true if there are still rx frames pending and false if all
- * pending rx frames were processed.
- */
-bool rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
-
-/**
- * rt2x00pci_flush_queue - Flush data queue
- * @queue: Data queue to stop
- * @drop: True to drop all pending frames.
- *
- * This will wait for a maximum of 100ms, waiting for the queues
- * to become empty.
- */
-void rt2x00pci_flush_queue(struct data_queue *queue, bool drop);
-
-/*
- * Device initialization handlers.
- */
-int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev);
-
-/*
* PCI driver handlers.
*/
int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index f95792c..9e3c8ff 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -35,6 +35,7 @@
#include <linux/eeprom_93cx6.h>
#include "rt2x00.h"
+#include "rt2x00mmio.h"
#include "rt2x00pci.h"
#include "rt61pci.h"
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 8647dc6..748f8f3 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -202,20 +202,16 @@
if (dev->is_added)
continue;
retval = pci_bus_add_device(dev);
+ if (retval)
+ dev_err(&dev->dev, "Error adding device (%d)\n",
+ retval);
}
list_for_each_entry(dev, &bus->devices, bus_list) {
BUG_ON(!dev->is_added);
-
child = dev->subordinate;
-
- if (!child)
- continue;
- pci_bus_add_devices(child);
-
- if (child->is_added)
- continue;
- child->is_added = 1;
+ if (child)
+ pci_bus_add_devices(child);
}
}
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 13e9e63..9fcb87f 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -52,15 +52,12 @@
When in doubt, say N.
config HOTPLUG_PCI_ACPI
- tristate "ACPI PCI Hotplug driver"
- depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK)
+ bool "ACPI PCI Hotplug driver"
+ depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK))
help
Say Y here if you have a system that supports PCI Hotplug using
ACPI.
- To compile this driver as a module, choose M here: the
- module will be called acpiphp.
-
When in doubt, say N.
config HOTPLUG_PCI_ACPI_IBM
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index b70ac00..6fdd49c 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -73,8 +73,9 @@
*/
struct acpiphp_bridge {
struct list_head list;
+ struct list_head slots;
+ struct kref ref;
acpi_handle handle;
- struct acpiphp_slot *slots;
/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
struct acpiphp_func *func;
@@ -97,7 +98,7 @@
* PCI slot information for each *physical* PCI slot
*/
struct acpiphp_slot {
- struct acpiphp_slot *next;
+ struct list_head node;
struct acpiphp_bridge *bridge; /* parent */
struct list_head funcs; /* one slot may have different
objects (i.e. for each function) */
@@ -119,7 +120,6 @@
*/
struct acpiphp_func {
struct acpiphp_slot *slot; /* parent */
- struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */
struct list_head sibling;
struct notifier_block nb;
@@ -146,10 +146,6 @@
#define ACPI_PCI_HOST_HID "PNP0A03"
/* ACPI _STA method value (ignore bit 4; battery present) */
-#define ACPI_STA_PRESENT (0x00000001)
-#define ACPI_STA_ENABLED (0x00000002)
-#define ACPI_STA_SHOW_IN_UI (0x00000004)
-#define ACPI_STA_FUNCTIONING (0x00000008)
#define ACPI_STA_ALL (0x0000000f)
/* bridge flags */
@@ -174,25 +170,24 @@
/* function prototypes */
/* acpiphp_core.c */
-extern int acpiphp_register_attention(struct acpiphp_attention_info*info);
-extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
-extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
-extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
+int acpiphp_register_attention(struct acpiphp_attention_info*info);
+int acpiphp_unregister_attention(struct acpiphp_attention_info *info);
+int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot);
+void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);
/* acpiphp_glue.c */
-extern int acpiphp_glue_init (void);
-extern void acpiphp_glue_exit (void);
typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);
-extern int acpiphp_enable_slot (struct acpiphp_slot *slot);
-extern int acpiphp_disable_slot (struct acpiphp_slot *slot);
-extern int acpiphp_eject_slot (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
-extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
+int acpiphp_enable_slot(struct acpiphp_slot *slot);
+int acpiphp_disable_slot(struct acpiphp_slot *slot);
+int acpiphp_eject_slot(struct acpiphp_slot *slot);
+u8 acpiphp_get_power_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);
+u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot);
/* variables */
extern bool acpiphp_debug;
+extern bool acpiphp_disabled;
#endif /* _ACPIPHP_H */
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index c2fd309..ca81279 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/pci_hotplug.h>
#include <linux/slab.h>
#include <linux/smp.h>
@@ -48,6 +49,7 @@
#define SLOT_NAME_SIZE 21 /* {_SUN} */
bool acpiphp_debug;
+bool acpiphp_disabled;
/* local variables */
static struct acpiphp_attention_info *attention_info;
@@ -60,7 +62,9 @@
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+MODULE_PARM_DESC(disable, "disable acpiphp driver");
module_param_named(debug, acpiphp_debug, bool, 0644);
+module_param_named(disable, acpiphp_disabled, bool, 0444);
/* export the attention callback registration methods */
EXPORT_SYMBOL_GPL(acpiphp_register_attention);
@@ -351,27 +355,9 @@
}
-static int __init acpiphp_init(void)
+void __init acpiphp_init(void)
{
- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-
- if (acpi_pci_disabled)
- return 0;
-
- /* read all the ACPI info from the system */
- /* initialize internal data structure etc. */
- return acpiphp_glue_init();
+ info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",
+ acpiphp_disabled ? ", disabled by user; please report a bug"
+ : "");
}
-
-
-static void __exit acpiphp_exit(void)
-{
- if (acpi_pci_disabled)
- return;
-
- /* deallocate internal data structures etc. */
- acpiphp_glue_exit();
-}
-
-module_init(acpiphp_init);
-module_exit(acpiphp_exit);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 270fdba..96fed19 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -54,6 +54,7 @@
#include "acpiphp.h"
static LIST_HEAD(bridge_list);
+static DEFINE_MUTEX(bridge_mutex);
#define MY_NAME "acpiphp_glue"
@@ -61,6 +62,7 @@
static void acpiphp_sanitize_bus(struct pci_bus *bus);
static void acpiphp_set_hpp_values(struct pci_bus *bus);
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context);
+static void free_bridge(struct kref *kref);
/* callback routine to check for the existence of a pci dock device */
static acpi_status
@@ -76,6 +78,39 @@
}
}
+static inline void get_bridge(struct acpiphp_bridge *bridge)
+{
+ kref_get(&bridge->ref);
+}
+
+static inline void put_bridge(struct acpiphp_bridge *bridge)
+{
+ kref_put(&bridge->ref, free_bridge);
+}
+
+static void free_bridge(struct kref *kref)
+{
+ struct acpiphp_bridge *bridge;
+ struct acpiphp_slot *slot, *next;
+ struct acpiphp_func *func, *tmp;
+
+ bridge = container_of(kref, struct acpiphp_bridge, ref);
+
+ list_for_each_entry_safe(slot, next, &bridge->slots, node) {
+ list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
+ kfree(func);
+ }
+ kfree(slot);
+ }
+
+ /* Release reference acquired by acpiphp_bridge_handle_to_function() */
+ if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)
+ put_bridge(bridge->func->slot->bridge);
+ put_device(&bridge->pci_bus->dev);
+ pci_dev_put(bridge->pci_dev);
+ kfree(bridge);
+}
+
/*
* the _DCK method can do funny things... and sometimes not
* hah-hah funny.
@@ -154,9 +189,10 @@
acpi_handle tmp;
acpi_status status = AE_OK;
unsigned long long adr, sun;
- int device, function, retval;
+ int device, function, retval, found = 0;
struct pci_bus *pbus = bridge->pci_bus;
struct pci_dev *pdev;
+ u32 val;
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
return AE_OK;
@@ -170,7 +206,7 @@
device = (adr >> 16) & 0xffff;
function = adr & 0xffff;
- pdev = pbus->self;
+ pdev = bridge->pci_dev;
if (pdev && device_is_managed_by_native_pciehp(pdev))
return AE_OK;
@@ -178,7 +214,6 @@
if (!newfunc)
return AE_NO_MEMORY;
- INIT_LIST_HEAD(&newfunc->sibling);
newfunc->handle = handle;
newfunc->function = function;
@@ -207,14 +242,15 @@
}
/* search for objects that share the same slot */
- for (slot = bridge->slots; slot; slot = slot->next)
+ list_for_each_entry(slot, &bridge->slots, node)
if (slot->device == device) {
if (slot->sun != sun)
warn("sibling found, but _SUN doesn't match!\n");
+ found = 1;
break;
}
- if (!slot) {
+ if (!found) {
slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);
if (!slot) {
kfree(newfunc);
@@ -227,9 +263,9 @@
INIT_LIST_HEAD(&slot->funcs);
mutex_init(&slot->crit_sect);
- slot->next = bridge->slots;
- bridge->slots = slot;
-
+ mutex_lock(&bridge_mutex);
+ list_add_tail(&slot->node, &bridge->slots);
+ mutex_unlock(&bridge_mutex);
bridge->nr_slots++;
dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",
@@ -247,13 +283,13 @@
}
newfunc->slot = slot;
+ mutex_lock(&bridge_mutex);
list_add_tail(&newfunc->sibling, &slot->funcs);
+ mutex_unlock(&bridge_mutex);
- pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
- if (pdev) {
+ if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function),
+ &val, 60*1000))
slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
- pci_dev_put(pdev);
- }
if (is_dock_device(handle)) {
/* we don't want to call this device's _EJ0
@@ -290,7 +326,9 @@
err_exit:
bridge->nr_slots--;
- bridge->slots = slot->next;
+ mutex_lock(&bridge_mutex);
+ list_del(&slot->node);
+ mutex_unlock(&bridge_mutex);
kfree(slot);
kfree(newfunc);
@@ -315,13 +353,17 @@
acpi_status status;
/* must be added to the list prior to calling register_slot */
+ mutex_lock(&bridge_mutex);
list_add(&bridge->list, &bridge_list);
+ mutex_unlock(&bridge_mutex);
/* register all slot objects under this bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
register_slot, NULL, bridge, NULL);
if (ACPI_FAILURE(status)) {
+ mutex_lock(&bridge_mutex);
list_del(&bridge->list);
+ mutex_unlock(&bridge_mutex);
return;
}
@@ -351,178 +393,46 @@
{
struct acpiphp_bridge *bridge;
struct acpiphp_slot *slot;
- struct acpiphp_func *func;
+ struct acpiphp_func *func = NULL;
+ mutex_lock(&bridge_mutex);
list_for_each_entry(bridge, &bridge_list, list) {
- for (slot = bridge->slots; slot; slot = slot->next) {
+ list_for_each_entry(slot, &bridge->slots, node) {
list_for_each_entry(func, &slot->funcs, sibling) {
- if (func->handle == handle)
+ if (func->handle == handle) {
+ get_bridge(func->slot->bridge);
+ mutex_unlock(&bridge_mutex);
return func;
+ }
}
}
}
+ mutex_unlock(&bridge_mutex);
return NULL;
}
-static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
-{
- acpi_handle dummy_handle;
- struct acpiphp_func *func;
-
- if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
- "_EJ0", &dummy_handle))) {
- bridge->flags |= BRIDGE_HAS_EJ0;
-
- dbg("found ejectable p2p bridge\n");
-
- /* make link between PCI bridge and PCI function */
- func = acpiphp_bridge_handle_to_function(bridge->handle);
- if (!func)
- return;
- bridge->func = func;
- func->bridge = bridge;
- }
-}
-
-
-/* allocate and initialize host bridge data structure */
-static void add_host_bridge(struct acpi_pci_root *root)
-{
- struct acpiphp_bridge *bridge;
- acpi_handle handle = root->device->handle;
-
- bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
- if (bridge == NULL)
- return;
-
- bridge->handle = handle;
-
- bridge->pci_bus = root->bus;
-
- init_bridge_misc(bridge);
-}
-
-
-/* allocate and initialize PCI-to-PCI bridge data structure */
-static void add_p2p_bridge(acpi_handle *handle)
-{
- struct acpiphp_bridge *bridge;
-
- bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
- if (bridge == NULL) {
- err("out of memory\n");
- return;
- }
-
- bridge->handle = handle;
- config_p2p_bridge_flags(bridge);
-
- bridge->pci_dev = acpi_get_pci_dev(handle);
- bridge->pci_bus = bridge->pci_dev->subordinate;
- if (!bridge->pci_bus) {
- err("This is not a PCI-to-PCI bridge!\n");
- goto err;
- }
-
- /*
- * Grab a ref to the subordinate PCI bus in case the bus is
- * removed via PCI core logical hotplug. The ref pins the bus
- * (which we access during module unload).
- */
- get_device(&bridge->pci_bus->dev);
-
- init_bridge_misc(bridge);
- return;
- err:
- pci_dev_put(bridge->pci_dev);
- kfree(bridge);
- return;
-}
-
-
-/* callback routine to find P2P bridges */
-static acpi_status
-find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- acpi_status status;
- struct pci_dev *dev;
-
- dev = acpi_get_pci_dev(handle);
- if (!dev || !dev->subordinate)
- goto out;
-
- /* check if this bridge has ejectable slots */
- if ((detect_ejectable_slots(handle) > 0)) {
- dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));
- add_p2p_bridge(handle);
- }
-
- /* search P2P bridges under this p2p bridge */
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, NULL, NULL, NULL);
- if (ACPI_FAILURE(status))
- warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
-
- out:
- pci_dev_put(dev);
- return AE_OK;
-}
-
-
-/* find hot-pluggable slots, and then find P2P bridge */
-static int add_bridge(struct acpi_pci_root *root)
-{
- acpi_status status;
- unsigned long long tmp;
- acpi_handle dummy_handle;
- acpi_handle handle = root->device->handle;
-
- /* if the bridge doesn't have _STA, we assume it is always there */
- status = acpi_get_handle(handle, "_STA", &dummy_handle);
- if (ACPI_SUCCESS(status)) {
- status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp);
- if (ACPI_FAILURE(status)) {
- dbg("%s: _STA evaluation failure\n", __func__);
- return 0;
- }
- if ((tmp & ACPI_STA_FUNCTIONING) == 0)
- /* don't register this object */
- return 0;
- }
-
- /* check if this bridge has ejectable slots */
- if (detect_ejectable_slots(handle) > 0) {
- dbg("found PCI host-bus bridge with hot-pluggable slots\n");
- add_host_bridge(root);
- }
-
- /* search P2P bridges under this host bridge */
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, NULL, NULL, NULL);
-
- if (ACPI_FAILURE(status))
- warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
-
- return 0;
-}
-
static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
{
struct acpiphp_bridge *bridge;
+ mutex_lock(&bridge_mutex);
list_for_each_entry(bridge, &bridge_list, list)
- if (bridge->handle == handle)
+ if (bridge->handle == handle) {
+ get_bridge(bridge);
+ mutex_unlock(&bridge_mutex);
return bridge;
+ }
+ mutex_unlock(&bridge_mutex);
return NULL;
}
static void cleanup_bridge(struct acpiphp_bridge *bridge)
{
- struct acpiphp_slot *slot, *next;
- struct acpiphp_func *func, *tmp;
+ struct acpiphp_slot *slot;
+ struct acpiphp_func *func;
acpi_status status;
acpi_handle handle = bridge->handle;
@@ -543,10 +453,8 @@
err("failed to install interrupt notify handler\n");
}
- slot = bridge->slots;
- while (slot) {
- next = slot->next;
- list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
+ list_for_each_entry(slot, &bridge->slots, node) {
+ list_for_each_entry(func, &slot->funcs, sibling) {
if (is_dock_device(func->handle)) {
unregister_hotplug_dock_device(func->handle);
unregister_dock_notifier(&func->nb);
@@ -558,63 +466,13 @@
if (ACPI_FAILURE(status))
err("failed to remove notify handler\n");
}
- list_del(&func->sibling);
- kfree(func);
}
acpiphp_unregister_hotplug_slot(slot);
- list_del(&slot->funcs);
- kfree(slot);
- slot = next;
}
- /*
- * Only P2P bridges have a pci_dev
- */
- if (bridge->pci_dev)
- put_device(&bridge->pci_bus->dev);
-
- pci_dev_put(bridge->pci_dev);
+ mutex_lock(&bridge_mutex);
list_del(&bridge->list);
- kfree(bridge);
-}
-
-static acpi_status
-cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- struct acpiphp_bridge *bridge;
-
- /* cleanup p2p bridges under this P2P bridge
- in a depth-first manner */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- cleanup_p2p_bridge, NULL, NULL, NULL);
-
- bridge = acpiphp_handle_to_bridge(handle);
- if (bridge)
- cleanup_bridge(bridge);
-
- return AE_OK;
-}
-
-static void remove_bridge(struct acpi_pci_root *root)
-{
- struct acpiphp_bridge *bridge;
- acpi_handle handle = root->device->handle;
-
- /* cleanup p2p bridges under this host bridge
- in a depth-first manner */
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL);
-
- /*
- * On root bridges with hotplug slots directly underneath (ie,
- * no p2p bridge between), we call cleanup_bridge().
- *
- * The else clause cleans up root bridges that either had no
- * hotplug slots at all, or had a p2p bridge underneath.
- */
- bridge = acpiphp_handle_to_bridge(handle);
- if (bridge)
- cleanup_bridge(bridge);
+ mutex_unlock(&bridge_mutex);
}
static int power_on_slot(struct acpiphp_slot *slot)
@@ -798,6 +656,7 @@
}
}
}
+
/**
* enable_device - enable, configure a slot
* @slot: slot to be enabled
@@ -810,9 +669,7 @@
struct pci_dev *dev;
struct pci_bus *bus = slot->bridge->pci_bus;
struct acpiphp_func *func;
- int retval = 0;
int num, max, pass;
- acpi_status status;
if (slot->flags & SLOT_ENABLED)
goto err_exit;
@@ -867,23 +724,11 @@
slot->flags &= (~SLOT_ENABLED);
continue;
}
-
- if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE &&
- dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) {
- pci_dev_put(dev);
- continue;
- }
-
- status = find_p2p_bridge(func->handle, (u32)1, bus, NULL);
- if (ACPI_FAILURE(status))
- warn("find_p2p_bridge failed (error code = 0x%x)\n",
- status);
- pci_dev_put(dev);
}
err_exit:
- return retval;
+ return 0;
}
/* return first device in slot, acquiring a reference on it */
@@ -912,23 +757,6 @@
{
struct acpiphp_func *func;
struct pci_dev *pdev;
- struct pci_bus *bus = slot->bridge->pci_bus;
-
- /* The slot will be enabled when func 0 is added, so check
- func 0 before disable the slot. */
- pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
- if (!pdev)
- goto err_exit;
- pci_dev_put(pdev);
-
- list_for_each_entry(func, &slot->funcs, sibling) {
- if (func->bridge) {
- /* cleanup p2p bridges under this P2P bridge */
- cleanup_p2p_bridge(func->bridge->handle,
- (u32)1, NULL, NULL);
- func->bridge = NULL;
- }
- }
/*
* enable_device() enumerates all functions in this device via
@@ -947,7 +775,6 @@
slot->flags &= (~SLOT_ENABLED);
-err_exit:
return 0;
}
@@ -1037,7 +864,7 @@
enabled = disabled = 0;
- for (slot = bridge->slots; slot; slot = slot->next) {
+ list_for_each_entry(slot, &bridge->slots, node) {
unsigned int status = get_slot_status(slot);
if (slot->flags & SLOT_ENABLED) {
if (status == ACPI_STA_ALL)
@@ -1082,11 +909,11 @@
*/
static void acpiphp_sanitize_bus(struct pci_bus *bus)
{
- struct pci_dev *dev;
+ struct pci_dev *dev, *tmp;
int i;
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
- list_for_each_entry(dev, &bus->devices, bus_list) {
+ list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
struct resource *res = &dev->resource[i];
if ((res->flags & type_mask) && !res->start &&
@@ -1118,6 +945,7 @@
dbg("%s: re-enumerating slots under %s\n",
__func__, objname);
acpiphp_check_bridge(bridge);
+ put_bridge(bridge);
}
return AE_OK ;
}
@@ -1195,6 +1023,7 @@
acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
+ put_bridge(bridge);
}
/**
@@ -1208,6 +1037,8 @@
static void handle_hotplug_event_bridge(acpi_handle handle, u32 type,
void *context)
{
+ struct acpiphp_bridge *bridge = context;
+
/*
* Currently the code adds all hotplug events to the kacpid_wq
* queue when it should add hotplug events to the kacpi_hotplug_wq.
@@ -1216,6 +1047,7 @@
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
+ get_bridge(bridge);
alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
}
@@ -1270,6 +1102,7 @@
acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_func */
+ put_bridge(func->slot->bridge);
}
/**
@@ -1283,6 +1116,8 @@
static void handle_hotplug_event_func(acpi_handle handle, u32 type,
void *context)
{
+ struct acpiphp_func *func = context;
+
/*
* Currently the code adds all hotplug events to the kacpid_wq
* queue when it should add hotplug events to the kacpi_hotplug_wq.
@@ -1291,33 +1126,69 @@
* For now just re-add this work to the kacpi_hotplug_wq so we
* don't deadlock on hotplug actions.
*/
+ get_bridge(func->slot->bridge);
alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
}
-static struct acpi_pci_driver acpi_pci_hp_driver = {
- .add = add_bridge,
- .remove = remove_bridge,
-};
-
-/**
- * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
+/*
+ * Create hotplug slots for the PCI bus.
+ * It should always return 0 to avoid skipping following notifiers.
*/
-int __init acpiphp_glue_init(void)
+void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
{
- acpi_pci_register_driver(&acpi_pci_hp_driver);
+ acpi_handle dummy_handle;
+ struct acpiphp_bridge *bridge;
- return 0;
+ if (acpiphp_disabled)
+ return;
+
+ if (detect_ejectable_slots(handle) <= 0)
+ return;
+
+ bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+ if (bridge == NULL) {
+ err("out of memory\n");
+ return;
+ }
+
+ INIT_LIST_HEAD(&bridge->slots);
+ kref_init(&bridge->ref);
+ bridge->handle = handle;
+ bridge->pci_dev = pci_dev_get(bus->self);
+ bridge->pci_bus = bus;
+
+ /*
+ * Grab a ref to the subordinate PCI bus in case the bus is
+ * removed via PCI core logical hotplug. The ref pins the bus
+ * (which we access during module unload).
+ */
+ get_device(&bus->dev);
+
+ if (!pci_is_root_bus(bridge->pci_bus) &&
+ ACPI_SUCCESS(acpi_get_handle(bridge->handle,
+ "_EJ0", &dummy_handle))) {
+ dbg("found ejectable p2p bridge\n");
+ bridge->flags |= BRIDGE_HAS_EJ0;
+ bridge->func = acpiphp_bridge_handle_to_function(handle);
+ }
+
+ init_bridge_misc(bridge);
}
-
-/**
- * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
- *
- * This function frees all data allocated in acpiphp_glue_init().
- */
-void acpiphp_glue_exit(void)
+/* Destroy hotplug slots associated with the PCI bus */
+void acpiphp_remove_slots(struct pci_bus *bus)
{
- acpi_pci_unregister_driver(&acpi_pci_hp_driver);
+ struct acpiphp_bridge *bridge, *tmp;
+
+ if (acpiphp_disabled)
+ return;
+
+ list_for_each_entry_safe(bridge, tmp, &bridge_list, list)
+ if (bridge->pci_bus == bus) {
+ cleanup_bridge(bridge);
+ put_bridge(bridge);
+ break;
+ }
}
/**
@@ -1396,7 +1267,7 @@
sta = get_slot_status(slot);
- return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1;
+ return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1;
}
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index 9fff878..1356211 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -75,28 +75,36 @@
return hotplug_slot_name(slot->hotplug_slot);
}
-extern int cpci_hp_register_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
-extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
-extern int cpci_hp_unregister_bus(struct pci_bus *bus);
-extern int cpci_hp_start(void);
-extern int cpci_hp_stop(void);
+int cpci_hp_register_controller(struct cpci_hp_controller *controller);
+int cpci_hp_unregister_controller(struct cpci_hp_controller *controller);
+int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last);
+int cpci_hp_unregister_bus(struct pci_bus *bus);
+int cpci_hp_start(void);
+int cpci_hp_stop(void);
/*
* Internal function prototypes, these functions should not be used by
* board/chassis drivers.
*/
-extern u8 cpci_get_attention_status(struct slot *slot);
-extern u8 cpci_get_latch_status(struct slot *slot);
-extern u8 cpci_get_adapter_status(struct slot *slot);
-extern u16 cpci_get_hs_csr(struct slot * slot);
-extern int cpci_set_attention_status(struct slot *slot, int status);
-extern int cpci_check_and_clear_ins(struct slot * slot);
-extern int cpci_check_ext(struct slot * slot);
-extern int cpci_clear_ext(struct slot * slot);
-extern int cpci_led_on(struct slot * slot);
-extern int cpci_led_off(struct slot * slot);
-extern int cpci_configure_slot(struct slot *slot);
-extern int cpci_unconfigure_slot(struct slot *slot);
+u8 cpci_get_attention_status(struct slot *slot);
+u8 cpci_get_latch_status(struct slot *slot);
+u8 cpci_get_adapter_status(struct slot *slot);
+u16 cpci_get_hs_csr(struct slot * slot);
+int cpci_set_attention_status(struct slot *slot, int status);
+int cpci_check_and_clear_ins(struct slot * slot);
+int cpci_check_ext(struct slot * slot);
+int cpci_clear_ext(struct slot * slot);
+int cpci_led_on(struct slot * slot);
+int cpci_led_off(struct slot * slot);
+int cpci_configure_slot(struct slot *slot);
+int cpci_unconfigure_slot(struct slot *slot);
+
+#ifdef CONFIG_HOTPLUG_PCI_CPCI
+int cpci_hotplug_init(int debug);
+void cpci_hotplug_exit(void);
+#else
+static inline int cpci_hotplug_init(int debug) { return 0; }
+static inline void cpci_hotplug_exit(void) { }
+#endif
#endif /* _CPCI_HOTPLUG_H */
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index d8ffc73..516b877 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -404,50 +404,44 @@
/* debugfs functions for the hotplug controller info */
-extern void cpqhp_initialize_debugfs(void);
-extern void cpqhp_shutdown_debugfs(void);
-extern void cpqhp_create_debugfs_files(struct controller *ctrl);
-extern void cpqhp_remove_debugfs_files(struct controller *ctrl);
+void cpqhp_initialize_debugfs(void);
+void cpqhp_shutdown_debugfs(void);
+void cpqhp_create_debugfs_files(struct controller *ctrl);
+void cpqhp_remove_debugfs_files(struct controller *ctrl);
/* controller functions */
-extern void cpqhp_pushbutton_thread(unsigned long event_pointer);
-extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
-extern int cpqhp_find_available_resources(struct controller *ctrl,
- void __iomem *rom_start);
-extern int cpqhp_event_start_thread(void);
-extern void cpqhp_event_stop_thread(void);
-extern struct pci_func *cpqhp_slot_create(unsigned char busnumber);
-extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
- unsigned char index);
-extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
-extern int cpqhp_hardware_test(struct controller *ctrl, int test_num);
+void cpqhp_pushbutton_thread(unsigned long event_pointer);
+irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data);
+int cpqhp_find_available_resources(struct controller *ctrl,
+ void __iomem *rom_start);
+int cpqhp_event_start_thread(void);
+void cpqhp_event_stop_thread(void);
+struct pci_func *cpqhp_slot_create(unsigned char busnumber);
+struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device,
+ unsigned char index);
+int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func);
+int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func);
+int cpqhp_hardware_test(struct controller *ctrl, int test_num);
/* resource functions */
-extern int cpqhp_resource_sort_and_combine (struct pci_resource **head);
+int cpqhp_resource_sort_and_combine (struct pci_resource **head);
/* pci functions */
-extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
- u8 slot);
-extern int cpqhp_save_config(struct controller *ctrl, int busnumber,
- int is_hot_plug);
-extern int cpqhp_save_base_addr_length(struct controller *ctrl,
- struct pci_func *func);
-extern int cpqhp_save_used_resources(struct controller *ctrl,
- struct pci_func *func);
-extern int cpqhp_configure_board(struct controller *ctrl,
- struct pci_func *func);
-extern int cpqhp_save_slot_config(struct controller *ctrl,
- struct pci_func *new_slot);
-extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
-extern void cpqhp_destroy_board_resources(struct pci_func *func);
-extern int cpqhp_return_board_resources (struct pci_func *func,
- struct resource_lists *resources);
-extern void cpqhp_destroy_resource_list(struct resource_lists *resources);
-extern int cpqhp_configure_device(struct controller *ctrl,
- struct pci_func *func);
-extern int cpqhp_unconfigure_device(struct pci_func *func);
+int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
+int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num,
+ u8 slot);
+int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug);
+int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func);
+int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func);
+int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func);
+int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot);
+int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func);
+void cpqhp_destroy_board_resources(struct pci_func *func);
+int cpqhp_return_board_resources(struct pci_func *func,
+ struct resource_lists *resources);
+void cpqhp_destroy_resource_list(struct resource_lists *resources);
+int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func);
+int cpqhp_unconfigure_device(struct pci_func *func);
/* Global variables */
extern int cpqhp_debug;
diff --git a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h
index e89c070..34e4e54 100644
--- a/drivers/pci/hotplug/cpqphp_nvram.h
+++ b/drivers/pci/hotplug/cpqphp_nvram.h
@@ -30,26 +30,26 @@
#ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM
-static inline void compaq_nvram_init (void __iomem *rom_start)
+static inline void compaq_nvram_init(void __iomem *rom_start)
{
return;
}
-static inline int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
+static inline int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl)
{
return 0;
}
-static inline int compaq_nvram_store (void __iomem *rom_start)
+static inline int compaq_nvram_store(void __iomem *rom_start)
{
return 0;
}
#else
-extern void compaq_nvram_init (void __iomem *rom_start);
-extern int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl);
-extern int compaq_nvram_store (void __iomem *rom_start);
+void compaq_nvram_init(void __iomem *rom_start);
+int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl);
+int compaq_nvram_store(void __iomem *rom_start);
#endif
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index a8d391a..8c5b258 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -275,17 +275,17 @@
* FUNCTION PROTOTYPES *
***********************************************************/
-extern void ibmphp_free_ebda_hpc_queue (void);
-extern int ibmphp_access_ebda (void);
-extern struct slot *ibmphp_get_slot_from_physical_num (u8);
-extern int ibmphp_get_total_hp_slots (void);
-extern void ibmphp_free_ibm_slot (struct slot *);
-extern void ibmphp_free_bus_info_queue (void);
-extern void ibmphp_free_ebda_pci_rsrc_queue (void);
-extern struct bus_info *ibmphp_find_same_bus_num (u32);
-extern int ibmphp_get_bus_index (u8);
-extern u16 ibmphp_get_total_controllers (void);
-extern int ibmphp_register_pci (void);
+void ibmphp_free_ebda_hpc_queue(void);
+int ibmphp_access_ebda(void);
+struct slot *ibmphp_get_slot_from_physical_num(u8);
+int ibmphp_get_total_hp_slots(void);
+void ibmphp_free_ibm_slot(struct slot *);
+void ibmphp_free_bus_info_queue(void);
+void ibmphp_free_ebda_pci_rsrc_queue(void);
+struct bus_info *ibmphp_find_same_bus_num(u32);
+int ibmphp_get_bus_index(u8);
+u16 ibmphp_get_total_controllers(void);
+int ibmphp_register_pci(void);
/* passed parameters */
#define MEM 0
@@ -381,24 +381,24 @@
/* functions */
-extern int ibmphp_rsrc_init (void);
-extern int ibmphp_add_resource (struct resource_node *);
-extern int ibmphp_remove_resource (struct resource_node *);
-extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int);
-extern int ibmphp_check_resource (struct resource_node *, u8);
-extern int ibmphp_remove_bus (struct bus_node *, u8);
-extern void ibmphp_free_resources (void);
-extern int ibmphp_add_pfmem_from_mem (struct resource_node *);
-extern struct bus_node *ibmphp_find_res_bus (u8);
-extern void ibmphp_print_test (void); /* for debugging purposes */
+int ibmphp_rsrc_init(void);
+int ibmphp_add_resource(struct resource_node *);
+int ibmphp_remove_resource(struct resource_node *);
+int ibmphp_find_resource(struct bus_node *, u32, struct resource_node **, int);
+int ibmphp_check_resource(struct resource_node *, u8);
+int ibmphp_remove_bus(struct bus_node *, u8);
+void ibmphp_free_resources(void);
+int ibmphp_add_pfmem_from_mem(struct resource_node *);
+struct bus_node *ibmphp_find_res_bus(u8);
+void ibmphp_print_test(void); /* for debugging purposes */
-extern void ibmphp_hpc_initvars (void);
-extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *);
-extern int ibmphp_hpc_writeslot (struct slot *, u8);
-extern void ibmphp_lock_operations (void);
-extern void ibmphp_unlock_operations (void);
-extern int ibmphp_hpc_start_poll_thread (void);
-extern void ibmphp_hpc_stop_poll_thread (void);
+void ibmphp_hpc_initvars(void);
+int ibmphp_hpc_readslot(struct slot *, u8, u8 *);
+int ibmphp_hpc_writeslot(struct slot *, u8);
+void ibmphp_lock_operations(void);
+void ibmphp_unlock_operations(void);
+int ibmphp_hpc_start_poll_thread(void);
+void ibmphp_hpc_stop_poll_thread(void);
//----------------------------------------------------------------------------
@@ -749,11 +749,11 @@
/* Functions */
-extern int ibmphp_init_devno (struct slot **); /* This function is called from EBDA, so we need it not be static */
-extern int ibmphp_do_disable_slot (struct slot *slot_cur);
-extern int ibmphp_update_slot_info (struct slot *); /* This function is called from HPC, so we need it to not be be static */
-extern int ibmphp_configure_card (struct pci_func *, u8);
-extern int ibmphp_unconfigure_card (struct slot **, int);
+int ibmphp_init_devno(struct slot **); /* This function is called from EBDA, so we need it not be static */
+int ibmphp_do_disable_slot(struct slot *slot_cur);
+int ibmphp_update_slot_info(struct slot *); /* This function is called from HPC, so we need it to not be be static */
+int ibmphp_configure_card(struct pci_func *, u8);
+int ibmphp_unconfigure_card(struct slot **, int);
extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops;
#endif //__IBMPHP_H
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 202f4a9..ec20f74 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -41,6 +41,7 @@
#include <linux/pci_hotplug.h>
#include <asm/uaccess.h>
#include "../pci.h"
+#include "cpci_hotplug.h"
#define MY_NAME "pci_hotplug"
@@ -63,14 +64,6 @@
static LIST_HEAD(pci_hotplug_slot_list);
static DEFINE_MUTEX(pci_hp_mutex);
-#ifdef CONFIG_HOTPLUG_PCI_CPCI
-extern int cpci_hotplug_init(int debug);
-extern void cpci_hotplug_exit(void);
-#else
-static inline int cpci_hotplug_init(int debug) { return 0; }
-static inline void cpci_hotplug_exit(void) { }
-#endif
-
/* Weee, fun with macros... */
#define GET_STATUS(name,type) \
static int get_##name (struct hotplug_slot *slot, type *value) \
@@ -524,13 +517,11 @@
*
* Returns 0 if successful, anything else for an error.
*/
-int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug,
- struct hotplug_slot_info *info)
+int pci_hp_change_slot_info(struct hotplug_slot *hotplug,
+ struct hotplug_slot_info *info)
{
- struct pci_slot *slot;
if (!hotplug || !info)
return -ENODEV;
- slot = hotplug->pci_slot;
memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info));
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 2c113de..7fb3269 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -127,15 +127,15 @@
#define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS)
#define PSN(ctrl) ((ctrl)->slot_cap >> 19)
-extern int pciehp_sysfs_enable_slot(struct slot *slot);
-extern int pciehp_sysfs_disable_slot(struct slot *slot);
-extern u8 pciehp_handle_attention_button(struct slot *p_slot);
-extern u8 pciehp_handle_switch_change(struct slot *p_slot);
-extern u8 pciehp_handle_presence_change(struct slot *p_slot);
-extern u8 pciehp_handle_power_fault(struct slot *p_slot);
-extern int pciehp_configure_device(struct slot *p_slot);
-extern int pciehp_unconfigure_device(struct slot *p_slot);
-extern void pciehp_queue_pushbutton_work(struct work_struct *work);
+int pciehp_sysfs_enable_slot(struct slot *slot);
+int pciehp_sysfs_disable_slot(struct slot *slot);
+u8 pciehp_handle_attention_button(struct slot *p_slot);
+u8 pciehp_handle_switch_change(struct slot *p_slot);
+u8 pciehp_handle_presence_change(struct slot *p_slot);
+u8 pciehp_handle_power_fault(struct slot *p_slot);
+int pciehp_configure_device(struct slot *p_slot);
+int pciehp_unconfigure_device(struct slot *p_slot);
+void pciehp_queue_pushbutton_work(struct work_struct *work);
struct controller *pcie_init(struct pcie_device *dev);
int pcie_init_notification(struct controller *ctrl);
int pciehp_enable_slot(struct slot *p_slot);
@@ -166,8 +166,8 @@
#include <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>
-extern void __init pciehp_acpi_slot_detection_init(void);
-extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev);
+void __init pciehp_acpi_slot_detection_init(void);
+int pciehp_acpi_slot_detection_check(struct pci_dev *dev);
static inline void pciehp_firmware_init(void)
{
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 24d709b..ead7c53 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -90,7 +90,7 @@
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
if (!slot)
return -ENOMEM;
- slot->number = slot_cap >> 19;
+ slot->number = (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19;
list_for_each_entry(tmp, &dummy_slots, list) {
if (tmp->number == slot->number)
dup_slot_id++;
diff --git a/drivers/pci/hotplug/rpadlpar.h b/drivers/pci/hotplug/rpadlpar.h
index 4a0a59b..81df939 100644
--- a/drivers/pci/hotplug/rpadlpar.h
+++ b/drivers/pci/hotplug/rpadlpar.h
@@ -15,10 +15,10 @@
#ifndef _RPADLPAR_IO_H_
#define _RPADLPAR_IO_H_
-extern int dlpar_sysfs_init(void);
-extern void dlpar_sysfs_exit(void);
+int dlpar_sysfs_init(void);
+void dlpar_sysfs_exit(void);
-extern int dlpar_add_slot(char *drc_name);
-extern int dlpar_remove_slot(char *drc_name);
+int dlpar_add_slot(char *drc_name);
+int dlpar_remove_slot(char *drc_name);
#endif
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index df56774..3135856 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -86,18 +86,18 @@
/* function prototypes */
/* rpaphp_pci.c */
-extern int rpaphp_enable_slot(struct slot *slot);
-extern int rpaphp_get_sensor_state(struct slot *slot, int *state);
+int rpaphp_enable_slot(struct slot *slot);
+int rpaphp_get_sensor_state(struct slot *slot, int *state);
/* rpaphp_core.c */
-extern int rpaphp_add_slot(struct device_node *dn);
-extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
+int rpaphp_add_slot(struct device_node *dn);
+int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
char **drc_name, char **drc_type, int *drc_power_domain);
/* rpaphp_slot.c */
-extern void dealloc_slot_struct(struct slot *slot);
-extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
-extern int rpaphp_register_slot(struct slot *slot);
-extern int rpaphp_deregister_slot(struct slot *slot);
+void dealloc_slot_struct(struct slot *slot);
+struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
+int rpaphp_register_slot(struct slot *slot);
+int rpaphp_deregister_slot(struct slot *slot);
#endif /* _PPC64PHP_H */
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index 7db249a..46a7b73 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -16,6 +16,7 @@
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/init.h>
+#include <asm/pci_debug.h>
#include <asm/sclp.h>
#define SLOT_NAME_SIZE 10
@@ -49,6 +50,7 @@
return -EIO;
rc = sclp_pci_configure(slot->zdev->fid);
+ zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, rc);
if (!rc) {
slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;
/* automatically scan the device after is was configured */
@@ -66,16 +68,16 @@
if (!zpci_fn_configured(slot->zdev->state))
return -EIO;
+ rc = zpci_disable_device(slot->zdev);
+ if (rc)
+ return rc;
/* TODO: we rely on the user to unbind/remove the device, is that plausible
* or do we need to trigger that here?
*/
rc = sclp_pci_deconfigure(slot->zdev->fid);
- if (!rc) {
- /* Fixme: better call List-PCI to find the disabled FH
- for the FID since the FH should be opaque... */
- slot->zdev->fh &= 0x7fffffff;
+ zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, rc);
+ if (!rc)
slot->zdev->state = ZPCI_FN_STATE_STANDBY;
- }
return rc;
}
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index b849f995..e260f20 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -168,19 +168,19 @@
#define WRONG_BUS_FREQUENCY 0x0000000D
#define POWER_FAILURE 0x0000000E
-extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
-extern void shpchp_remove_ctrl_files(struct controller *ctrl);
-extern int shpchp_sysfs_enable_slot(struct slot *slot);
-extern int shpchp_sysfs_disable_slot(struct slot *slot);
-extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
-extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
-extern int shpchp_configure_device(struct slot *p_slot);
-extern int shpchp_unconfigure_device(struct slot *p_slot);
-extern void cleanup_slots(struct controller *ctrl);
-extern void shpchp_queue_pushbutton_work(struct work_struct *work);
-extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
+int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
+void shpchp_remove_ctrl_files(struct controller *ctrl);
+int shpchp_sysfs_enable_slot(struct slot *slot);
+int shpchp_sysfs_disable_slot(struct slot *slot);
+u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
+u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
+int shpchp_configure_device(struct slot *p_slot);
+int shpchp_unconfigure_device(struct slot *p_slot);
+void cleanup_slots(struct controller *ctrl);
+void shpchp_queue_pushbutton_work(struct work_struct *work);
+int shpc_init( struct controller *ctrl, struct pci_dev *pdev);
static inline const char *slot_name(struct slot *slot)
{
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index eeb23ce..e8c31fe 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -85,7 +85,7 @@
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-int __must_check shpchp_create_ctrl_files (struct controller *ctrl)
+int shpchp_create_ctrl_files (struct controller *ctrl)
{
return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 00cc78c7..d40bed7 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -22,10 +22,12 @@
#include <linux/slab.h>
#include "pci.h"
-#include "msi.h"
static int pci_msi_enable = 1;
+#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1)
+
+
/* Arch hooks */
#ifndef arch_msi_check_device
@@ -111,32 +113,26 @@
}
#endif
-static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
+static void msi_set_enable(struct pci_dev *dev, int enable)
{
u16 control;
- BUG_ON(!pos);
-
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
control &= ~PCI_MSI_FLAGS_ENABLE;
if (enable)
control |= PCI_MSI_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
static void msix_set_enable(struct pci_dev *dev, int enable)
{
- int pos;
u16 control;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- if (pos) {
- pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
- control &= ~PCI_MSIX_FLAGS_ENABLE;
- if (enable)
- control |= PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
- }
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+ control &= ~PCI_MSIX_FLAGS_ENABLE;
+ if (enable)
+ control |= PCI_MSIX_FLAGS_ENABLE;
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
}
static inline __attribute_const__ u32 msi_mask(unsigned x)
@@ -247,18 +243,18 @@
msg->data = readl(base + PCI_MSIX_ENTRY_DATA);
} else {
struct pci_dev *dev = entry->dev;
- int pos = entry->msi_attrib.pos;
+ int pos = dev->msi_cap;
u16 data;
- pci_read_config_dword(dev, msi_lower_address_reg(pos),
- &msg->address_lo);
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
+ &msg->address_lo);
if (entry->msi_attrib.is_64) {
- pci_read_config_dword(dev, msi_upper_address_reg(pos),
- &msg->address_hi);
- pci_read_config_word(dev, msi_data_reg(pos, 1), &data);
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+ &msg->address_hi);
+ pci_read_config_word(dev, pos + PCI_MSI_DATA_64, &data);
} else {
msg->address_hi = 0;
- pci_read_config_word(dev, msi_data_reg(pos, 0), &data);
+ pci_read_config_word(dev, pos + PCI_MSI_DATA_32, &data);
}
msg->data = data;
}
@@ -302,24 +298,24 @@
writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
} else {
struct pci_dev *dev = entry->dev;
- int pos = entry->msi_attrib.pos;
+ int pos = dev->msi_cap;
u16 msgctl;
- pci_read_config_word(dev, msi_control_reg(pos), &msgctl);
+ pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
msgctl &= ~PCI_MSI_FLAGS_QSIZE;
msgctl |= entry->msi_attrib.multiple << 4;
- pci_write_config_word(dev, msi_control_reg(pos), msgctl);
+ pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl);
- pci_write_config_dword(dev, msi_lower_address_reg(pos),
- msg->address_lo);
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
+ msg->address_lo);
if (entry->msi_attrib.is_64) {
- pci_write_config_dword(dev, msi_upper_address_reg(pos),
- msg->address_hi);
- pci_write_config_word(dev, msi_data_reg(pos, 1),
- msg->data);
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+ msg->address_hi);
+ pci_write_config_word(dev, pos + PCI_MSI_DATA_64,
+ msg->data);
} else {
- pci_write_config_word(dev, msi_data_reg(pos, 0),
- msg->data);
+ pci_write_config_word(dev, pos + PCI_MSI_DATA_32,
+ msg->data);
}
}
entry->msg = *msg;
@@ -391,7 +387,6 @@
static void __pci_restore_msi_state(struct pci_dev *dev)
{
- int pos;
u16 control;
struct msi_desc *entry;
@@ -399,22 +394,20 @@
return;
entry = irq_get_msi_desc(dev->irq);
- pos = entry->msi_attrib.pos;
pci_intx_for_msi(dev, 0);
- msi_set_enable(dev, pos, 0);
+ msi_set_enable(dev, 0);
arch_restore_msi_irqs(dev, dev->irq);
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
control &= ~PCI_MSI_FLAGS_QSIZE;
control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
+ pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control);
}
static void __pci_restore_msix_state(struct pci_dev *dev)
{
- int pos;
struct msi_desc *entry;
u16 control;
@@ -422,13 +415,12 @@
return;
BUG_ON(list_empty(&dev->msi_list));
entry = list_first_entry(&dev->msi_list, struct msi_desc, list);
- pos = entry->msi_attrib.pos;
- pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
/* route the table */
pci_intx_for_msi(dev, 0);
control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
list_for_each_entry(entry, &dev->msi_list, list) {
arch_restore_msi_irqs(dev, entry->irq);
@@ -436,7 +428,7 @@
}
control &= ~PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
}
void pci_restore_msi_state(struct pci_dev *dev)
@@ -484,12 +476,12 @@
__ATTR(mode, S_IRUGO, show_msi_mode, NULL);
-struct attribute *msi_irq_default_attrs[] = {
+static struct attribute *msi_irq_default_attrs[] = {
&mode_attribute.attr,
NULL
};
-void msi_kobj_release(struct kobject *kobj)
+static void msi_kobj_release(struct kobject *kobj)
{
struct msi_desc *entry = to_msi_desc(kobj);
@@ -552,27 +544,27 @@
static int msi_capability_init(struct pci_dev *dev, int nvec)
{
struct msi_desc *entry;
- int pos, ret;
+ int ret;
u16 control;
unsigned mask;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- msi_set_enable(dev, pos, 0); /* Disable MSI during set up */
+ msi_set_enable(dev, 0); /* Disable MSI during set up */
- pci_read_config_word(dev, msi_control_reg(pos), &control);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
/* MSI Entry Initialization */
entry = alloc_msi_entry(dev);
if (!entry)
return -ENOMEM;
entry->msi_attrib.is_msix = 0;
- entry->msi_attrib.is_64 = is_64bit_address(control);
+ entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
entry->msi_attrib.entry_nr = 0;
- entry->msi_attrib.maskbit = is_mask_bit_support(control);
+ entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
- entry->msi_attrib.pos = pos;
+ entry->msi_attrib.pos = dev->msi_cap;
- entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64);
+ entry->mask_pos = dev->msi_cap + (control & PCI_MSI_FLAGS_64BIT) ?
+ PCI_MSI_MASK_64 : PCI_MSI_MASK_32;
/* All MSIs are unmasked by default, Mask them all */
if (entry->msi_attrib.maskbit)
pci_read_config_dword(dev, entry->mask_pos, &entry->masked);
@@ -598,31 +590,30 @@
/* Set MSI enabled bits */
pci_intx_for_msi(dev, 0);
- msi_set_enable(dev, pos, 1);
+ msi_set_enable(dev, 1);
dev->msi_enabled = 1;
dev->irq = entry->irq;
return 0;
}
-static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos,
- unsigned nr_entries)
+static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries)
{
resource_size_t phys_addr;
u32 table_offset;
u8 bir;
- pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset);
- bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
- table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+ pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE,
+ &table_offset);
+ bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR);
+ table_offset &= PCI_MSIX_TABLE_OFFSET;
phys_addr = pci_resource_start(dev, bir) + table_offset;
return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
}
-static int msix_setup_entries(struct pci_dev *dev, unsigned pos,
- void __iomem *base, struct msix_entry *entries,
- int nvec)
+static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
+ struct msix_entry *entries, int nvec)
{
struct msi_desc *entry;
int i;
@@ -642,7 +633,7 @@
entry->msi_attrib.is_64 = 1;
entry->msi_attrib.entry_nr = entries[i].entry;
entry->msi_attrib.default_irq = dev->irq;
- entry->msi_attrib.pos = pos;
+ entry->msi_attrib.pos = dev->msix_cap;
entry->mask_base = base;
list_add_tail(&entry->list, &dev->msi_list);
@@ -652,7 +643,7 @@
}
static void msix_program_entries(struct pci_dev *dev,
- struct msix_entry *entries)
+ struct msix_entry *entries)
{
struct msi_desc *entry;
int i = 0;
@@ -682,23 +673,22 @@
static int msix_capability_init(struct pci_dev *dev,
struct msix_entry *entries, int nvec)
{
- int pos, ret;
+ int ret;
u16 control;
void __iomem *base;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
/* Ensure MSI-X is disabled while it is set up */
control &= ~PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
/* Request & Map MSI-X table region */
- base = msix_map_region(dev, pos, multi_msix_capable(control));
+ base = msix_map_region(dev, msix_table_size(control));
if (!base)
return -ENOMEM;
- ret = msix_setup_entries(dev, pos, base, entries, nvec);
+ ret = msix_setup_entries(dev, base, entries, nvec);
if (ret)
return ret;
@@ -712,7 +702,7 @@
* interrupts coming in before they're fully set up.
*/
control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
msix_program_entries(dev, entries);
@@ -727,7 +717,7 @@
dev->msix_enabled = 1;
control &= ~PCI_MSIX_FLAGS_MASKALL;
- pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
+ pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control);
return 0;
@@ -795,9 +785,6 @@
if (ret)
return ret;
- if (!pci_find_capability(dev, type))
- return -EINVAL;
-
return 0;
}
@@ -816,13 +803,13 @@
*/
int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
{
- int status, pos, maxvec;
+ int status, maxvec;
u16 msgctl;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (!pos)
+ if (!dev->msi_cap)
return -EINVAL;
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
if (nvec > maxvec)
return maxvec;
@@ -847,14 +834,13 @@
int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
{
- int ret, pos, nvec;
+ int ret, nvec;
u16 msgctl;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (!pos)
+ if (!dev->msi_cap)
return -EINVAL;
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
if (maxvec)
@@ -876,21 +862,19 @@
struct msi_desc *desc;
u32 mask;
u16 ctrl;
- unsigned pos;
if (!pci_msi_enable || !dev || !dev->msi_enabled)
return;
BUG_ON(list_empty(&dev->msi_list));
desc = list_first_entry(&dev->msi_list, struct msi_desc, list);
- pos = desc->msi_attrib.pos;
- msi_set_enable(dev, pos, 0);
+ msi_set_enable(dev, 0);
pci_intx_for_msi(dev, 1);
dev->msi_enabled = 0;
/* Return the device with MSI unmasked as initial states */
- pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);
mask = msi_capable_mask(ctrl);
/* Keep cached state to be restored */
__msi_mask_irq(desc, mask, ~mask);
@@ -917,15 +901,13 @@
*/
int pci_msix_table_size(struct pci_dev *dev)
{
- int pos;
u16 control;
- pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
- if (!pos)
+ if (!dev->msix_cap)
return 0;
- pci_read_config_word(dev, msi_control_reg(pos), &control);
- return multi_msix_capable(control);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+ return msix_table_size(control);
}
/**
@@ -948,7 +930,7 @@
int status, nr_entries;
int i, j;
- if (!entries)
+ if (!entries || !dev->msix_cap)
return -EINVAL;
status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);
@@ -1048,15 +1030,17 @@
void pci_msi_init_pci_dev(struct pci_dev *dev)
{
- int pos;
INIT_LIST_HEAD(&dev->msi_list);
/* Disable the msi hardware to avoid screaming interrupts
* during boot. This is the power on reset default so
* usually this should be a noop.
*/
- pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
- if (pos)
- msi_set_enable(dev, pos, 0);
- msix_set_enable(dev, 0);
+ dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (dev->msi_cap)
+ msi_set_enable(dev, 0);
+
+ dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+ if (dev->msix_cap)
+ msix_set_enable(dev, 0);
}
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
deleted file mode 100644
index 65c42f8..0000000
--- a/drivers/pci/msi.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2003-2004 Intel
- * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
- */
-
-#ifndef MSI_H
-#define MSI_H
-
-#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
-#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO)
-#define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI)
-#define msi_data_reg(base, is64bit) \
- (base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32))
-#define msi_mask_reg(base, is64bit) \
- (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32))
-#define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT))
-#define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT))
-
-#define msix_table_offset_reg(base) (base + PCI_MSIX_TABLE)
-#define msix_pba_offset_reg(base) (base + PCI_MSIX_PBA)
-#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1)
-#define multi_msix_capable(control) msix_table_size((control))
-
-#endif /* MSI_H */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 5147c21..e4b1fb2 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -288,6 +288,32 @@
.run_wake = acpi_pci_run_wake,
};
+void acpi_pci_add_bus(struct pci_bus *bus)
+{
+ acpi_handle handle = NULL;
+
+ if (bus->bridge)
+ handle = ACPI_HANDLE(bus->bridge);
+ if (acpi_pci_disabled || handle == NULL)
+ return;
+
+ acpi_pci_slot_enumerate(bus, handle);
+ acpiphp_enumerate_slots(bus, handle);
+}
+
+void acpi_pci_remove_bus(struct pci_bus *bus)
+{
+ /*
+ * bus->bridge->acpi_node.handle has already been reset to NULL
+ * when acpi_pci_remove_bus() is called, so don't check ACPI handle.
+ */
+ if (acpi_pci_disabled)
+ return;
+
+ acpiphp_remove_slots(bus);
+ acpi_pci_slot_remove(bus);
+}
+
/* ACPI bus type */
static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
{
@@ -362,7 +388,11 @@
ret = register_acpi_bus_type(&acpi_pci_bus);
if (ret)
return 0;
+
pci_set_platform_pm(&acpi_pci_platform_pm);
+ acpi_pci_slot_init();
+ acpiphp_init();
+
return 0;
}
arch_initcall(acpi_pci_init);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9c6e9bb..5b4a9d9 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -897,7 +897,7 @@
if (pci_resource_len(pdev, resno) == 0)
return 0;
- nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+ nr = vma_pages(vma);
start = vma->vm_pgoff;
size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index b099e00..a899d8b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -646,15 +646,11 @@
error = platform_pci_set_power_state(dev, state);
if (!error)
pci_update_current_state(dev, state);
- /* Fall back to PCI_D0 if native PM is not supported */
- if (!dev->pm_cap)
- dev->current_state = PCI_D0;
- } else {
+ } else
error = -ENODEV;
- /* Fall back to PCI_D0 if native PM is not supported */
- if (!dev->pm_cap)
- dev->current_state = PCI_D0;
- }
+
+ if (error && !dev->pm_cap) /* Fall back to PCI_D0 */
+ dev->current_state = PCI_D0;
return error;
}
@@ -1575,7 +1571,7 @@
{
u16 pmcsr;
- if (!dev->pm_cap)
+ if (!dev->pme_support)
return;
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
@@ -1924,6 +1920,7 @@
dev->wakeup_prepared = false;
dev->pm_cap = 0;
+ dev->pme_support = 0;
/* find PCI PM capability in list */
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
@@ -1975,8 +1972,6 @@
device_set_wakeup_capable(&dev->dev, true);
/* Disable the PME# generation functionality */
pci_pme_active(dev, false);
- } else {
- dev->pme_support = 0;
}
}
@@ -2619,7 +2614,7 @@
pci_release_region(pdev, i);
}
-int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
+static int __pci_request_selected_regions(struct pci_dev *pdev, int bars,
const char *res_name, int excl)
{
int i;
@@ -3699,7 +3694,7 @@
* RETURNS: Resource alignment if it is specified.
* Zero if it is not specified.
*/
-resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
+static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
{
int seg, bus, slot, func, align_order, count;
resource_size_t align = 0;
@@ -3812,7 +3807,7 @@
}
}
-ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
+static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count)
{
if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1)
count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1;
@@ -3823,7 +3818,7 @@
return count;
}
-ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
+static ssize_t pci_get_resource_alignment_param(char *buf, size_t size)
{
size_t count;
spin_lock(&resource_alignment_lock);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 7346ee6..68678ed 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -8,26 +8,25 @@
/* Functions internal to the PCI core code */
-extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
-extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
+int pci_create_sysfs_dev_files(struct pci_dev *pdev);
+void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
{ return; }
static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
{ return; }
#else
-extern void pci_create_firmware_label_files(struct pci_dev *pdev);
-extern void pci_remove_firmware_label_files(struct pci_dev *pdev);
+void pci_create_firmware_label_files(struct pci_dev *pdev);
+void pci_remove_firmware_label_files(struct pci_dev *pdev);
#endif
-extern void pci_cleanup_rom(struct pci_dev *dev);
+void pci_cleanup_rom(struct pci_dev *dev);
#ifdef HAVE_PCI_MMAP
enum pci_mmap_api {
PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
};
-extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
- struct vm_area_struct *vmai,
- enum pci_mmap_api mmap_api);
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
+ enum pci_mmap_api mmap_api);
#endif
int pci_probe_reset_function(struct pci_dev *dev);
@@ -60,17 +59,17 @@
int (*run_wake)(struct pci_dev *dev, bool enable);
};
-extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
-extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
-extern void pci_power_up(struct pci_dev *dev);
-extern void pci_disable_enabled_device(struct pci_dev *dev);
-extern int pci_finish_runtime_suspend(struct pci_dev *dev);
-extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
-extern void pci_wakeup_bus(struct pci_bus *bus);
-extern void pci_config_pm_runtime_get(struct pci_dev *dev);
-extern void pci_config_pm_runtime_put(struct pci_dev *dev);
-extern void pci_pm_init(struct pci_dev *dev);
-extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
+int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
+void pci_power_up(struct pci_dev *dev);
+void pci_disable_enabled_device(struct pci_dev *dev);
+int pci_finish_runtime_suspend(struct pci_dev *dev);
+int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
+void pci_wakeup_bus(struct pci_bus *bus);
+void pci_config_pm_runtime_get(struct pci_dev *dev);
+void pci_config_pm_runtime_put(struct pci_dev *dev);
+void pci_pm_init(struct pci_dev *dev);
+void pci_allocate_cap_save_buffers(struct pci_dev *dev);
void pci_free_cap_save_buffers(struct pci_dev *dev);
static inline void pci_wakeup_event(struct pci_dev *dev)
@@ -96,7 +95,7 @@
struct bin_attribute *attr; /* descriptor for sysfs VPD entry */
};
-extern int pci_vpd_pci22_init(struct pci_dev *dev);
+int pci_vpd_pci22_init(struct pci_dev *dev);
static inline void pci_vpd_release(struct pci_dev *dev)
{
if (dev->vpd)
@@ -105,9 +104,9 @@
/* PCI /proc functions */
#ifdef CONFIG_PROC_FS
-extern int pci_proc_attach_device(struct pci_dev *dev);
-extern int pci_proc_detach_device(struct pci_dev *dev);
-extern int pci_proc_detach_bus(struct pci_bus *bus);
+int pci_proc_attach_device(struct pci_dev *dev);
+int pci_proc_detach_device(struct pci_dev *dev);
+int pci_proc_detach_bus(struct pci_bus *bus);
#else
static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; }
static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; }
@@ -118,8 +117,8 @@
int pci_hp_add_bridge(struct pci_dev *dev);
#ifdef HAVE_PCI_LEGACY
-extern void pci_create_legacy_files(struct pci_bus *bus);
-extern void pci_remove_legacy_files(struct pci_bus *bus);
+void pci_create_legacy_files(struct pci_bus *bus);
+void pci_remove_legacy_files(struct pci_bus *bus);
#else
static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
@@ -134,7 +133,7 @@
#ifdef CONFIG_PCI_MSI
void pci_no_msi(void);
-extern void pci_msi_init_pci_dev(struct pci_dev *dev);
+void pci_msi_init_pci_dev(struct pci_dev *dev);
#else
static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
@@ -198,12 +197,11 @@
bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl,
int crs_timeout);
-extern int pci_setup_device(struct pci_dev *dev);
-extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
- struct resource *res, unsigned int reg);
-extern int pci_resource_bar(struct pci_dev *dev, int resno,
- enum pci_bar_type *type);
-extern void pci_configure_ari(struct pci_dev *dev);
+int pci_setup_device(struct pci_dev *dev);
+int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
+ struct resource *res, unsigned int reg);
+int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);
+void pci_configure_ari(struct pci_dev *dev);
/**
* pci_ari_enabled - query ARI forwarding status
@@ -217,7 +215,7 @@
}
void pci_reassigndev_resource_alignment(struct pci_dev *dev);
-extern void pci_disable_bridge_window(struct pci_dev *dev);
+void pci_disable_bridge_window(struct pci_dev *dev);
/* Single Root I/O Virtualization */
struct pci_sriov {
@@ -241,7 +239,7 @@
};
#ifdef CONFIG_PCI_ATS
-extern void pci_restore_ats_state(struct pci_dev *dev);
+void pci_restore_ats_state(struct pci_dev *dev);
#else
static inline void pci_restore_ats_state(struct pci_dev *dev)
{
@@ -249,14 +247,13 @@
#endif /* CONFIG_PCI_ATS */
#ifdef CONFIG_PCI_IOV
-extern int pci_iov_init(struct pci_dev *dev);
-extern void pci_iov_release(struct pci_dev *dev);
-extern int pci_iov_resource_bar(struct pci_dev *dev, int resno,
- enum pci_bar_type *type);
-extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev,
- int resno);
-extern void pci_restore_iov_state(struct pci_dev *dev);
-extern int pci_iov_bus_range(struct pci_bus *bus);
+int pci_iov_init(struct pci_dev *dev);
+void pci_iov_release(struct pci_dev *dev);
+int pci_iov_resource_bar(struct pci_dev *dev, int resno,
+ enum pci_bar_type *type);
+resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno);
+void pci_restore_iov_state(struct pci_dev *dev);
+int pci_iov_bus_range(struct pci_bus *bus);
#else
static inline int pci_iov_init(struct pci_dev *dev)
@@ -282,10 +279,10 @@
#endif /* CONFIG_PCI_IOV */
-extern unsigned long pci_cardbus_resource_alignment(struct resource *);
+unsigned long pci_cardbus_resource_alignment(struct resource *);
static inline resource_size_t pci_resource_alignment(struct pci_dev *dev,
- struct resource *res)
+ struct resource *res)
{
#ifdef CONFIG_PCI_IOV
int resno = res - dev->resource;
@@ -298,7 +295,7 @@
return resource_alignment(res);
}
-extern void pci_enable_acs(struct pci_dev *dev);
+void pci_enable_acs(struct pci_dev *dev);
struct pci_dev_reset_methods {
u16 vendor;
@@ -307,7 +304,7 @@
};
#ifdef CONFIG_PCI_QUIRKS
-extern int pci_dev_specific_reset(struct pci_dev *dev, int probe);
+int pci_dev_specific_reset(struct pci_dev *dev, int probe);
#else
static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe)
{
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index fde4a32..569f82f 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -82,4 +82,4 @@
config PCIE_PME
def_bool y
- depends on PCIEPORTBUS && PM_RUNTIME && ACPI
+ depends on PCIEPORTBUS && PM_RUNTIME
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 4e24cb8..587e7e8 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -212,8 +212,8 @@
return ops->read(bus, devfn, where, size, val);
}
-int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
- u32 val)
+static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
{
u32 *sim;
struct aer_error *err;
@@ -334,13 +334,13 @@
return -ENODEV;
rpdev = pcie_find_root_port(dev);
if (!rpdev) {
- ret = -ENOTTY;
+ ret = -ENODEV;
goto out_put;
}
pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos_cap_err) {
- ret = -ENOTTY;
+ ret = -EPERM;
goto out_put;
}
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
@@ -350,7 +350,7 @@
rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
if (!rp_pos_cap_err) {
- ret = -ENOTTY;
+ ret = -EPERM;
goto out_put;
}
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 22f840f..d12c77c 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -110,15 +110,15 @@
}
extern struct bus_type pcie_port_bus_type;
-extern void aer_do_secondary_bus_reset(struct pci_dev *dev);
-extern int aer_init(struct pcie_device *dev);
-extern void aer_isr(struct work_struct *work);
-extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
-extern irqreturn_t aer_irq(int irq, void *context);
+void aer_do_secondary_bus_reset(struct pci_dev *dev);
+int aer_init(struct pcie_device *dev);
+void aer_isr(struct work_struct *work);
+void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
+void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
+irqreturn_t aer_irq(int irq, void *context);
#ifdef CONFIG_ACPI_APEI
-extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
+int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
#else
static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
{
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 564d97f..8ec8b4f 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -89,8 +89,6 @@
return -ENOSPC;
}
-#define PCI_BUS(x) (((x) >> 8) & 0xff)
-
/**
* is_error_source - check whether the device is source of reported error
* @dev: pointer to pci_dev to be checked
@@ -106,7 +104,7 @@
* When bus id is equal to 0, it might be a bad id
* reported by root port.
*/
- if (!nosourceid && (PCI_BUS(e_info->id) != 0)) {
+ if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) {
/* Device ID match? */
if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
return true;
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 9ca0dc9..795db1f 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -19,8 +19,6 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/pcieport_if.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
#include <linux/pm_runtime.h>
#include "../pci.h"
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index eea2ca2..d2eb80a 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -21,18 +21,18 @@
#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
extern struct bus_type pcie_port_bus_type;
-extern int pcie_port_device_register(struct pci_dev *dev);
+int pcie_port_device_register(struct pci_dev *dev);
#ifdef CONFIG_PM
-extern int pcie_port_device_suspend(struct device *dev);
-extern int pcie_port_device_resume(struct device *dev);
+int pcie_port_device_suspend(struct device *dev);
+int pcie_port_device_resume(struct device *dev);
#endif
-extern void pcie_port_device_remove(struct pci_dev *dev);
-extern int __must_check pcie_port_bus_register(void);
-extern void pcie_port_bus_unregister(void);
+void pcie_port_device_remove(struct pci_dev *dev);
+int __must_check pcie_port_bus_register(void);
+void pcie_port_bus_unregister(void);
struct pci_dev;
-extern void pcie_clear_root_pme_status(struct pci_dev *dev);
+void pcie_clear_root_pme_status(struct pci_dev *dev);
#ifdef CONFIG_HOTPLUG_PCI_PCIE
extern bool pciehp_msi_disabled;
@@ -59,7 +59,7 @@
return pcie_pme_msi_disabled;
}
-extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);
+void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable);
#else /* !CONFIG_PCIE_PME */
static inline void pcie_pme_disable_msi(void) {}
static inline bool pcie_pme_no_msi(void) { return false; }
@@ -67,7 +67,7 @@
#endif /* !CONFIG_PCIE_PME */
#ifdef CONFIG_ACPI
-extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask);
+int pcie_port_acpi_setup(struct pci_dev *port, int *mask);
static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask)
{
diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c
index a86b56e..b4d2894 100644
--- a/drivers/pci/pcie/portdrv_acpi.c
+++ b/drivers/pci/pcie/portdrv_acpi.c
@@ -17,6 +17,7 @@
#include "aer/aerdrv.h"
#include "../pci.h"
+#include "portdrv.h"
/**
* pcie_port_acpi_setup - Request the BIOS to release control of PCIe services.
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index ed4d094..696caed 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -259,11 +259,9 @@
enum pci_channel_state error)
{
struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER};
- int ret;
- /* can not fail */
- ret = device_for_each_child(&dev->dev, &data, error_detected_iter);
-
+ /* get true return value from &data */
+ device_for_each_child(&dev->dev, &data, error_detected_iter);
return data.result;
}
@@ -295,10 +293,9 @@
static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
{
pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
- int retval;
/* get true return value from &status */
- retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
+ device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
return status;
}
@@ -330,7 +327,6 @@
static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
{
pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
- int retval;
/* If fatal, restore cfg space for possible link reset at upstream */
if (dev->error_state == pci_channel_io_frozen) {
@@ -341,8 +337,7 @@
}
/* get true return value from &status */
- retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
-
+ device_for_each_child(&dev->dev, &status, slot_reset_iter);
return status;
}
@@ -368,9 +363,7 @@
static void pcie_portdrv_err_resume(struct pci_dev *dev)
{
- int retval;
- /* nothing to do with error value, if it ever happens */
- retval = device_for_each_child(&dev->dev, NULL, resume_iter);
+ device_for_each_child(&dev->dev, NULL, resume_iter);
}
/*
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b494066..43ece5d 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -673,6 +673,8 @@
ret = device_register(&child->dev);
WARN_ON(ret < 0);
+ pcibios_add_bus(child);
+
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(child);
@@ -1627,8 +1629,7 @@
if (!bus->is_added) {
dev_dbg(&bus->dev, "fixups for bus\n");
pcibios_fixup_bus(bus);
- if (pci_is_root_bus(bus))
- bus->is_added = 1;
+ bus->is_added = 1;
}
for (pass=0; pass < 2; pass++)
@@ -1661,6 +1662,14 @@
return 0;
}
+void __weak pcibios_add_bus(struct pci_bus *bus)
+{
+}
+
+void __weak pcibios_remove_bus(struct pci_bus *bus)
+{
+}
+
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
@@ -1715,6 +1724,8 @@
if (error)
goto class_dev_reg_err;
+ pcibios_add_bus(b);
+
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(b);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 0369fb6..7d68aee 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -324,29 +324,30 @@
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa);
-static void quirk_io_region(struct pci_dev *dev, unsigned region,
- unsigned size, int nr, const char *name)
+static void quirk_io_region(struct pci_dev *dev, int port,
+ unsigned size, int nr, const char *name)
{
- region &= ~(size-1);
- if (region) {
- struct pci_bus_region bus_region;
- struct resource *res = dev->resource + nr;
+ u16 region;
+ struct pci_bus_region bus_region;
+ struct resource *res = dev->resource + nr;
- res->name = pci_name(dev);
- res->start = region;
- res->end = region + size - 1;
- res->flags = IORESOURCE_IO;
+ pci_read_config_word(dev, port, ®ion);
+ region &= ~(size - 1);
- /* Convert from PCI bus to resource space. */
- bus_region.start = res->start;
- bus_region.end = res->end;
- pcibios_bus_to_resource(dev, res, &bus_region);
+ if (!region)
+ return;
- if (pci_claim_resource(dev, nr) == 0)
- dev_info(&dev->dev, "quirk: %pR claimed by %s\n",
- res, name);
- }
-}
+ res->name = pci_name(dev);
+ res->flags = IORESOURCE_IO;
+
+ /* Convert from PCI bus to resource space */
+ bus_region.start = region;
+ bus_region.end = region + size - 1;
+ pcibios_bus_to_resource(dev, res, &bus_region);
+
+ if (!pci_claim_resource(dev, nr))
+ dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
+}
/*
* ATI Northbridge setups MCE the processor if you even
@@ -374,12 +375,8 @@
*/
static void quirk_ali7101_acpi(struct pci_dev *dev)
{
- u16 region;
-
- pci_read_config_word(dev, 0xE0, ®ion);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
- pci_read_config_word(dev, 0xE2, ®ion);
- quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
+ quirk_io_region(dev, 0xE0, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
+ quirk_io_region(dev, 0xE2, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi);
@@ -442,12 +439,10 @@
*/
static void quirk_piix4_acpi(struct pci_dev *dev)
{
- u32 region, res_a;
+ u32 res_a;
- pci_read_config_dword(dev, 0x40, ®ion);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
- pci_read_config_dword(dev, 0x90, ®ion);
- quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
+ quirk_io_region(dev, 0x40, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
+ quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB");
/* Device resource A has enables for some of the other ones */
pci_read_config_dword(dev, 0x5c, &res_a);
@@ -491,7 +486,6 @@
*/
static void quirk_ich4_lpc_acpi(struct pci_dev *dev)
{
- u32 region;
u8 enable;
/*
@@ -503,22 +497,14 @@
*/
pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
- if (enable & ICH4_ACPI_EN) {
- pci_read_config_dword(dev, ICH_PMBASE, ®ion);
- region &= PCI_BASE_ADDRESS_IO_MASK;
- if (region >= PCIBIOS_MIN_IO)
- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
- "ICH4 ACPI/GPIO/TCO");
- }
+ if (enable & ICH4_ACPI_EN)
+ quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES,
+ "ICH4 ACPI/GPIO/TCO");
pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
- if (enable & ICH4_GPIO_EN) {
- pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion);
- region &= PCI_BASE_ADDRESS_IO_MASK;
- if (region >= PCIBIOS_MIN_IO)
- quirk_io_region(dev, region, 64,
- PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
- }
+ if (enable & ICH4_GPIO_EN)
+ quirk_io_region(dev, ICH4_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1,
+ "ICH4 GPIO");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi);
@@ -533,26 +519,17 @@
static void ich6_lpc_acpi_gpio(struct pci_dev *dev)
{
- u32 region;
u8 enable;
pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
- if (enable & ICH6_ACPI_EN) {
- pci_read_config_dword(dev, ICH_PMBASE, ®ion);
- region &= PCI_BASE_ADDRESS_IO_MASK;
- if (region >= PCIBIOS_MIN_IO)
- quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
- "ICH6 ACPI/GPIO/TCO");
- }
+ if (enable & ICH6_ACPI_EN)
+ quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES,
+ "ICH6 ACPI/GPIO/TCO");
pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
- if (enable & ICH6_GPIO_EN) {
- pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion);
- region &= PCI_BASE_ADDRESS_IO_MASK;
- if (region >= PCIBIOS_MIN_IO)
- quirk_io_region(dev, region, 64,
- PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
- }
+ if (enable & ICH6_GPIO_EN)
+ quirk_io_region(dev, ICH6_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1,
+ "ICH6 GPIO");
}
static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -650,13 +627,9 @@
*/
static void quirk_vt82c586_acpi(struct pci_dev *dev)
{
- u32 region;
-
- if (dev->revision & 0x10) {
- pci_read_config_dword(dev, 0x48, ®ion);
- region &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
- }
+ if (dev->revision & 0x10)
+ quirk_io_region(dev, 0x48, 256, PCI_BRIDGE_RESOURCES,
+ "vt82c586 ACPI");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi);
@@ -668,18 +641,12 @@
*/
static void quirk_vt82c686_acpi(struct pci_dev *dev)
{
- u16 hm;
- u32 smb;
-
quirk_vt82c586_acpi(dev);
- pci_read_config_word(dev, 0x70, &hm);
- hm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon");
+ quirk_io_region(dev, 0x70, 128, PCI_BRIDGE_RESOURCES+1,
+ "vt82c686 HW-mon");
- pci_read_config_dword(dev, 0x90, &smb);
- smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
+ quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+2, "vt82c686 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi);
@@ -690,15 +657,8 @@
*/
static void quirk_vt8235_acpi(struct pci_dev *dev)
{
- u16 pm, smb;
-
- pci_read_config_word(dev, 0x88, &pm);
- pm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
-
- pci_read_config_word(dev, 0xd0, &smb);
- smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB");
+ quirk_io_region(dev, 0x88, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM");
+ quirk_io_region(dev, 0xd0, 16, PCI_BRIDGE_RESOURCES+1, "vt8235 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi);
@@ -2594,6 +2554,14 @@
dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
pci_dev_put(p);
}
+static void quirk_msi_intx_disable_qca_bug(struct pci_dev *dev)
+{
+ /* AR816X/AR817X/E210X MSI is fixed at HW level from revision 0x18 */
+ if (dev->revision < 0x18) {
+ dev_info(&dev->dev, "set MSI_INTX_DISABLE_BUG flag\n");
+ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+ }
+}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
PCI_DEVICE_ID_TIGON3_5780,
quirk_msi_intx_disable_bug);
@@ -2643,6 +2611,16 @@
quirk_msi_intx_disable_bug);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083,
quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1090,
+ quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1091,
+ quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a0,
+ quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a1,
+ quirk_msi_intx_disable_qca_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091,
+ quirk_msi_intx_disable_qca_bug);
#endif /* CONFIG_PCI_MSI */
/* Allow manual resource allocation for PCI hotplug bridges
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index cc875e6..8fc54b7 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -50,10 +50,8 @@
list_del(&bus->node);
pci_bus_release_busn_res(bus);
up_write(&pci_bus_sem);
- if (!bus->is_added)
- return;
-
pci_remove_legacy_files(bus);
+ pcibios_remove_bus(bus);
device_unregister(&bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 7e8739e..16abaaa 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1044,7 +1044,7 @@
;
}
-void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+static void __ref __pci_bus_size_bridges(struct pci_bus *bus,
struct list_head *realloc_head)
{
struct pci_dev *dev;
@@ -1545,6 +1545,8 @@
enable_all:
retval = pci_reenable_device(bridge);
+ if (retval)
+ dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval);
pci_set_master(bridge);
pci_enable_bridges(parent);
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 81b88bd..07f2edd 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -261,7 +261,6 @@
{
struct resource *res = dev->resource + resno;
resource_size_t align, size;
- struct pci_bus *bus;
int ret;
align = pci_resource_alignment(dev, res);
@@ -271,7 +270,6 @@
return -EINVAL;
}
- bus = dev->bus;
size = resource_size(res);
ret = _pci_assign_resource(dev, resno, size, align);
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index ac6412f..c1e9284 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -377,14 +377,17 @@
{
struct hotplug_slot *slot = pci_slot->hotplug;
struct kobject *kobj = NULL;
- int no_warn;
+ int ret;
if (!slot || !slot->ops)
return;
kobj = kset_find_obj(module_kset, slot->ops->mod_name);
if (!kobj)
return;
- no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module");
+ ret = sysfs_create_link(&pci_slot->kobj, kobj, "module");
+ if (ret)
+ dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n",
+ ret);
kobject_put(kobj);
}
EXPORT_SYMBOL_GPL(pci_hp_create_module_link);
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 34f51d2..f910962 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -106,20 +106,11 @@
select PINMUX
select PINCONF
-config PINCTRL_PXA3xx
- bool
- select PINMUX
-
config PINCTRL_FALCON
bool
depends on SOC_FALCON
depends on PINCTRL_LANTIQ
-config PINCTRL_MMP2
- bool "MMP2 pin controller driver"
- depends on ARCH_MMP
- select PINCTRL_PXA3xx
-
config PINCTRL_MXS
bool
select PINMUX
@@ -151,21 +142,12 @@
bool "DB8540 pin controller driver"
depends on PINCTRL_NOMADIK && ARCH_U8500
-config PINCTRL_PXA168
- bool "PXA168 pin controller driver"
- depends on ARCH_MMP
- select PINCTRL_PXA3xx
-
-config PINCTRL_PXA910
- bool "PXA910 pin controller driver"
- depends on ARCH_MMP
- select PINCTRL_PXA3xx
-
config PINCTRL_SINGLE
tristate "One-register-per-pin type device tree based pinctrl driver"
depends on OF
select PINMUX
select PINCONF
+ select GENERIC_PINCONF
help
This selects the device tree based generic pinctrl driver.
@@ -226,6 +208,11 @@
select PINMUX
select PINCONF
+config PINCTRL_S3C64XX
+ bool "Samsung S3C64XX SoC pinctrl driver"
+ depends on ARCH_S3C64XX
+ select PINCTRL_SAMSUNG
+
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/sh-pfc/Kconfig"
source "drivers/pinctrl/spear/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f82cc5b..988279a 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -21,9 +21,7 @@
obj-$(CONFIG_PINCTRL_IMX51) += pinctrl-imx51.o
obj-$(CONFIG_PINCTRL_IMX53) += pinctrl-imx53.o
obj-$(CONFIG_PINCTRL_IMX6Q) += pinctrl-imx6q.o
-obj-$(CONFIG_PINCTRL_PXA3xx) += pinctrl-pxa3xx.o
obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o
-obj-$(CONFIG_PINCTRL_MMP2) += pinctrl-mmp2.o
obj-$(CONFIG_PINCTRL_MXS) += pinctrl-mxs.o
obj-$(CONFIG_PINCTRL_IMX23) += pinctrl-imx23.o
obj-$(CONFIG_PINCTRL_IMX28) += pinctrl-imx28.o
@@ -31,8 +29,6 @@
obj-$(CONFIG_PINCTRL_STN8815) += pinctrl-nomadik-stn8815.o
obj-$(CONFIG_PINCTRL_DB8500) += pinctrl-nomadik-db8500.o
obj-$(CONFIG_PINCTRL_DB8540) += pinctrl-nomadik-db8540.o
-obj-$(CONFIG_PINCTRL_PXA168) += pinctrl-pxa168.o
-obj-$(CONFIG_PINCTRL_PXA910) += pinctrl-pxa910.o
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_SIRF) += pinctrl-sirf.o
obj-$(CONFIG_PINCTRL_SUNXI) += pinctrl-sunxi.o
@@ -45,6 +41,7 @@
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_EXYNOS5440) += pinctrl-exynos5440.o
+obj-$(CONFIG_PINCTRL_S3C64XX) += pinctrl-s3c64xx.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b0de6e7..c3d222e 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -27,6 +27,11 @@
#include <linux/pinctrl/consumer.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/machine.h>
+
+#ifdef CONFIG_GPIOLIB
+#include <asm-generic/gpio.h>
+#endif
+
#include "core.h"
#include "devicetree.h"
#include "pinmux.h"
@@ -35,11 +40,17 @@
static bool pinctrl_dummy_state;
-/* Mutex taken by all entry points */
-DEFINE_MUTEX(pinctrl_mutex);
+/* Mutex taken to protect pinctrl_list */
+DEFINE_MUTEX(pinctrl_list_mutex);
+
+/* Mutex taken to protect pinctrl_maps */
+DEFINE_MUTEX(pinctrl_maps_mutex);
+
+/* Mutex taken to protect pinctrldev_list */
+DEFINE_MUTEX(pinctrldev_list_mutex);
/* Global list of pin control devices (struct pinctrl_dev) */
-LIST_HEAD(pinctrldev_list);
+static LIST_HEAD(pinctrldev_list);
/* List of pin controller handles (struct pinctrl) */
static LIST_HEAD(pinctrl_list);
@@ -106,6 +117,23 @@
return found ? pctldev : NULL;
}
+struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np)
+{
+ struct pinctrl_dev *pctldev;
+
+ mutex_lock(&pinctrldev_list_mutex);
+
+ list_for_each_entry(pctldev, &pinctrldev_list, node)
+ if (pctldev->dev->of_node == np) {
+ mutex_unlock(&pinctrldev_list_mutex);
+ return pctldev;
+ }
+
+ mutex_lock(&pinctrldev_list_mutex);
+
+ return NULL;
+}
+
/**
* pin_get_from_name() - look up a pin number from a name
* @pctldev: the pin control device to lookup the pin on
@@ -165,9 +193,9 @@
if (pin < 0)
return false;
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
pindesc = pin_desc_get(pctldev, pin);
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return pindesc != NULL;
}
@@ -264,19 +292,58 @@
{
struct pinctrl_gpio_range *range = NULL;
+ mutex_lock(&pctldev->mutex);
/* Loop over the ranges */
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
/* Check if we're in the valid range */
if (gpio >= range->base &&
gpio < range->base + range->npins) {
+ mutex_unlock(&pctldev->mutex);
return range;
}
}
-
+ mutex_unlock(&pctldev->mutex);
return NULL;
}
/**
+ * pinctrl_ready_for_gpio_range() - check if other GPIO pins of
+ * the same GPIO chip are in range
+ * @gpio: gpio pin to check taken from the global GPIO pin space
+ *
+ * This function is complement of pinctrl_match_gpio_range(). If the return
+ * value of pinctrl_match_gpio_range() is NULL, this function could be used
+ * to check whether pinctrl device is ready or not. Maybe some GPIO pins
+ * of the same GPIO chip don't have back-end pinctrl interface.
+ * If the return value is true, it means that pinctrl device is ready & the
+ * certain GPIO pin doesn't have back-end pinctrl device. If the return value
+ * is false, it means that pinctrl device may not be ready.
+ */
+#ifdef CONFIG_GPIOLIB
+static bool pinctrl_ready_for_gpio_range(unsigned gpio)
+{
+ struct pinctrl_dev *pctldev;
+ struct pinctrl_gpio_range *range = NULL;
+ struct gpio_chip *chip = gpio_to_chip(gpio);
+
+ /* Loop over the pin controllers */
+ list_for_each_entry(pctldev, &pinctrldev_list, node) {
+ /* Loop over the ranges */
+ list_for_each_entry(range, &pctldev->gpio_ranges, node) {
+ /* Check if any gpio range overlapped with gpio chip */
+ if (range->base + range->npins - 1 < chip->base ||
+ range->base > chip->base + chip->ngpio - 1)
+ continue;
+ return true;
+ }
+ }
+ return false;
+}
+#else
+static bool pinctrl_ready_for_gpio_range(unsigned gpio) { return true; }
+#endif
+
+/**
* pinctrl_get_device_gpio_range() - find device for GPIO range
* @gpio: the pin to locate the pin controller for
* @outdev: the pin control device if found
@@ -319,9 +386,9 @@
void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
list_add_tail(&range->node, &pctldev->gpio_ranges);
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_range);
@@ -339,17 +406,25 @@
struct pinctrl_dev *pinctrl_find_and_add_gpio_range(const char *devname,
struct pinctrl_gpio_range *range)
{
- struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+ struct pinctrl_dev *pctldev;
+
+ mutex_lock(&pinctrldev_list_mutex);
+
+ pctldev = get_pinctrl_dev_from_devname(devname);
/*
* If we can't find this device, let's assume that is because
* it has not probed yet, so the driver trying to register this
* range need to defer probing.
*/
- if (!pctldev)
+ if (!pctldev) {
+ mutex_unlock(&pinctrldev_list_mutex);
return ERR_PTR(-EPROBE_DEFER);
-
+ }
pinctrl_add_gpio_range(pctldev, range);
+
+ mutex_unlock(&pinctrldev_list_mutex);
+
return pctldev;
}
EXPORT_SYMBOL_GPL(pinctrl_find_and_add_gpio_range);
@@ -365,14 +440,17 @@
{
struct pinctrl_gpio_range *range = NULL;
+ mutex_lock(&pctldev->mutex);
/* Loop over the ranges */
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
/* Check if we're in the valid range */
if (pin >= range->pin_base &&
pin < range->pin_base + range->npins) {
+ mutex_unlock(&pctldev->mutex);
return range;
}
}
+ mutex_unlock(&pctldev->mutex);
return NULL;
}
@@ -386,9 +464,9 @@
void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
list_del(&range->node);
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
@@ -439,11 +517,13 @@
int ret;
int pin;
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pinctrldev_list_mutex);
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret) {
- mutex_unlock(&pinctrl_mutex);
+ if (pinctrl_ready_for_gpio_range(gpio))
+ ret = 0;
+ mutex_unlock(&pinctrldev_list_mutex);
return ret;
}
@@ -452,7 +532,7 @@
ret = pinmux_request_gpio(pctldev, range, pin, gpio);
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(pinctrl_request_gpio);
@@ -472,20 +552,22 @@
int ret;
int pin;
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pinctrldev_list_mutex);
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
if (ret) {
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
return;
}
+ mutex_lock(&pctldev->mutex);
/* Convert to the pin controllers number space */
pin = gpio - range->base + range->pin_base;
pinmux_free_gpio(pctldev, pin, range);
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_free_gpio);
@@ -496,14 +578,24 @@
int ret;
int pin;
+ mutex_lock(&pinctrldev_list_mutex);
+
ret = pinctrl_get_device_gpio_range(gpio, &pctldev, &range);
- if (ret)
+ if (ret) {
+ mutex_unlock(&pinctrldev_list_mutex);
return ret;
+ }
+
+ mutex_lock(&pctldev->mutex);
/* Convert to the pin controllers number space */
pin = gpio - range->base + range->pin_base;
+ ret = pinmux_gpio_direction(pctldev, range, pin, input);
- return pinmux_gpio_direction(pctldev, range, pin, input);
+ mutex_unlock(&pctldev->mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
+
+ return ret;
}
/**
@@ -516,11 +608,7 @@
*/
int pinctrl_gpio_direction_input(unsigned gpio)
{
- int ret;
- mutex_lock(&pinctrl_mutex);
- ret = pinctrl_gpio_direction(gpio, true);
- mutex_unlock(&pinctrl_mutex);
- return ret;
+ return pinctrl_gpio_direction(gpio, true);
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_input);
@@ -534,11 +622,7 @@
*/
int pinctrl_gpio_direction_output(unsigned gpio)
{
- int ret;
- mutex_lock(&pinctrl_mutex);
- ret = pinctrl_gpio_direction(gpio, false);
- mutex_unlock(&pinctrl_mutex);
- return ret;
+ return pinctrl_gpio_direction(gpio, false);
}
EXPORT_SYMBOL_GPL(pinctrl_gpio_direction_output);
@@ -641,14 +725,18 @@
{
struct pinctrl *p;
+ mutex_lock(&pinctrl_list_mutex);
list_for_each_entry(p, &pinctrl_list, node)
- if (p->dev == dev)
+ if (p->dev == dev) {
+ mutex_unlock(&pinctrl_list_mutex);
return p;
+ }
+ mutex_unlock(&pinctrl_list_mutex);
return NULL;
}
-static void pinctrl_put_locked(struct pinctrl *p, bool inlist);
+static void pinctrl_free(struct pinctrl *p, bool inlist);
static struct pinctrl *create_pinctrl(struct device *dev)
{
@@ -681,6 +769,7 @@
devname = dev_name(dev);
+ mutex_lock(&pinctrl_maps_mutex);
/* Iterate over the pin control maps to locate the right ones */
for_each_maps(maps_node, i, map) {
/* Map must be for this device */
@@ -702,13 +791,16 @@
* an -EPROBE_DEFER later, as that is the worst case.
*/
if (ret == -EPROBE_DEFER) {
- pinctrl_put_locked(p, false);
+ pinctrl_free(p, false);
+ mutex_unlock(&pinctrl_maps_mutex);
return ERR_PTR(ret);
}
}
+ mutex_unlock(&pinctrl_maps_mutex);
+
if (ret < 0) {
/* If some other error than deferral occured, return here */
- pinctrl_put_locked(p, false);
+ pinctrl_free(p, false);
return ERR_PTR(ret);
}
@@ -720,7 +812,11 @@
return p;
}
-static struct pinctrl *pinctrl_get_locked(struct device *dev)
+/**
+ * pinctrl_get() - retrieves the pinctrl handle for a device
+ * @dev: the device to obtain the handle for
+ */
+struct pinctrl *pinctrl_get(struct device *dev)
{
struct pinctrl *p;
@@ -741,43 +837,35 @@
return create_pinctrl(dev);
}
-
-/**
- * pinctrl_get() - retrieves the pinctrl handle for a device
- * @dev: the device to obtain the handle for
- */
-struct pinctrl *pinctrl_get(struct device *dev)
-{
- struct pinctrl *p;
-
- mutex_lock(&pinctrl_mutex);
- p = pinctrl_get_locked(dev);
- mutex_unlock(&pinctrl_mutex);
-
- return p;
-}
EXPORT_SYMBOL_GPL(pinctrl_get);
-static void pinctrl_put_locked(struct pinctrl *p, bool inlist)
+static void pinctrl_free_setting(bool disable_setting,
+ struct pinctrl_setting *setting)
+{
+ switch (setting->type) {
+ case PIN_MAP_TYPE_MUX_GROUP:
+ if (disable_setting)
+ pinmux_disable_setting(setting);
+ pinmux_free_setting(setting);
+ break;
+ case PIN_MAP_TYPE_CONFIGS_PIN:
+ case PIN_MAP_TYPE_CONFIGS_GROUP:
+ pinconf_free_setting(setting);
+ break;
+ default:
+ break;
+ }
+}
+
+static void pinctrl_free(struct pinctrl *p, bool inlist)
{
struct pinctrl_state *state, *n1;
struct pinctrl_setting *setting, *n2;
+ mutex_lock(&pinctrl_list_mutex);
list_for_each_entry_safe(state, n1, &p->states, node) {
list_for_each_entry_safe(setting, n2, &state->settings, node) {
- switch (setting->type) {
- case PIN_MAP_TYPE_MUX_GROUP:
- if (state == p->state)
- pinmux_disable_setting(setting);
- pinmux_free_setting(setting);
- break;
- case PIN_MAP_TYPE_CONFIGS_PIN:
- case PIN_MAP_TYPE_CONFIGS_GROUP:
- pinconf_free_setting(setting);
- break;
- default:
- break;
- }
+ pinctrl_free_setting(state == p->state, setting);
list_del(&setting->node);
kfree(setting);
}
@@ -790,6 +878,7 @@
if (inlist)
list_del(&p->node);
kfree(p);
+ mutex_unlock(&pinctrl_list_mutex);
}
/**
@@ -800,7 +889,7 @@
{
struct pinctrl *p = container_of(kref, struct pinctrl, users);
- pinctrl_put_locked(p, true);
+ pinctrl_free(p, true);
}
/**
@@ -809,14 +898,17 @@
*/
void pinctrl_put(struct pinctrl *p)
{
- mutex_lock(&pinctrl_mutex);
kref_put(&p->users, pinctrl_release);
- mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_put);
-static struct pinctrl_state *pinctrl_lookup_state_locked(struct pinctrl *p,
- const char *name)
+/**
+ * pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
+ * @p: the pinctrl handle to retrieve the state from
+ * @name: the state name to retrieve
+ */
+struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,
+ const char *name)
{
struct pinctrl_state *state;
@@ -833,28 +925,17 @@
return state;
}
-
-/**
- * pinctrl_lookup_state() - retrieves a state handle from a pinctrl handle
- * @p: the pinctrl handle to retrieve the state from
- * @name: the state name to retrieve
- */
-struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p, const char *name)
-{
- struct pinctrl_state *s;
-
- mutex_lock(&pinctrl_mutex);
- s = pinctrl_lookup_state_locked(p, name);
- mutex_unlock(&pinctrl_mutex);
-
- return s;
-}
EXPORT_SYMBOL_GPL(pinctrl_lookup_state);
-static int pinctrl_select_state_locked(struct pinctrl *p,
- struct pinctrl_state *state)
+/**
+ * pinctrl_select_state() - select/activate/program a pinctrl state to HW
+ * @p: the pinctrl handle for the device that requests configuration
+ * @state: the state handle to select/activate/program
+ */
+int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
{
struct pinctrl_setting *setting, *setting2;
+ struct pinctrl_state *old_state = p->state;
int ret;
if (p->state == state)
@@ -888,7 +969,7 @@
}
}
- p->state = state;
+ p->state = NULL;
/* Apply all the settings for the new state */
list_for_each_entry(setting, &state->settings, node) {
@@ -904,27 +985,36 @@
ret = -EINVAL;
break;
}
+
if (ret < 0) {
- /* FIXME: Difficult to return to prev state */
- return ret;
+ goto unapply_new_state;
}
}
+ p->state = state;
+
return 0;
-}
-/**
- * pinctrl_select() - select/activate/program a pinctrl state to HW
- * @p: the pinctrl handle for the device that requests configuratio
- * @state: the state handle to select/activate/program
- */
-int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)
-{
- int ret;
+unapply_new_state:
+ dev_err(p->dev, "Error applying setting, reverse things back\n");
- mutex_lock(&pinctrl_mutex);
- ret = pinctrl_select_state_locked(p, state);
- mutex_unlock(&pinctrl_mutex);
+ list_for_each_entry(setting2, &state->settings, node) {
+ if (&setting2->node == &setting->node)
+ break;
+ /*
+ * All we can do here is pinmux_disable_setting.
+ * That means that some pins are muxed differently now
+ * than they were before applying the setting (We can't
+ * "unmux a pin"!), but it's not a big deal since the pins
+ * are free to be muxed by another apply_setting.
+ */
+ if (setting2->type == PIN_MAP_TYPE_MUX_GROUP)
+ pinmux_disable_setting(setting2);
+ }
+
+ /* There's no infinite recursive loop here because p->state is NULL */
+ if (old_state)
+ pinctrl_select_state(p, old_state);
return ret;
}
@@ -979,9 +1069,8 @@
*/
void devm_pinctrl_put(struct pinctrl *p)
{
- WARN_ON(devres_destroy(p->dev, devm_pinctrl_release,
+ WARN_ON(devres_release(p->dev, devm_pinctrl_release,
devm_pinctrl_match, p));
- pinctrl_put(p);
}
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
@@ -1055,10 +1144,10 @@
}
if (!locked)
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pinctrl_maps_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps);
if (!locked)
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrl_maps_mutex);
return 0;
}
@@ -1080,12 +1169,15 @@
{
struct pinctrl_maps *maps_node;
+ mutex_lock(&pinctrl_maps_mutex);
list_for_each_entry(maps_node, &pinctrl_maps, node) {
if (maps_node->maps == map) {
list_del(&maps_node->node);
+ mutex_unlock(&pinctrl_maps_mutex);
return;
}
}
+ mutex_unlock(&pinctrl_maps_mutex);
}
/**
@@ -1122,7 +1214,7 @@
seq_printf(s, "registered pins: %d\n", pctldev->desc->npins);
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
@@ -1144,7 +1236,7 @@
seq_puts(s, "\n");
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
@@ -1155,8 +1247,9 @@
const struct pinctrl_ops *ops = pctldev->desc->pctlops;
unsigned ngroups, selector = 0;
+ mutex_lock(&pctldev->mutex);
+
ngroups = ops->get_groups_count(pctldev);
- mutex_lock(&pinctrl_mutex);
seq_puts(s, "registered pin groups:\n");
while (selector < ngroups) {
@@ -1177,7 +1270,7 @@
for (i = 0; i < num_pins; i++) {
pname = pin_get_name(pctldev, pins[i]);
if (WARN_ON(!pname)) {
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return -EINVAL;
}
seq_printf(s, "pin %d (%s)\n", pins[i], pname);
@@ -1187,7 +1280,7 @@
selector++;
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
@@ -1199,7 +1292,7 @@
seq_puts(s, "GPIO ranges handled:\n");
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
/* Loop over the ranges */
list_for_each_entry(range, &pctldev->gpio_ranges, node) {
@@ -1210,7 +1303,7 @@
(range->pin_base + range->npins - 1));
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
@@ -1221,7 +1314,7 @@
seq_puts(s, "name [pinmux] [pinconf]\n");
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pinctrldev_list_mutex);
list_for_each_entry(pctldev, &pinctrldev_list, node) {
seq_printf(s, "%s ", pctldev->desc->name);
@@ -1236,7 +1329,7 @@
seq_puts(s, "\n");
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
return 0;
}
@@ -1265,8 +1358,7 @@
seq_puts(s, "Pinctrl maps:\n");
- mutex_lock(&pinctrl_mutex);
-
+ mutex_lock(&pinctrl_maps_mutex);
for_each_maps(maps_node, i, map) {
seq_printf(s, "device %s\nstate %s\ntype %s (%d)\n",
map->dev_name, map->name, map_type(map->type),
@@ -1290,8 +1382,7 @@
seq_printf(s, "\n");
}
-
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrl_maps_mutex);
return 0;
}
@@ -1304,7 +1395,7 @@
seq_puts(s, "Requested pin control handlers their pinmux maps:\n");
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pinctrl_list_mutex);
list_for_each_entry(p, &pinctrl_list, node) {
seq_printf(s, "device: %s current state: %s\n",
@@ -1336,7 +1427,7 @@
}
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrl_list_mutex);
return 0;
}
@@ -1522,6 +1613,7 @@
INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
INIT_LIST_HEAD(&pctldev->gpio_ranges);
pctldev->dev = dev;
+ mutex_init(&pctldev->mutex);
/* check core ops for sanity */
if (pinctrl_check_ops(pctldev)) {
@@ -1551,38 +1643,37 @@
goto out_err;
}
- mutex_lock(&pinctrl_mutex);
-
+ mutex_lock(&pinctrldev_list_mutex);
list_add_tail(&pctldev->node, &pinctrldev_list);
+ mutex_unlock(&pinctrldev_list_mutex);
- pctldev->p = pinctrl_get_locked(pctldev->dev);
+ pctldev->p = pinctrl_get(pctldev->dev);
+
if (!IS_ERR(pctldev->p)) {
pctldev->hog_default =
- pinctrl_lookup_state_locked(pctldev->p,
- PINCTRL_STATE_DEFAULT);
+ pinctrl_lookup_state(pctldev->p, PINCTRL_STATE_DEFAULT);
if (IS_ERR(pctldev->hog_default)) {
dev_dbg(dev, "failed to lookup the default state\n");
} else {
- if (pinctrl_select_state_locked(pctldev->p,
+ if (pinctrl_select_state(pctldev->p,
pctldev->hog_default))
dev_err(dev,
"failed to select default state\n");
}
pctldev->hog_sleep =
- pinctrl_lookup_state_locked(pctldev->p,
+ pinctrl_lookup_state(pctldev->p,
PINCTRL_STATE_SLEEP);
if (IS_ERR(pctldev->hog_sleep))
dev_dbg(dev, "failed to lookup the sleep state\n");
}
- mutex_unlock(&pinctrl_mutex);
-
pinctrl_init_device_debugfs(pctldev);
return pctldev;
out_err:
+ mutex_destroy(&pctldev->mutex);
kfree(pctldev);
return NULL;
}
@@ -1600,12 +1691,13 @@
if (pctldev == NULL)
return;
+ mutex_lock(&pinctrldev_list_mutex);
+ mutex_lock(&pctldev->mutex);
+
pinctrl_remove_device_debugfs(pctldev);
- mutex_lock(&pinctrl_mutex);
-
if (!IS_ERR(pctldev->p))
- pinctrl_put_locked(pctldev->p, true);
+ pinctrl_put(pctldev->p);
/* TODO: check that no pinmuxes are still active? */
list_del(&pctldev->node);
@@ -1616,9 +1708,10 @@
list_for_each_entry_safe(range, n, &pctldev->gpio_ranges, node)
list_del(&range->node);
+ mutex_unlock(&pctldev->mutex);
+ mutex_destroy(&pctldev->mutex);
kfree(pctldev);
-
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pinctrldev_list_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_unregister);
diff --git a/drivers/pinctrl/core.h b/drivers/pinctrl/core.h
index ee72f1f..75476b3 100644
--- a/drivers/pinctrl/core.h
+++ b/drivers/pinctrl/core.h
@@ -33,6 +33,7 @@
* @p: result of pinctrl_get() for this device
* @hog_default: default state for pins hogged by this device
* @hog_sleep: sleep state for pins hogged by this device
+ * @mutex: mutex taken on each pin controller specific action
* @device_root: debugfs root for this device
*/
struct pinctrl_dev {
@@ -46,6 +47,7 @@
struct pinctrl *p;
struct pinctrl_state *hog_default;
struct pinctrl_state *hog_sleep;
+ struct mutex mutex;
#ifdef CONFIG_DEBUG_FS
struct dentry *device_root;
#endif
@@ -72,7 +74,7 @@
/**
* struct pinctrl_state - a pinctrl state for a device
- * @node: list not for struct pinctrl's @states field
+ * @node: list node for struct pinctrl's @states field
* @name: the name of this state
* @settings: a list of settings for this state
*/
@@ -168,6 +170,7 @@
};
struct pinctrl_dev *get_pinctrl_dev_from_devname(const char *dev_name);
+struct pinctrl_dev *get_pinctrl_dev_from_of_node(struct device_node *np);
int pin_get_from_name(struct pinctrl_dev *pctldev, const char *name);
const char *pin_get_name(struct pinctrl_dev *pctldev, const unsigned pin);
int pinctrl_get_group_selector(struct pinctrl_dev *pctldev,
@@ -186,8 +189,7 @@
extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
extern int pinctrl_force_default(struct pinctrl_dev *pctldev);
-extern struct mutex pinctrl_mutex;
-extern struct list_head pinctrldev_list;
+extern struct mutex pinctrl_maps_mutex;
extern struct list_head pinctrl_maps;
#define for_each_maps(_maps_node_, _i_, _map_) \
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fd40a11..340fb4e 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -41,7 +41,7 @@
struct pinctrl_map *map, unsigned num_maps)
{
if (pctldev) {
- struct pinctrl_ops *ops = pctldev->desc->pctlops;
+ const struct pinctrl_ops *ops = pctldev->desc->pctlops;
ops->dt_free_map(pctldev, map, num_maps);
} else {
/* There is no pctldev for PIN_MAP_TYPE_DUMMY_STATE */
@@ -95,22 +95,11 @@
return pinctrl_register_map(map, num_maps, false, true);
}
-static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
-{
- struct pinctrl_dev *pctldev;
-
- list_for_each_entry(pctldev, &pinctrldev_list, node)
- if (pctldev->dev->of_node == np)
- return pctldev;
-
- return NULL;
-}
-
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
{
struct pinctrl_dev *pctldev;
- pctldev = find_pinctrl_by_of_node(np);
+ pctldev = get_pinctrl_dev_from_of_node(np);
if (!pctldev)
return NULL;
@@ -122,7 +111,7 @@
{
struct device_node *np_pctldev;
struct pinctrl_dev *pctldev;
- struct pinctrl_ops *ops;
+ const struct pinctrl_ops *ops;
int ret;
struct pinctrl_map *map;
unsigned num_maps;
@@ -138,7 +127,7 @@
/* OK let's just assume this will appear later then */
return -EPROBE_DEFER;
}
- pctldev = find_pinctrl_by_of_node(np_pctldev);
+ pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
if (pctldev)
break;
/* Do not defer probing of hogs (circular loop) */
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 2d2f0a4..bb7ddb1 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -263,7 +263,7 @@
return;
}
-static struct pinconf_ops mvebu_pinconf_ops = {
+static const struct pinconf_ops mvebu_pinconf_ops = {
.pin_config_group_get = mvebu_pinconf_group_get,
.pin_config_group_set = mvebu_pinconf_group_set,
.pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show,
@@ -369,7 +369,7 @@
return -ENOTSUPP;
}
-static struct pinmux_ops mvebu_pinmux_ops = {
+static const struct pinmux_ops mvebu_pinmux_ops = {
.get_functions_count = mvebu_pinmux_get_funcs_count,
.get_function_name = mvebu_pinmux_get_func_name,
.get_function_groups = mvebu_pinmux_get_groups,
@@ -470,7 +470,7 @@
kfree(map);
}
-static struct pinctrl_ops mvebu_pinctrl_ops = {
+static const struct pinctrl_ops mvebu_pinctrl_ops = {
.get_groups_count = mvebu_pinctrl_get_groups_count,
.get_group_name = mvebu_pinctrl_get_group_name,
.get_group_pins = mvebu_pinctrl_get_group_pins,
@@ -478,8 +478,12 @@
.dt_free_map = mvebu_pinctrl_dt_free_map,
};
-static int _add_function(struct mvebu_pinctrl_function *funcs, const char *name)
+static int _add_function(struct mvebu_pinctrl_function *funcs, int *funcsize,
+ const char *name)
{
+ if (*funcsize <= 0)
+ return -EOVERFLOW;
+
while (funcs->num_groups) {
/* function already there */
if (strcmp(funcs->name, name) == 0) {
@@ -488,8 +492,12 @@
}
funcs++;
}
+
+ /* append new unique function */
funcs->name = name;
funcs->num_groups = 1;
+ (*funcsize)--;
+
return 0;
}
@@ -497,12 +505,12 @@
struct mvebu_pinctrl *pctl)
{
struct mvebu_pinctrl_function *funcs;
- int num = 0;
+ int num = 0, funcsize = pctl->desc.npins;
int n, s;
/* we allocate functions for number of pins and hope
- * there are less unique functions than pins available */
- funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins *
+ * there are fewer unique functions than pins available */
+ funcs = devm_kzalloc(&pdev->dev, funcsize *
sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
if (!funcs)
return -ENOMEM;
@@ -510,26 +518,27 @@
for (n = 0; n < pctl->num_groups; n++) {
struct mvebu_pinctrl_group *grp = &pctl->groups[n];
for (s = 0; s < grp->num_settings; s++) {
+ int ret;
+
/* skip unsupported settings on this variant */
if (pctl->variant &&
!(pctl->variant & grp->settings[s].variant))
continue;
/* check for unique functions and count groups */
- if (_add_function(funcs, grp->settings[s].name))
+ ret = _add_function(funcs, &funcsize,
+ grp->settings[s].name);
+ if (ret == -EOVERFLOW)
+ dev_err(&pdev->dev,
+ "More functions than pins(%d)\n",
+ pctl->desc.npins);
+ if (ret < 0)
continue;
num++;
}
}
- /* with the number of unique functions and it's groups known,
- reallocate functions and assign group names */
- funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function),
- GFP_KERNEL);
- if (!funcs)
- return -ENOMEM;
-
pctl->num_functions = num;
pctl->functions = funcs;
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 06c304a..2ad5a8d 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) "generic pinconfig core: " fmt
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
@@ -33,7 +34,7 @@
#define PCONFDUMP(a, b, c) { .param = a, .display = b, .format = c }
-struct pin_config_item conf_items[] = {
+static struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_BIAS_DISABLE, "input bias disabled", NULL),
PCONFDUMP(PIN_CONFIG_BIAS_HIGH_IMPEDANCE, "input bias high impedance", NULL),
PCONFDUMP(PIN_CONFIG_BIAS_PULL_UP, "input bias pull up", NULL),
@@ -59,7 +60,7 @@
if (!ops->is_generic)
return;
- for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
+ for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
unsigned long config;
int ret;
@@ -94,7 +95,7 @@
if (!ops->is_generic)
return;
- for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
+ for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
unsigned long config;
int ret;
@@ -120,4 +121,17 @@
}
}
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned long config)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(conf_items); i++) {
+ if (pinconf_to_config_param(config) != conf_items[i].param)
+ continue;
+ seq_printf(s, "%s: 0x%x", conf_items[i].display,
+ pinconf_to_config_argument(config));
+ }
+}
+EXPORT_SYMBOL_GPL(pinconf_generic_dump_config);
#endif
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c
index d611ecf..c67c37e 100644
--- a/drivers/pinctrl/pinconf.c
+++ b/drivers/pinctrl/pinconf.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/uaccess.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinconf.h>
@@ -88,14 +89,14 @@
struct pinctrl_dev *pctldev;
int pin;
- mutex_lock(&pinctrl_mutex);
-
pctldev = get_pinctrl_dev_from_devname(dev_name);
if (!pctldev) {
pin = -EINVAL;
- goto unlock;
+ return pin;
}
+ mutex_lock(&pctldev->mutex);
+
pin = pin_get_from_name(pctldev, name);
if (pin < 0)
goto unlock;
@@ -103,7 +104,7 @@
pin = pin_config_get_for_pin(pctldev, pin, config);
unlock:
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return pin;
}
EXPORT_SYMBOL(pin_config_get);
@@ -144,14 +145,14 @@
struct pinctrl_dev *pctldev;
int pin, ret;
- mutex_lock(&pinctrl_mutex);
-
pctldev = get_pinctrl_dev_from_devname(dev_name);
if (!pctldev) {
ret = -EINVAL;
- goto unlock;
+ return ret;
}
+ mutex_lock(&pctldev->mutex);
+
pin = pin_get_from_name(pctldev, name);
if (pin < 0) {
ret = pin;
@@ -161,7 +162,7 @@
ret = pin_config_set_for_pin(pctldev, pin, config);
unlock:
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return ret;
}
EXPORT_SYMBOL(pin_config_set);
@@ -173,13 +174,14 @@
const struct pinconf_ops *ops;
int selector, ret;
- mutex_lock(&pinctrl_mutex);
-
pctldev = get_pinctrl_dev_from_devname(dev_name);
if (!pctldev) {
ret = -EINVAL;
- goto unlock;
+ return ret;
}
+
+ mutex_lock(&pctldev->mutex);
+
ops = pctldev->desc->confops;
if (!ops || !ops->pin_config_group_get) {
@@ -199,7 +201,7 @@
ret = ops->pin_config_group_get(pctldev, selector, config);
unlock:
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return ret;
}
EXPORT_SYMBOL(pin_config_group_get);
@@ -216,13 +218,14 @@
int ret;
int i;
- mutex_lock(&pinctrl_mutex);
-
pctldev = get_pinctrl_dev_from_devname(dev_name);
if (!pctldev) {
ret = -EINVAL;
- goto unlock;
+ return ret;
}
+
+ mutex_lock(&pctldev->mutex);
+
ops = pctldev->desc->confops;
pctlops = pctldev->desc->pctlops;
@@ -278,7 +281,7 @@
ret = 0;
unlock:
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return ret;
}
@@ -486,7 +489,7 @@
seq_puts(s, "Pin config settings per pin\n");
seq_puts(s, "Format: pin (name): configs\n");
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
@@ -506,7 +509,7 @@
seq_printf(s, "\n");
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
@@ -574,122 +577,58 @@
.release = single_release,
};
-/* 32bit read/write ressources */
-#define MAX_NAME_LEN 16
-char dbg_pinname[MAX_NAME_LEN]; /* shared: name of the state of the pin*/
-char dbg_state_name[MAX_NAME_LEN]; /* shared: state of the pin*/
-static u32 dbg_config; /* shared: config to be read/set for the pin & state*/
+#define MAX_NAME_LEN 15
-static int pinconf_dbg_pinname_print(struct seq_file *s, void *d)
-{
- if (strlen(dbg_pinname))
- seq_printf(s, "%s\n", dbg_pinname);
- else
- seq_printf(s, "No pin name set\n");
- return 0;
-}
-
-static int pinconf_dbg_pinname_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pinconf_dbg_pinname_print, inode->i_private);
-}
-
-static int pinconf_dbg_pinname_write(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- int err;
-
- if (count > MAX_NAME_LEN)
- return -EINVAL;
-
- err = sscanf(user_buf, "%15s", dbg_pinname);
-
- if (err != 1)
- return -EINVAL;
-
- return count;
-}
-
-static const struct file_operations pinconf_dbg_pinname_fops = {
- .open = pinconf_dbg_pinname_open,
- .write = pinconf_dbg_pinname_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
+struct dbg_cfg {
+ enum pinctrl_map_type map_type;
+ char dev_name[MAX_NAME_LEN+1];
+ char state_name[MAX_NAME_LEN+1];
+ char pin_name[MAX_NAME_LEN+1];
};
-static int pinconf_dbg_state_print(struct seq_file *s, void *d)
-{
- if (strlen(dbg_state_name))
- seq_printf(s, "%s\n", dbg_state_name);
- else
- seq_printf(s, "No pin state set\n");
- return 0;
-}
-
-static int pinconf_dbg_state_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pinconf_dbg_state_print, inode->i_private);
-}
-
-static int pinconf_dbg_state_write(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- int err;
-
- if (count > MAX_NAME_LEN)
- return -EINVAL;
-
- err = sscanf(user_buf, "%15s", dbg_state_name);
-
- if (err != 1)
- return -EINVAL;
-
- return count;
-}
-
-static const struct file_operations pinconf_dbg_pinstate_fops = {
- .open = pinconf_dbg_state_open,
- .write = pinconf_dbg_state_write,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
+/*
+ * Goal is to keep this structure as global in order to simply read the
+ * pinconf-config file after a write to check config is as expected
+ */
+static struct dbg_cfg pinconf_dbg_conf;
/**
* pinconf_dbg_config_print() - display the pinctrl config from the pinctrl
- * map, of a pin/state pair based on pinname and state that have been
- * selected with the debugfs entries pinconf-name and pinconf-state
- * @s: contains the 32bits config to be written
+ * map, of the dev/pin/state that was last written to pinconf-config file.
+ * @s: string filled in with config description
* @d: not used
*/
static int pinconf_dbg_config_print(struct seq_file *s, void *d)
{
struct pinctrl_maps *maps_node;
- struct pinctrl_map const *map;
+ const struct pinctrl_map *map;
struct pinctrl_dev *pctldev = NULL;
- struct pinconf_ops *confops = NULL;
+ const struct pinconf_ops *confops = NULL;
+ const struct pinctrl_map_configs *configs;
+ struct dbg_cfg *dbg = &pinconf_dbg_conf;
int i, j;
bool found = false;
+ unsigned long config;
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
/* Parse the pinctrl map and look for the elected pin/state */
for_each_maps(maps_node, i, map) {
- if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
+ if (map->type != dbg->map_type)
continue;
-
- if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
+ if (strcmp(map->dev_name, dbg->dev_name))
+ continue;
+ if (strcmp(map->name, dbg->state_name))
continue;
for (j = 0; j < map->data.configs.num_configs; j++) {
- if (0 == strncmp(map->data.configs.group_or_pin,
- dbg_pinname, MAX_NAME_LEN)) {
- /* We found the right pin / state, read the
- * config and store the pctldev */
- dbg_config = map->data.configs.configs[j];
+ if (!strcmp(map->data.configs.group_or_pin,
+ dbg->pin_name)) {
+ /*
+ * We found the right pin / state, read the
+ * config and he pctldev for later use
+ */
+ configs = &map->data.configs;
pctldev = get_pinctrl_dev_from_devname
(map->ctrl_dev_name);
found = true;
@@ -698,74 +637,166 @@
}
}
- mutex_unlock(&pinctrl_mutex);
-
- if (found) {
- seq_printf(s, "Config of %s in state %s: 0x%08X\n", dbg_pinname,
- dbg_state_name, dbg_config);
-
- if (pctldev)
- confops = pctldev->desc->confops;
-
- if (confops && confops->pin_config_config_dbg_show)
- confops->pin_config_config_dbg_show(pctldev,
- s, dbg_config);
- } else {
- seq_printf(s, "No pin found for defined name/state\n");
+ if (!found) {
+ seq_printf(s, "No config found for dev/state/pin, expected:\n");
+ seq_printf(s, "Searched dev:%s\n", dbg->dev_name);
+ seq_printf(s, "Searched state:%s\n", dbg->state_name);
+ seq_printf(s, "Searched pin:%s\n", dbg->pin_name);
+ seq_printf(s, "Use: modify config_pin <devname> "\
+ "<state> <pinname> <value>\n");
+ goto exit;
}
+ config = *(configs->configs);
+ seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n",
+ dbg->dev_name, dbg->pin_name,
+ dbg->state_name, config);
+
+ if (pctldev)
+ confops = pctldev->desc->confops;
+
+ if (confops && confops->pin_config_config_dbg_show)
+ confops->pin_config_config_dbg_show(pctldev, s, config);
+
+exit:
+ mutex_unlock(&pctldev->mutex);
+
return 0;
}
+/**
+ * pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl
+ * map, of a dev/pin/state entry based on user entries to pinconf-config
+ * @user_buf: contains the modification request with expected format:
+ * modify config_pin <devicename> <state> <pinname> <newvalue>
+ * modify is literal string, alternatives like add/delete not supported yet
+ * config_pin is literal, alternatives like config_mux not supported yet
+ * <devicename> <state> <pinname> are values that should match the pinctrl-maps
+ * <newvalue> reflects the new config and is driver dependant
+ */
+static int pinconf_dbg_config_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct pinctrl_maps *maps_node;
+ const struct pinctrl_map *map;
+ struct pinctrl_dev *pctldev = NULL;
+ const struct pinconf_ops *confops = NULL;
+ struct dbg_cfg *dbg = &pinconf_dbg_conf;
+ const struct pinctrl_map_configs *configs;
+ char config[MAX_NAME_LEN+1];
+ bool found = false;
+ char buf[128];
+ char *b = &buf[0];
+ int buf_size;
+ char *token;
+ int i;
+
+ /* Get userspace string and assure termination */
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ buf[buf_size] = 0;
+
+ /*
+ * need to parse entry and extract parameters:
+ * modify configs_pin devicename state pinname newvalue
+ */
+
+ /* Get arg: 'modify' */
+ token = strsep(&b, " ");
+ if (!token)
+ return -EINVAL;
+ if (strcmp(token, "modify"))
+ return -EINVAL;
+
+ /* Get arg type: "config_pin" type supported so far */
+ token = strsep(&b, " ");
+ if (!token)
+ return -EINVAL;
+ if (strcmp(token, "config_pin"))
+ return -EINVAL;
+ dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
+
+ /* get arg 'device_name' */
+ token = strsep(&b, " ");
+ if (token == NULL)
+ return -EINVAL;
+ if (strlen(token) >= MAX_NAME_LEN)
+ return -EINVAL;
+ strncpy(dbg->dev_name, token, MAX_NAME_LEN);
+
+ /* get arg 'state_name' */
+ token = strsep(&b, " ");
+ if (token == NULL)
+ return -EINVAL;
+ if (strlen(token) >= MAX_NAME_LEN)
+ return -EINVAL;
+ strncpy(dbg->state_name, token, MAX_NAME_LEN);
+
+ /* get arg 'pin_name' */
+ token = strsep(&b, " ");
+ if (token == NULL)
+ return -EINVAL;
+ if (strlen(token) >= MAX_NAME_LEN)
+ return -EINVAL;
+ strncpy(dbg->pin_name, token, MAX_NAME_LEN);
+
+ /* get new_value of config' */
+ token = strsep(&b, " ");
+ if (token == NULL)
+ return -EINVAL;
+ if (strlen(token) >= MAX_NAME_LEN)
+ return -EINVAL;
+ strncpy(config, token, MAX_NAME_LEN);
+
+ mutex_lock(&pinctrl_maps_mutex);
+
+ /* Parse the pinctrl map and look for the selected dev/state/pin */
+ for_each_maps(maps_node, i, map) {
+ if (strcmp(map->dev_name, dbg->dev_name))
+ continue;
+ if (map->type != dbg->map_type)
+ continue;
+ if (strcmp(map->name, dbg->state_name))
+ continue;
+
+ /* we found the right pin / state, so overwrite config */
+ if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
+ found = true;
+ pctldev = get_pinctrl_dev_from_devname(
+ map->ctrl_dev_name);
+ configs = &map->data.configs;
+ break;
+ }
+ }
+
+ if (!found) {
+ count = -EINVAL;
+ goto exit;
+ }
+
+ if (pctldev)
+ confops = pctldev->desc->confops;
+
+ if (confops && confops->pin_config_dbg_parse_modify) {
+ for (i = 0; i < configs->num_configs; i++) {
+ confops->pin_config_dbg_parse_modify(pctldev,
+ config,
+ &configs->configs[i]);
+ }
+ }
+
+exit:
+ mutex_unlock(&pinctrl_maps_mutex);
+
+ return count;
+}
+
static int pinconf_dbg_config_open(struct inode *inode, struct file *file)
{
return single_open(file, pinconf_dbg_config_print, inode->i_private);
}
-/**
- * pinconf_dbg_config_write() - overwrite the pinctrl config in thepinctrl
- * map, of a pin/state pair based on pinname and state that have been
- * selected with the debugfs entries pinconf-name and pinconf-state
- */
-static int pinconf_dbg_config_write(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- int err;
- unsigned long config;
- struct pinctrl_maps *maps_node;
- struct pinctrl_map const *map;
- int i, j;
-
- err = kstrtoul_from_user(user_buf, count, 0, &config);
-
- if (err)
- return err;
-
- dbg_config = config;
-
- mutex_lock(&pinctrl_mutex);
-
- /* Parse the pinctrl map and look for the selected pin/state */
- for_each_maps(maps_node, i, map) {
- if (map->type != PIN_MAP_TYPE_CONFIGS_PIN)
- continue;
-
- if (strncmp(map->name, dbg_state_name, MAX_NAME_LEN) > 0)
- continue;
-
- /* we found the right pin / state, so overwrite config */
- for (j = 0; j < map->data.configs.num_configs; j++) {
- if (strncmp(map->data.configs.group_or_pin, dbg_pinname,
- MAX_NAME_LEN) == 0)
- map->data.configs.configs[j] = dbg_config;
- }
- }
-
- mutex_unlock(&pinctrl_mutex);
-
- return count;
-}
-
static const struct file_operations pinconf_dbg_pinconfig_fops = {
.open = pinconf_dbg_config_open,
.write = pinconf_dbg_config_write,
@@ -782,10 +813,6 @@
devroot, pctldev, &pinconf_pins_ops);
debugfs_create_file("pinconf-groups", S_IFREG | S_IRUGO,
devroot, pctldev, &pinconf_groups_ops);
- debugfs_create_file("pinconf-name", (S_IRUGO | S_IWUSR | S_IWGRP),
- devroot, pctldev, &pinconf_dbg_pinname_fops);
- debugfs_create_file("pinconf-state", (S_IRUGO | S_IWUSR | S_IWGRP),
- devroot, pctldev, &pinconf_dbg_pinstate_fops);
debugfs_create_file("pinconf-config", (S_IRUGO | S_IWUSR | S_IWGRP),
devroot, pctldev, &pinconf_dbg_pinconfig_fops);
}
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index bfda73d..92c7267 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -98,6 +98,8 @@
void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname);
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned long config);
#else
static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
@@ -114,4 +116,10 @@
return;
}
+static inline void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config)
+{
+ return;
+}
#endif
diff --git a/drivers/pinctrl/pinctrl-ab8500.c b/drivers/pinctrl/pinctrl-ab8500.c
index 3b471d8..2ac2d0a 100644
--- a/drivers/pinctrl/pinctrl-ab8500.c
+++ b/drivers/pinctrl/pinctrl-ab8500.c
@@ -389,7 +389,8 @@
* alt_A | 1 | 0 | 0
*/
-struct alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
+static struct
+alternate_functions ab8500_alternate_functions[AB8500_GPIO_MAX_NUMBER + 1] = {
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
@@ -455,7 +456,7 @@
* GPIO24 and GPIO25
* GPIO36 to GPIO41
*/
-struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
+static struct abx500_gpio_irq_cluster ab8500_gpio_irq_cluster[] = {
GPIO_IRQ_CLUSTER(6, 13, AB8500_INT_GPIO6R),
GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
GPIO_IRQ_CLUSTER(36, 41, AB8500_INT_GPIO36R),
diff --git a/drivers/pinctrl/pinctrl-ab8505.c b/drivers/pinctrl/pinctrl-ab8505.c
index 3a4238e..bf0ef4a 100644
--- a/drivers/pinctrl/pinctrl-ab8505.c
+++ b/drivers/pinctrl/pinctrl-ab8505.c
@@ -271,7 +271,8 @@
* alt_A | 1 | 0 | 0
*/
-struct alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
+static struct
+alternate_functions ab8505_alternate_functions[AB8505_GPIO_MAX_NUMBER + 1] = {
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
ALTERNATE_FUNCTIONS(2, 1, UNUSED, UNUSED, 0, 0, 0), /* GPIO2, altA controlled by bit 1 */
@@ -284,7 +285,7 @@
ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9, bit 0 reserved */
ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
- ALTERNATE_FUNCTIONS(11, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
+ ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 2 */
ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12, bit3 reseved */
ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
@@ -348,7 +349,7 @@
* GPIO50
* GPIO52 to GPIO53
*/
-struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
+static struct abx500_gpio_irq_cluster ab8505_gpio_irq_cluster[] = {
GPIO_IRQ_CLUSTER(10, 11, AB8500_INT_GPIO10R),
GPIO_IRQ_CLUSTER(13, 13, AB8500_INT_GPIO13R),
GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
diff --git a/drivers/pinctrl/pinctrl-ab8540.c b/drivers/pinctrl/pinctrl-ab8540.c
index 8ee1e8d..9867535 100644
--- a/drivers/pinctrl/pinctrl-ab8540.c
+++ b/drivers/pinctrl/pinctrl-ab8540.c
@@ -299,7 +299,8 @@
*
*/
-struct alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
+static struct
+alternate_functions ab8540_alternate_functions[AB8540_GPIO_MAX_NUMBER + 1] = {
/* GPIOSEL1 - bit 4-7 reserved */
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
@@ -376,7 +377,7 @@
* GPIO43 to GPIO44
* GPIO51 to GPIO54
*/
-struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
+static struct abx500_gpio_irq_cluster ab8540_gpio_irq_cluster[] = {
GPIO_IRQ_CLUSTER(43, 43, AB8540_INT_GPIO43F),
GPIO_IRQ_CLUSTER(44, 44, AB8540_INT_GPIO44F),
GPIO_IRQ_CLUSTER(51, 54, AB9540_INT_GPIO51R),
diff --git a/drivers/pinctrl/pinctrl-ab9540.c b/drivers/pinctrl/pinctrl-ab9540.c
index 7610bd0..1a281ca 100644
--- a/drivers/pinctrl/pinctrl-ab9540.c
+++ b/drivers/pinctrl/pinctrl-ab9540.c
@@ -379,7 +379,8 @@
* alt_A | 1 | 0 | 0
*/
-struct alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
+static struct
+alternate_functions ab9540alternate_functions[AB9540_GPIO_MAX_NUMBER + 1] = {
/* GPIOSEL1 - bits 4-7 are reserved */
ALTERNATE_FUNCTIONS(0, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO0 */
ALTERNATE_FUNCTIONS(1, 0, UNUSED, UNUSED, 0, 0, 0), /* GPIO1, altA controlled by bit 0 */
@@ -393,7 +394,7 @@
/* GPIOSEL2 - bits 0 and 3 are reserved */
ALTERNATE_FUNCTIONS(9, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO9 */
ALTERNATE_FUNCTIONS(10, 1, 0, UNUSED, 1, 0, 0), /* GPIO10, altA and altB controlled by bit 0 */
- ALTERNATE_FUNCTIONS(11, 2, UNUSED, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
+ ALTERNATE_FUNCTIONS(11, 2, 1, UNUSED, 0, 0, 0), /* GPIO11, altA controlled by bit 1 */
ALTERNATE_FUNCTIONS(12, UNUSED, UNUSED, UNUSED, 0, 0, 0), /* no GPIO12 */
ALTERNATE_FUNCTIONS(13, 4, 3, 4, 1, 0, 2), /* GPIO13, altA altB and altC controlled by bit 3 and 4 */
ALTERNATE_FUNCTIONS(14, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO14, altA controlled by bit 5 */
@@ -454,7 +455,7 @@
ALTERNATE_FUNCTIONS(54, 5, UNUSED, UNUSED, 0, 0, 0), /* GPIO54 = GPIO60, altA controlled by bit 5 */
};
-struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
+static struct abx500_gpio_irq_cluster ab9540_gpio_irq_cluster[] = {
GPIO_IRQ_CLUSTER(10, 13, AB8500_INT_GPIO10R),
GPIO_IRQ_CLUSTER(24, 25, AB8500_INT_GPIO24R),
GPIO_IRQ_CLUSTER(40, 41, AB8500_INT_GPIO40R),
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c
index c542a97..aa17f75 100644
--- a/drivers/pinctrl/pinctrl-abx500.c
+++ b/drivers/pinctrl/pinctrl-abx500.c
@@ -517,14 +517,14 @@
#define abx500_gpio_dbg_show NULL
#endif
-int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
+static int abx500_gpio_request(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
return pinctrl_request_gpio(gpio);
}
-void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
+static void abx500_gpio_free(struct gpio_chip *chip, unsigned offset)
{
int gpio = chip->base + offset;
@@ -611,7 +611,7 @@
dev_dbg(pct->dev, "disable group %s, %u pins\n", g->name, g->npins);
}
-int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
+static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
@@ -656,7 +656,7 @@
{
}
-static struct pinmux_ops abx500_pinmux_ops = {
+static const struct pinmux_ops abx500_pinmux_ops = {
.get_functions_count = abx500_pmx_get_funcs_cnt,
.get_function_name = abx500_pmx_get_func_name,
.get_function_groups = abx500_pmx_get_func_groups,
@@ -704,21 +704,21 @@
chip->base + offset - 1);
}
-static struct pinctrl_ops abx500_pinctrl_ops = {
+static const struct pinctrl_ops abx500_pinctrl_ops = {
.get_groups_count = abx500_get_groups_cnt,
.get_group_name = abx500_get_group_name,
.get_group_pins = abx500_get_group_pins,
.pin_dbg_show = abx500_pin_dbg_show,
};
-int abx500_pin_config_get(struct pinctrl_dev *pctldev,
+static int abx500_pin_config_get(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *config)
{
return -ENOSYS;
}
-int abx500_pin_config_set(struct pinctrl_dev *pctldev,
+static int abx500_pin_config_set(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long config)
{
@@ -778,7 +778,7 @@
return ret;
}
-static struct pinconf_ops abx500_pinconf_ops = {
+static const struct pinconf_ops abx500_pinconf_ops = {
.pin_config_get = abx500_pin_config_get,
.pin_config_set = abx500_pin_config_set,
};
@@ -834,6 +834,7 @@
{ .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, },
{ .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, },
{ .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, },
+ { }
};
static int abx500_gpio_probe(struct platform_device *pdev)
@@ -879,7 +880,6 @@
pct->parent = dev_get_drvdata(pdev->dev.parent);
pct->chip = abx500gpio_chip;
pct->chip.dev = &pdev->dev;
- pct->chip.base = pdata->gpio_base;
pct->chip.base = (np) ? -1 : pdata->gpio_base;
/* initialize the lock */
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index efb7f10..4d7f531 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -294,7 +294,7 @@
{
}
-static struct pinctrl_ops at91_pctrl_ops = {
+static const struct pinctrl_ops at91_pctrl_ops = {
.get_groups_count = at91_get_groups_count,
.get_group_name = at91_get_group_name,
.get_group_pins = at91_get_group_pins,
@@ -303,7 +303,7 @@
.dt_free_map = at91_dt_free_map,
};
-static void __iomem * pin_to_controller(struct at91_pinctrl *info,
+static void __iomem *pin_to_controller(struct at91_pinctrl *info,
unsigned int bank)
{
return gpio_chips[bank]->regbase;
@@ -501,7 +501,7 @@
}
}
-static int pin_check_config(struct at91_pinctrl *info, const char* name,
+static int pin_check_config(struct at91_pinctrl *info, const char *name,
int index, const struct at91_pmx_pin *pin)
{
int mux;
@@ -579,7 +579,7 @@
pio = pin_to_controller(info, pin->bank);
mask = pin_to_mask(pin->pin);
at91_mux_disable_interrupt(pio, mask);
- switch(pin->mux) {
+ switch (pin->mux) {
case AT91_MUX_GPIO:
at91_mux_gpio_enable(pio, mask, 1);
break;
@@ -696,7 +696,7 @@
/* Set the pin to some default state, GPIO is usually default */
}
-static struct pinmux_ops at91_pmx_ops = {
+static const struct pinmux_ops at91_pmx_ops = {
.get_functions_count = at91_pmx_get_funcs_count,
.get_function_name = at91_pmx_get_func_name,
.get_function_groups = at91_pmx_get_groups,
@@ -776,7 +776,7 @@
{
}
-static struct pinconf_ops at91_pinconf_ops = {
+static const struct pinconf_ops at91_pinconf_ops = {
.pin_config_get = at91_pinconf_get,
.pin_config_set = at91_pinconf_set,
.pin_config_dbg_show = at91_pinconf_dbg_show,
@@ -812,7 +812,7 @@
{
int ret = 0;
int size;
- const const __be32 *list;
+ const __be32 *list;
list = of_get_property(np, "atmel,mux-mask", &size);
if (!list) {
@@ -846,7 +846,7 @@
{
struct at91_pmx_pin *pin;
int size;
- const const __be32 *list;
+ const __be32 *list;
int i, j;
dev_dbg(info->dev, "group(%d): %s\n", index, np->name);
@@ -944,7 +944,7 @@
return -ENODEV;
info->dev = &pdev->dev;
- info->ops = (struct at91_pinctrl_mux_ops*)
+ info->ops = (struct at91_pinctrl_mux_ops *)
of_match_device(at91_pinctrl_of_match, &pdev->dev)->data;
at91_pinctrl_child_count(info, np);
@@ -1002,7 +1002,7 @@
{
struct at91_pinctrl *info;
struct pinctrl_pin_desc *pdesc;
- int ret, i, j ,k;
+ int ret, i, j, k;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info)
@@ -1568,7 +1568,7 @@
goto err;
}
- at91_chip->ops = (struct at91_pinctrl_mux_ops*)
+ at91_chip->ops = (struct at91_pinctrl_mux_ops *)
of_match_device(at91_gpio_of_match, &pdev->dev)->data;
at91_chip->pioc_virq = irq;
at91_chip->pioc_idx = alias_idx;
@@ -1605,7 +1605,8 @@
chip->ngpio = ngpio;
}
- names = devm_kzalloc(&pdev->dev, sizeof(char*) * chip->ngpio, GFP_KERNEL);
+ names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+ GFP_KERNEL);
if (!names) {
ret = -ENOMEM;
@@ -1615,7 +1616,7 @@
for (i = 0; i < chip->ngpio; i++)
names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);
- chip->names = (const char*const*)names;
+ chip->names = (const char *const *)names;
range = &at91_chip->range;
range->name = chip->label;
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c
index 4eb6d2c..f28d4b0 100644
--- a/drivers/pinctrl/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/pinctrl-bcm2835.c
@@ -795,7 +795,7 @@
return err;
}
-static struct pinctrl_ops bcm2835_pctl_ops = {
+static const struct pinctrl_ops bcm2835_pctl_ops = {
.get_groups_count = bcm2835_pctl_get_groups_count,
.get_group_name = bcm2835_pctl_get_group_name,
.get_group_pins = bcm2835_pctl_get_group_pins,
@@ -872,7 +872,7 @@
return 0;
}
-static struct pinmux_ops bcm2835_pmx_ops = {
+static const struct pinmux_ops bcm2835_pmx_ops = {
.get_functions_count = bcm2835_pmx_get_functions_count,
.get_function_name = bcm2835_pmx_get_function_name,
.get_function_groups = bcm2835_pmx_get_function_groups,
@@ -916,7 +916,7 @@
return 0;
}
-static struct pinconf_ops bcm2835_pinconf_ops = {
+static const struct pinconf_ops bcm2835_pinconf_ops = {
.pin_config_get = bcm2835_pinconf_get,
.pin_config_set = bcm2835_pinconf_set,
};
diff --git a/drivers/pinctrl/pinctrl-coh901.c b/drivers/pinctrl/pinctrl-coh901.c
index 8b7e7bc..edde3ac 100644
--- a/drivers/pinctrl/pinctrl-coh901.c
+++ b/drivers/pinctrl/pinctrl-coh901.c
@@ -318,13 +318,16 @@
struct u300_gpio_port *port = NULL;
struct list_head *p;
int retirq;
+ bool found = false;
list_for_each(p, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node);
- if (port->number == portno)
+ if (port->number == portno) {
+ found = true;
break;
+ }
}
- if (port == NULL) {
+ if (!found) {
dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
offset);
return -EINVAL;
@@ -359,7 +362,7 @@
drmode &= (U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1));
drmode >>= ((offset & 0x07) << 1);
- switch(param) {
+ switch (param) {
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
*config = 0;
if (biasmode)
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 538b9dd..8b10b1a 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -26,6 +26,7 @@
#include <linux/of_irq.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/err.h>
#include <asm/mach/irq.h>
@@ -33,6 +34,17 @@
#include "pinctrl-samsung.h"
#include "pinctrl-exynos.h"
+
+static struct samsung_pin_bank_type bank_type_off = {
+ .fld_width = { 4, 1, 2, 2, 2, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, },
+};
+
+static struct samsung_pin_bank_type bank_type_alive = {
+ .fld_width = { 4, 1, 2, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0x0c, },
+};
+
/* list of external wakeup controllers supported */
static const struct of_device_id exynos_wkup_irq_ids[] = {
{ .compatible = "samsung,exynos4210-wakeup-eint", },
@@ -75,12 +87,14 @@
static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pin_bank_type *bank_type = bank->type;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
struct samsung_pin_ctrl *ctrl = d->ctrl;
unsigned int pin = irqd->hwirq;
unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
unsigned int con, trig_type;
unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
+ unsigned long flags;
unsigned int mask;
switch (type) {
@@ -114,15 +128,19 @@
con |= trig_type << shift;
writel(con, d->virt_base + reg_con);
- reg_con = bank->pctl_offset;
- shift = pin * bank->func_width;
- mask = (1 << bank->func_width) - 1;
+ reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
+ shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
+ mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+ spin_lock_irqsave(&bank->slock, flags);
con = readl(d->virt_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, d->virt_base + reg_con);
+ spin_unlock_irqrestore(&bank->slock, flags);
+
return 0;
}
@@ -253,11 +271,13 @@
static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
{
struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pin_bank_type *bank_type = bank->type;
struct samsung_pinctrl_drv_data *d = bank->drvdata;
unsigned int pin = irqd->hwirq;
unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
unsigned long con, trig_type;
+ unsigned long flags;
unsigned int mask;
switch (type) {
@@ -291,15 +311,19 @@
con |= trig_type << shift;
writel(con, d->virt_base + reg_con);
- reg_con = bank->pctl_offset;
- shift = pin * bank->func_width;
- mask = (1 << bank->func_width) - 1;
+ reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
+ shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
+ mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+ spin_lock_irqsave(&bank->slock, flags);
con = readl(d->virt_base + reg_con);
con &= ~(mask << shift);
con |= EXYNOS_EINT_FUNC << shift;
writel(con, d->virt_base + reg_con);
+ spin_unlock_irqrestore(&bank->slock, flags);
+
return 0;
}
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 0a70889..9b1f77a 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -48,26 +48,18 @@
#define EXYNOS_PIN_BANK_EINTN(pins, reg, id) \
{ \
+ .type = &bank_type_off, \
.pctl_offset = reg, \
.nr_pins = pins, \
- .func_width = 4, \
- .pud_width = 2, \
- .drv_width = 2, \
- .conpdn_width = 2, \
- .pudpdn_width = 2, \
.eint_type = EINT_TYPE_NONE, \
.name = id \
}
#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs) \
{ \
+ .type = &bank_type_off, \
.pctl_offset = reg, \
.nr_pins = pins, \
- .func_width = 4, \
- .pud_width = 2, \
- .drv_width = 2, \
- .conpdn_width = 2, \
- .pudpdn_width = 2, \
.eint_type = EINT_TYPE_GPIO, \
.eint_offset = offs, \
.name = id \
@@ -75,11 +67,9 @@
#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs) \
{ \
+ .type = &bank_type_alive, \
.pctl_offset = reg, \
.nr_pins = pins, \
- .func_width = 4, \
- .pud_width = 2, \
- .drv_width = 2, \
.eint_type = EINT_TYPE_WKUP, \
.eint_offset = offs, \
.name = id \
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
index 1376eb7..6038503 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -20,6 +20,9 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/of_irq.h>
#include "core.h"
/* EXYNOS5440 GPIO and Pinctrl register offsets */
@@ -37,6 +40,7 @@
#define GPIO_DS1 0x2C
#define EXYNOS5440_MAX_PINS 23
+#define EXYNOS5440_MAX_GPIO_INT 8
#define PIN_NAME_LENGTH 10
#define GROUP_SUFFIX "-grp"
@@ -109,6 +113,7 @@
struct exynos5440_pinctrl_priv_data {
void __iomem *reg_base;
struct gpio_chip *gc;
+ struct irq_domain *irq_domain;
const struct exynos5440_pin_group *pin_groups;
unsigned int nr_groups;
@@ -116,6 +121,16 @@
unsigned int nr_functions;
};
+/**
+ * struct exynos5440_gpio_intr_data: private data for gpio interrupts.
+ * @priv: driver's private runtime data.
+ * @gpio_int: gpio interrupt number.
+ */
+struct exynos5440_gpio_intr_data {
+ struct exynos5440_pinctrl_priv_data *priv;
+ unsigned int gpio_int;
+};
+
/* list of all possible config options supported */
static struct pin_config {
char *prop_cfg;
@@ -286,7 +301,7 @@
}
/* list of pinctrl callbacks for the pinctrl core */
-static struct pinctrl_ops exynos5440_pctrl_ops = {
+static const struct pinctrl_ops exynos5440_pctrl_ops = {
.get_groups_count = exynos5440_get_group_count,
.get_group_name = exynos5440_get_group_name,
.get_group_pins = exynos5440_get_group_pins,
@@ -374,7 +389,7 @@
}
/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static struct pinmux_ops exynos5440_pinmux_ops = {
+static const struct pinmux_ops exynos5440_pinmux_ops = {
.get_functions_count = exynos5440_get_functions_count,
.get_function_name = exynos5440_pinmux_get_fname,
.get_function_groups = exynos5440_pinmux_get_groups,
@@ -523,7 +538,7 @@
}
/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static struct pinconf_ops exynos5440_pinconf_ops = {
+static const struct pinconf_ops exynos5440_pinconf_ops = {
.pin_config_get = exynos5440_pinconf_get,
.pin_config_set = exynos5440_pinconf_set,
.pin_config_group_get = exynos5440_pinconf_group_get,
@@ -598,6 +613,22 @@
return 0;
}
+/* gpiolib gpio_to_irq callback function */
+static int exynos5440_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct exynos5440_pinctrl_priv_data *priv = dev_get_drvdata(gc->dev);
+ unsigned int virq;
+
+ if (offset < 16 || offset > 23)
+ return -ENXIO;
+
+ if (!priv->irq_domain)
+ return -ENXIO;
+
+ virq = irq_create_mapping(priv->irq_domain, offset - 16);
+ return virq ? : -ENXIO;
+}
+
/* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
struct device_node *cfg_np, unsigned int **pin_list,
@@ -670,8 +701,10 @@
ret = exynos5440_pinctrl_parse_dt_pins(pdev, cfg_np,
&pin_list, &npins);
- if (ret)
- return ret;
+ if (ret) {
+ gname = NULL;
+ goto skip_to_pin_function;
+ }
/* derive pin group name from the node name */
gname = devm_kzalloc(dev, strlen(cfg_np->name) + GSUFFIX_LEN,
@@ -687,6 +720,7 @@
grp->num_pins = npins;
grp++;
+skip_to_pin_function:
ret = of_property_read_u32(cfg_np, "samsung,exynos5440-pin-function",
&function);
if (ret)
@@ -709,7 +743,7 @@
return -ENOMEM;
}
func->groups[0] = gname;
- func->num_groups = 1;
+ func->num_groups = gname ? 1 : 0;
func->function = function;
func++;
func_idx++;
@@ -818,6 +852,7 @@
gc->get = exynos5440_gpio_get;
gc->direction_input = exynos5440_gpio_direction_input;
gc->direction_output = exynos5440_gpio_direction_output;
+ gc->to_irq = exynos5440_gpio_to_irq;
gc->label = "gpiolib-exynos5440";
gc->owner = THIS_MODULE;
ret = gpiochip_add(gc);
@@ -842,6 +877,110 @@
return 0;
}
+static void exynos5440_gpio_irq_unmask(struct irq_data *irqd)
+{
+ struct exynos5440_pinctrl_priv_data *d;
+ unsigned long gpio_int;
+
+ d = irq_data_get_irq_chip_data(irqd);
+ gpio_int = readl(d->reg_base + GPIO_INT);
+ gpio_int |= 1 << irqd->hwirq;
+ writel(gpio_int, d->reg_base + GPIO_INT);
+}
+
+static void exynos5440_gpio_irq_mask(struct irq_data *irqd)
+{
+ struct exynos5440_pinctrl_priv_data *d;
+ unsigned long gpio_int;
+
+ d = irq_data_get_irq_chip_data(irqd);
+ gpio_int = readl(d->reg_base + GPIO_INT);
+ gpio_int &= ~(1 << irqd->hwirq);
+ writel(gpio_int, d->reg_base + GPIO_INT);
+}
+
+/* irq_chip for gpio interrupts */
+static struct irq_chip exynos5440_gpio_irq_chip = {
+ .name = "exynos5440_gpio_irq_chip",
+ .irq_unmask = exynos5440_gpio_irq_unmask,
+ .irq_mask = exynos5440_gpio_irq_mask,
+};
+
+/* interrupt handler for GPIO interrupts 0..7 */
+static irqreturn_t exynos5440_gpio_irq(int irq, void *data)
+{
+ struct exynos5440_gpio_intr_data *intd = data;
+ struct exynos5440_pinctrl_priv_data *d = intd->priv;
+ int virq;
+
+ virq = irq_linear_revmap(d->irq_domain, intd->gpio_int);
+ if (!virq)
+ return IRQ_NONE;
+ generic_handle_irq(virq);
+ return IRQ_HANDLED;
+}
+
+static int exynos5440_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct exynos5440_pinctrl_priv_data *d = h->host_data;
+
+ irq_set_chip_data(virq, d);
+ irq_set_chip_and_handler(virq, &exynos5440_gpio_irq_chip,
+ handle_level_irq);
+ set_irq_flags(virq, IRQF_VALID);
+ return 0;
+}
+
+/* irq domain callbacks for gpio interrupt controller */
+static const struct irq_domain_ops exynos5440_gpio_irqd_ops = {
+ .map = exynos5440_gpio_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+/* setup handling of gpio interrupts */
+static int exynos5440_gpio_irq_init(struct platform_device *pdev,
+ struct exynos5440_pinctrl_priv_data *priv)
+{
+ struct device *dev = &pdev->dev;
+ struct exynos5440_gpio_intr_data *intd;
+ int i, irq, ret;
+
+ intd = devm_kzalloc(dev, sizeof(*intd) * EXYNOS5440_MAX_GPIO_INT,
+ GFP_KERNEL);
+ if (!intd) {
+ dev_err(dev, "failed to allocate memory for gpio intr data\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < EXYNOS5440_MAX_GPIO_INT; i++) {
+ irq = irq_of_parse_and_map(dev->of_node, i);
+ if (irq <= 0) {
+ dev_err(dev, "irq parsing failed\n");
+ return -EINVAL;
+ }
+
+ intd->gpio_int = i;
+ intd->priv = priv;
+ ret = devm_request_irq(dev, irq, exynos5440_gpio_irq,
+ 0, dev_name(dev), intd++);
+ if (ret) {
+ dev_err(dev, "irq request failed\n");
+ return -ENXIO;
+ }
+ }
+
+ priv->irq_domain = irq_domain_add_linear(dev->of_node,
+ EXYNOS5440_MAX_GPIO_INT,
+ &exynos5440_gpio_irqd_ops, priv);
+ if (!priv->irq_domain) {
+ dev_err(dev, "failed to create irq domain\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
static int exynos5440_pinctrl_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -854,7 +993,7 @@
return -ENODEV;
}
- priv = devm_kzalloc(dev, sizeof(priv), GFP_KERNEL);
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(dev, "could not allocate memory for private data\n");
return -ENOMEM;
@@ -880,6 +1019,12 @@
return ret;
}
+ ret = exynos5440_gpio_irq_init(pdev, priv);
+ if (ret) {
+ dev_err(dev, "failed to setup gpio interrupts\n");
+ return ret;
+ }
+
platform_set_drvdata(pdev, priv);
dev_info(dev, "EXYNOS5440 pinctrl driver registered\n");
return 0;
diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c
index af97a1f..f9b2a1d 100644
--- a/drivers/pinctrl/pinctrl-falcon.c
+++ b/drivers/pinctrl/pinctrl-falcon.c
@@ -353,7 +353,7 @@
{
}
-static struct pinconf_ops falcon_pinconf_ops = {
+static const struct pinconf_ops falcon_pinconf_ops = {
.pin_config_get = falcon_pinconf_get,
.pin_config_set = falcon_pinconf_set,
.pin_config_group_get = falcon_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-imx.c b/drivers/pinctrl/pinctrl-imx.c
index 4cebb9c..0ef1904 100644
--- a/drivers/pinctrl/pinctrl-imx.c
+++ b/drivers/pinctrl/pinctrl-imx.c
@@ -207,7 +207,7 @@
kfree(map);
}
-static struct pinctrl_ops imx_pctrl_ops = {
+static const struct pinctrl_ops imx_pctrl_ops = {
.get_groups_count = imx_get_groups_count,
.get_group_name = imx_get_group_name,
.get_group_pins = imx_get_group_pins,
@@ -299,7 +299,7 @@
return 0;
}
-static struct pinmux_ops imx_pmx_ops = {
+static const struct pinmux_ops imx_pmx_ops = {
.get_functions_count = imx_pmx_get_funcs_count,
.get_function_name = imx_pmx_get_func_name,
.get_function_groups = imx_pmx_get_groups,
@@ -397,7 +397,7 @@
}
}
-static struct pinconf_ops imx_pinconf_ops = {
+static const struct pinconf_ops imx_pinconf_ops = {
.pin_config_get = imx_pinconf_get,
.pin_config_set = imx_pinconf_set,
.pin_config_dbg_show = imx_pinconf_dbg_show,
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index a703846..615c500 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -169,7 +169,7 @@
return 0;
}
-static struct pinctrl_ops ltq_pctrl_ops = {
+static const struct pinctrl_ops ltq_pctrl_ops = {
.get_groups_count = ltq_get_group_count,
.get_group_name = ltq_get_group_name,
.get_group_pins = ltq_get_group_pins,
@@ -311,7 +311,7 @@
return info->apply_mux(pctrldev, mfp, pin_func);
}
-static struct pinmux_ops ltq_pmx_ops = {
+static const struct pinmux_ops ltq_pmx_ops = {
.get_functions_count = ltq_pmx_func_count,
.get_function_name = ltq_pmx_func_name,
.get_function_groups = ltq_pmx_get_groups,
diff --git a/drivers/pinctrl/pinctrl-mmp2.c b/drivers/pinctrl/pinctrl-mmp2.c
deleted file mode 100644
index 4afa56a..0000000
--- a/drivers/pinctrl/pinctrl-mmp2.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * linux/drivers/pinctrl/pinmux-mmp2.c
- *
- * 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
- * publishhed by the Free Software Foundation.
- *
- * Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define MMP2_DS_MASK 0x1800
-#define MMP2_DS_SHIFT 11
-#define MMP2_SLEEP_MASK 0x38
-#define MMP2_SLEEP_SELECT (1 << 9)
-#define MMP2_SLEEP_DATA (1 << 8)
-#define MMP2_SLEEP_DIR (1 << 7)
-
-#define MFPR_MMP2(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \
- { \
- .name = #a, \
- .pin = a, \
- .mfpr = r, \
- .func = { \
- MMP2_MUX_##f0, \
- MMP2_MUX_##f1, \
- MMP2_MUX_##f2, \
- MMP2_MUX_##f3, \
- MMP2_MUX_##f4, \
- MMP2_MUX_##f5, \
- MMP2_MUX_##f6, \
- MMP2_MUX_##f7, \
- }, \
- }
-
-#define GRP_MMP2(a, m, p) \
- { .name = a, .mux = MMP2_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 174 pins */
-enum mmp2_pin_list {
- /* 0~168: GPIO0~GPIO168 */
- TWSI4_SCL = 169,
- TWSI4_SDA, /* 170 */
- G_CLKREQ,
- VCXO_REQ,
- VCXO_OUT,
-};
-
-enum mmp2_mux {
- /* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
- MMP2_MUX_GPIO = 0,
- MMP2_MUX_G_CLKREQ,
- MMP2_MUX_VCXO_REQ,
- MMP2_MUX_VCXO_OUT,
- MMP2_MUX_KP_MK,
- MMP2_MUX_KP_DK,
- MMP2_MUX_CCIC1,
- MMP2_MUX_CCIC2,
- MMP2_MUX_SPI,
- MMP2_MUX_SSPA2,
- MMP2_MUX_ROT,
- MMP2_MUX_I2S,
- MMP2_MUX_TB,
- MMP2_MUX_CAM2,
- MMP2_MUX_HDMI,
- MMP2_MUX_TWSI2,
- MMP2_MUX_TWSI3,
- MMP2_MUX_TWSI4,
- MMP2_MUX_TWSI5,
- MMP2_MUX_TWSI6,
- MMP2_MUX_UART1,
- MMP2_MUX_UART2,
- MMP2_MUX_UART3,
- MMP2_MUX_UART4,
- MMP2_MUX_SSP1_RX,
- MMP2_MUX_SSP1_FRM,
- MMP2_MUX_SSP1_TXRX,
- MMP2_MUX_SSP2_RX,
- MMP2_MUX_SSP2_FRM,
- MMP2_MUX_SSP1,
- MMP2_MUX_SSP2,
- MMP2_MUX_SSP3,
- MMP2_MUX_SSP4,
- MMP2_MUX_MMC1,
- MMP2_MUX_MMC2,
- MMP2_MUX_MMC3,
- MMP2_MUX_MMC4,
- MMP2_MUX_ULPI,
- MMP2_MUX_AC,
- MMP2_MUX_CA,
- MMP2_MUX_PWM,
- MMP2_MUX_USIM,
- MMP2_MUX_TIPU,
- MMP2_MUX_PLL,
- MMP2_MUX_NAND,
- MMP2_MUX_FSIC,
- MMP2_MUX_SLEEP_IND,
- MMP2_MUX_EXT_DMA,
- MMP2_MUX_ONE_WIRE,
- MMP2_MUX_LCD,
- MMP2_MUX_SMC,
- MMP2_MUX_SMC_INT,
- MMP2_MUX_MSP,
- MMP2_MUX_G_CLKOUT,
- MMP2_MUX_32K_CLKOUT,
- MMP2_MUX_PRI_JTAG,
- MMP2_MUX_AAS_JTAG,
- MMP2_MUX_AAS_GPIO,
- MMP2_MUX_AAS_SPI,
- MMP2_MUX_AAS_TWSI,
- MMP2_MUX_AAS_DEU_EX,
- MMP2_MUX_NONE = 0xffff,
-};
-
-static struct pinctrl_pin_desc mmp2_pads[] = {
- /*
- * The name indicates function 0 of this pin.
- * After reset, function 0 is the default function of pin.
- */
- PINCTRL_PIN(GPIO0, "GPIO0"),
- PINCTRL_PIN(GPIO1, "GPIO1"),
- PINCTRL_PIN(GPIO2, "GPIO2"),
- PINCTRL_PIN(GPIO3, "GPIO3"),
- PINCTRL_PIN(GPIO4, "GPIO4"),
- PINCTRL_PIN(GPIO5, "GPIO5"),
- PINCTRL_PIN(GPIO6, "GPIO6"),
- PINCTRL_PIN(GPIO7, "GPIO7"),
- PINCTRL_PIN(GPIO8, "GPIO8"),
- PINCTRL_PIN(GPIO9, "GPIO9"),
- PINCTRL_PIN(GPIO10, "GPIO10"),
- PINCTRL_PIN(GPIO11, "GPIO11"),
- PINCTRL_PIN(GPIO12, "GPIO12"),
- PINCTRL_PIN(GPIO13, "GPIO13"),
- PINCTRL_PIN(GPIO14, "GPIO14"),
- PINCTRL_PIN(GPIO15, "GPIO15"),
- PINCTRL_PIN(GPIO16, "GPIO16"),
- PINCTRL_PIN(GPIO17, "GPIO17"),
- PINCTRL_PIN(GPIO18, "GPIO18"),
- PINCTRL_PIN(GPIO19, "GPIO19"),
- PINCTRL_PIN(GPIO20, "GPIO20"),
- PINCTRL_PIN(GPIO21, "GPIO21"),
- PINCTRL_PIN(GPIO22, "GPIO22"),
- PINCTRL_PIN(GPIO23, "GPIO23"),
- PINCTRL_PIN(GPIO24, "GPIO24"),
- PINCTRL_PIN(GPIO25, "GPIO25"),
- PINCTRL_PIN(GPIO26, "GPIO26"),
- PINCTRL_PIN(GPIO27, "GPIO27"),
- PINCTRL_PIN(GPIO28, "GPIO28"),
- PINCTRL_PIN(GPIO29, "GPIO29"),
- PINCTRL_PIN(GPIO30, "GPIO30"),
- PINCTRL_PIN(GPIO31, "GPIO31"),
- PINCTRL_PIN(GPIO32, "GPIO32"),
- PINCTRL_PIN(GPIO33, "GPIO33"),
- PINCTRL_PIN(GPIO34, "GPIO34"),
- PINCTRL_PIN(GPIO35, "GPIO35"),
- PINCTRL_PIN(GPIO36, "GPIO36"),
- PINCTRL_PIN(GPIO37, "GPIO37"),
- PINCTRL_PIN(GPIO38, "GPIO38"),
- PINCTRL_PIN(GPIO39, "GPIO39"),
- PINCTRL_PIN(GPIO40, "GPIO40"),
- PINCTRL_PIN(GPIO41, "GPIO41"),
- PINCTRL_PIN(GPIO42, "GPIO42"),
- PINCTRL_PIN(GPIO43, "GPIO43"),
- PINCTRL_PIN(GPIO44, "GPIO44"),
- PINCTRL_PIN(GPIO45, "GPIO45"),
- PINCTRL_PIN(GPIO46, "GPIO46"),
- PINCTRL_PIN(GPIO47, "GPIO47"),
- PINCTRL_PIN(GPIO48, "GPIO48"),
- PINCTRL_PIN(GPIO49, "GPIO49"),
- PINCTRL_PIN(GPIO50, "GPIO50"),
- PINCTRL_PIN(GPIO51, "GPIO51"),
- PINCTRL_PIN(GPIO52, "GPIO52"),
- PINCTRL_PIN(GPIO53, "GPIO53"),
- PINCTRL_PIN(GPIO54, "GPIO54"),
- PINCTRL_PIN(GPIO55, "GPIO55"),
- PINCTRL_PIN(GPIO56, "GPIO56"),
- PINCTRL_PIN(GPIO57, "GPIO57"),
- PINCTRL_PIN(GPIO58, "GPIO58"),
- PINCTRL_PIN(GPIO59, "GPIO59"),
- PINCTRL_PIN(GPIO60, "GPIO60"),
- PINCTRL_PIN(GPIO61, "GPIO61"),
- PINCTRL_PIN(GPIO62, "GPIO62"),
- PINCTRL_PIN(GPIO63, "GPIO63"),
- PINCTRL_PIN(GPIO64, "GPIO64"),
- PINCTRL_PIN(GPIO65, "GPIO65"),
- PINCTRL_PIN(GPIO66, "GPIO66"),
- PINCTRL_PIN(GPIO67, "GPIO67"),
- PINCTRL_PIN(GPIO68, "GPIO68"),
- PINCTRL_PIN(GPIO69, "GPIO69"),
- PINCTRL_PIN(GPIO70, "GPIO70"),
- PINCTRL_PIN(GPIO71, "GPIO71"),
- PINCTRL_PIN(GPIO72, "GPIO72"),
- PINCTRL_PIN(GPIO73, "GPIO73"),
- PINCTRL_PIN(GPIO74, "GPIO74"),
- PINCTRL_PIN(GPIO75, "GPIO75"),
- PINCTRL_PIN(GPIO76, "GPIO76"),
- PINCTRL_PIN(GPIO77, "GPIO77"),
- PINCTRL_PIN(GPIO78, "GPIO78"),
- PINCTRL_PIN(GPIO79, "GPIO79"),
- PINCTRL_PIN(GPIO80, "GPIO80"),
- PINCTRL_PIN(GPIO81, "GPIO81"),
- PINCTRL_PIN(GPIO82, "GPIO82"),
- PINCTRL_PIN(GPIO83, "GPIO83"),
- PINCTRL_PIN(GPIO84, "GPIO84"),
- PINCTRL_PIN(GPIO85, "GPIO85"),
- PINCTRL_PIN(GPIO86, "GPIO86"),
- PINCTRL_PIN(GPIO87, "GPIO87"),
- PINCTRL_PIN(GPIO88, "GPIO88"),
- PINCTRL_PIN(GPIO89, "GPIO89"),
- PINCTRL_PIN(GPIO90, "GPIO90"),
- PINCTRL_PIN(GPIO91, "GPIO91"),
- PINCTRL_PIN(GPIO92, "GPIO92"),
- PINCTRL_PIN(GPIO93, "GPIO93"),
- PINCTRL_PIN(GPIO94, "GPIO94"),
- PINCTRL_PIN(GPIO95, "GPIO95"),
- PINCTRL_PIN(GPIO96, "GPIO96"),
- PINCTRL_PIN(GPIO97, "GPIO97"),
- PINCTRL_PIN(GPIO98, "GPIO98"),
- PINCTRL_PIN(GPIO99, "GPIO99"),
- PINCTRL_PIN(GPIO100, "GPIO100"),
- PINCTRL_PIN(GPIO101, "GPIO101"),
- PINCTRL_PIN(GPIO102, "GPIO102"),
- PINCTRL_PIN(GPIO103, "GPIO103"),
- PINCTRL_PIN(GPIO104, "GPIO104"),
- PINCTRL_PIN(GPIO105, "GPIO105"),
- PINCTRL_PIN(GPIO106, "GPIO106"),
- PINCTRL_PIN(GPIO107, "GPIO107"),
- PINCTRL_PIN(GPIO108, "GPIO108"),
- PINCTRL_PIN(GPIO109, "GPIO109"),
- PINCTRL_PIN(GPIO110, "GPIO110"),
- PINCTRL_PIN(GPIO111, "GPIO111"),
- PINCTRL_PIN(GPIO112, "GPIO112"),
- PINCTRL_PIN(GPIO113, "GPIO113"),
- PINCTRL_PIN(GPIO114, "GPIO114"),
- PINCTRL_PIN(GPIO115, "GPIO115"),
- PINCTRL_PIN(GPIO116, "GPIO116"),
- PINCTRL_PIN(GPIO117, "GPIO117"),
- PINCTRL_PIN(GPIO118, "GPIO118"),
- PINCTRL_PIN(GPIO119, "GPIO119"),
- PINCTRL_PIN(GPIO120, "GPIO120"),
- PINCTRL_PIN(GPIO121, "GPIO121"),
- PINCTRL_PIN(GPIO122, "GPIO122"),
- PINCTRL_PIN(GPIO123, "GPIO123"),
- PINCTRL_PIN(GPIO124, "GPIO124"),
- PINCTRL_PIN(GPIO125, "GPIO125"),
- PINCTRL_PIN(GPIO126, "GPIO126"),
- PINCTRL_PIN(GPIO127, "GPIO127"),
- PINCTRL_PIN(GPIO128, "GPIO128"),
- PINCTRL_PIN(GPIO129, "GPIO129"),
- PINCTRL_PIN(GPIO130, "GPIO130"),
- PINCTRL_PIN(GPIO131, "GPIO131"),
- PINCTRL_PIN(GPIO132, "GPIO132"),
- PINCTRL_PIN(GPIO133, "GPIO133"),
- PINCTRL_PIN(GPIO134, "GPIO134"),
- PINCTRL_PIN(GPIO135, "GPIO135"),
- PINCTRL_PIN(GPIO136, "GPIO136"),
- PINCTRL_PIN(GPIO137, "GPIO137"),
- PINCTRL_PIN(GPIO138, "GPIO138"),
- PINCTRL_PIN(GPIO139, "GPIO139"),
- PINCTRL_PIN(GPIO140, "GPIO140"),
- PINCTRL_PIN(GPIO141, "GPIO141"),
- PINCTRL_PIN(GPIO142, "GPIO142"),
- PINCTRL_PIN(GPIO143, "GPIO143"),
- PINCTRL_PIN(GPIO144, "GPIO144"),
- PINCTRL_PIN(GPIO145, "GPIO145"),
- PINCTRL_PIN(GPIO146, "GPIO146"),
- PINCTRL_PIN(GPIO147, "GPIO147"),
- PINCTRL_PIN(GPIO148, "GPIO148"),
- PINCTRL_PIN(GPIO149, "GPIO149"),
- PINCTRL_PIN(GPIO150, "GPIO150"),
- PINCTRL_PIN(GPIO151, "GPIO151"),
- PINCTRL_PIN(GPIO152, "GPIO152"),
- PINCTRL_PIN(GPIO153, "GPIO153"),
- PINCTRL_PIN(GPIO154, "GPIO154"),
- PINCTRL_PIN(GPIO155, "GPIO155"),
- PINCTRL_PIN(GPIO156, "GPIO156"),
- PINCTRL_PIN(GPIO157, "GPIO157"),
- PINCTRL_PIN(GPIO158, "GPIO158"),
- PINCTRL_PIN(GPIO159, "GPIO159"),
- PINCTRL_PIN(GPIO160, "GPIO160"),
- PINCTRL_PIN(GPIO161, "GPIO161"),
- PINCTRL_PIN(GPIO162, "GPIO162"),
- PINCTRL_PIN(GPIO163, "GPIO163"),
- PINCTRL_PIN(GPIO164, "GPIO164"),
- PINCTRL_PIN(GPIO165, "GPIO165"),
- PINCTRL_PIN(GPIO166, "GPIO166"),
- PINCTRL_PIN(GPIO167, "GPIO167"),
- PINCTRL_PIN(GPIO168, "GPIO168"),
- PINCTRL_PIN(TWSI4_SCL, "TWSI4_SCL"),
- PINCTRL_PIN(TWSI4_SDA, "TWSI4_SDA"),
- PINCTRL_PIN(G_CLKREQ, "G_CLKREQ"),
- PINCTRL_PIN(VCXO_REQ, "VCXO_REQ"),
- PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"),
-};
-
-struct pxa3xx_mfp_pin mmp2_mfp[] = {
- /* pin offs f0 f1 f2 f3 f4 f5 f6 f7 */
- MFPR_MMP2(GPIO0, 0x054, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO1, 0x058, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO2, 0x05C, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO3, 0x060, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO4, 0x064, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO5, 0x068, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO6, 0x06C, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO7, 0x070, GPIO, KP_MK, NONE, SPI, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO8, 0x074, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO9, 0x078, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO10, 0x07C, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO11, 0x080, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO12, 0x084, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO13, 0x088, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO14, 0x08C, GPIO, KP_MK, NONE, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO15, 0x090, GPIO, KP_MK, KP_DK, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO16, 0x094, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO17, 0x098, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO18, 0x09C, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO19, 0x0A0, GPIO, KP_DK, ROT, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO20, 0x0A4, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO21, 0x0A8, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO22, 0x0AC, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO23, 0x0B0, GPIO, KP_DK, TB, CCIC1, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO24, 0x0B4, GPIO, I2S, VCXO_OUT, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO25, 0x0B8, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO26, 0x0BC, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO27, 0x0C0, GPIO, I2S, HDMI, SSPA2, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO28, 0x0C4, GPIO, I2S, NONE, SSPA2, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO29, 0x0C8, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
- MFPR_MMP2(GPIO30, 0x0CC, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
- MFPR_MMP2(GPIO31, 0x0D0, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
- MFPR_MMP2(GPIO32, 0x0D4, GPIO, UART1, KP_MK, NONE, NONE, NONE, AAS_SPI, NONE),
- MFPR_MMP2(GPIO33, 0x0D8, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO34, 0x0DC, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO35, 0x0E0, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO36, 0x0E4, GPIO, SSPA2, I2S, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO37, 0x0E8, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
- MFPR_MMP2(GPIO38, 0x0EC, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
- MFPR_MMP2(GPIO39, 0x0F0, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
- MFPR_MMP2(GPIO40, 0x0F4, GPIO, MMC2, SSP1, TWSI2, UART2, UART3, AAS_SPI, AAS_TWSI),
- MFPR_MMP2(GPIO41, 0x0F8, GPIO, MMC2, TWSI5, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO42, 0x0FC, GPIO, MMC2, TWSI5, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO43, 0x100, GPIO, TWSI2, UART4, SSP1, UART2, UART3, NONE, AAS_TWSI),
- MFPR_MMP2(GPIO44, 0x104, GPIO, TWSI2, UART4, SSP1, UART2, UART3, NONE, AAS_TWSI),
- MFPR_MMP2(GPIO45, 0x108, GPIO, UART1, UART4, SSP1, UART2, UART3, NONE, NONE),
- MFPR_MMP2(GPIO46, 0x10C, GPIO, UART1, UART4, SSP1, UART2, UART3, NONE, NONE),
- MFPR_MMP2(GPIO47, 0x110, GPIO, UART2, SSP2, TWSI6, CAM2, AAS_SPI, AAS_GPIO, NONE),
- MFPR_MMP2(GPIO48, 0x114, GPIO, UART2, SSP2, TWSI6, CAM2, AAS_SPI, AAS_GPIO, NONE),
- MFPR_MMP2(GPIO49, 0x118, GPIO, UART2, SSP2, PWM, CCIC2, AAS_SPI, NONE, NONE),
- MFPR_MMP2(GPIO50, 0x11C, GPIO, UART2, SSP2, PWM, CCIC2, AAS_SPI, NONE, NONE),
- MFPR_MMP2(GPIO51, 0x120, GPIO, UART3, ROT, AAS_GPIO, PWM, NONE, NONE, NONE),
- MFPR_MMP2(GPIO52, 0x124, GPIO, UART3, ROT, AAS_GPIO, PWM, NONE, NONE, NONE),
- MFPR_MMP2(GPIO53, 0x128, GPIO, UART3, TWSI2, VCXO_REQ, NONE, PWM, NONE, AAS_TWSI),
- MFPR_MMP2(GPIO54, 0x12C, GPIO, UART3, TWSI2, VCXO_OUT, HDMI, PWM, NONE, AAS_TWSI),
- MFPR_MMP2(GPIO55, 0x130, GPIO, SSP2, SSP1, UART2, ROT, TWSI2, SSP3, AAS_TWSI),
- MFPR_MMP2(GPIO56, 0x134, GPIO, SSP2, SSP1, UART2, ROT, TWSI2, KP_DK, AAS_TWSI),
- MFPR_MMP2(GPIO57, 0x138, GPIO, SSP2_RX, SSP1_TXRX, SSP2_FRM, SSP1_RX, VCXO_REQ, KP_DK, NONE),
- MFPR_MMP2(GPIO58, 0x13C, GPIO, SSP2, SSP1_RX, SSP1_FRM, SSP1_TXRX, VCXO_REQ, KP_DK, NONE),
- MFPR_MMP2(GPIO59, 0x280, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, UART4, NONE),
- MFPR_MMP2(GPIO60, 0x284, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, UART4, NONE),
- MFPR_MMP2(GPIO61, 0x288, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, HDMI, NONE),
- MFPR_MMP2(GPIO62, 0x28C, GPIO, CCIC1, ULPI, MMC3, CCIC2, UART3, NONE, NONE),
- MFPR_MMP2(GPIO63, 0x290, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
- MFPR_MMP2(GPIO64, 0x294, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
- MFPR_MMP2(GPIO65, 0x298, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
- MFPR_MMP2(GPIO66, 0x29C, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, UART4, NONE),
- MFPR_MMP2(GPIO67, 0x2A0, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, NONE, NONE),
- MFPR_MMP2(GPIO68, 0x2A4, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, LCD, NONE),
- MFPR_MMP2(GPIO69, 0x2A8, GPIO, CCIC1, ULPI, MMC3, CCIC2, NONE, LCD, NONE),
- MFPR_MMP2(GPIO70, 0x2AC, GPIO, CCIC1, ULPI, MMC3, CCIC2, MSP, LCD, NONE),
- MFPR_MMP2(GPIO71, 0x2B0, GPIO, TWSI3, NONE, PWM, NONE, NONE, LCD, AAS_TWSI),
- MFPR_MMP2(GPIO72, 0x2B4, GPIO, TWSI3, HDMI, PWM, NONE, NONE, LCD, AAS_TWSI),
- MFPR_MMP2(GPIO73, 0x2B8, GPIO, VCXO_REQ, 32K_CLKOUT, PWM, VCXO_OUT, NONE, LCD, NONE),
- MFPR_MMP2(GPIO74, 0x170, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
- MFPR_MMP2(GPIO75, 0x174, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
- MFPR_MMP2(GPIO76, 0x178, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
- MFPR_MMP2(GPIO77, 0x17C, GPIO, LCD, SMC, MMC4, SSP3, UART2, UART4, TIPU),
- MFPR_MMP2(GPIO78, 0x180, GPIO, LCD, HDMI, MMC4, NONE, SSP4, AAS_SPI, TIPU),
- MFPR_MMP2(GPIO79, 0x184, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
- MFPR_MMP2(GPIO80, 0x188, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
- MFPR_MMP2(GPIO81, 0x18C, GPIO, LCD, AAS_GPIO, MMC4, NONE, SSP4, AAS_SPI, TIPU),
- MFPR_MMP2(GPIO82, 0x190, GPIO, LCD, NONE, MMC4, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO83, 0x194, GPIO, LCD, NONE, MMC4, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO84, 0x198, GPIO, LCD, SMC, MMC2, NONE, TWSI5, AAS_TWSI, TIPU),
- MFPR_MMP2(GPIO85, 0x19C, GPIO, LCD, SMC, MMC2, NONE, TWSI5, AAS_TWSI, TIPU),
- MFPR_MMP2(GPIO86, 0x1A0, GPIO, LCD, SMC, MMC2, NONE, TWSI6, CCIC2, TIPU),
- MFPR_MMP2(GPIO87, 0x1A4, GPIO, LCD, SMC, MMC2, NONE, TWSI6, CCIC2, TIPU),
- MFPR_MMP2(GPIO88, 0x1A8, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO89, 0x1AC, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO90, 0x1B0, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO91, 0x1B4, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO92, 0x1B8, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO93, 0x1BC, GPIO, LCD, AAS_GPIO, MMC2, NONE, NONE, CCIC2, TIPU),
- MFPR_MMP2(GPIO94, 0x1C0, GPIO, LCD, AAS_GPIO, SPI, NONE, AAS_SPI, CCIC2, TIPU),
- MFPR_MMP2(GPIO95, 0x1C4, GPIO, LCD, TWSI3, SPI, AAS_DEU_EX, AAS_SPI, CCIC2, TIPU),
- MFPR_MMP2(GPIO96, 0x1C8, GPIO, LCD, TWSI3, SPI, AAS_DEU_EX, AAS_SPI, NONE, TIPU),
- MFPR_MMP2(GPIO97, 0x1CC, GPIO, LCD, TWSI6, SPI, AAS_DEU_EX, AAS_SPI, NONE, TIPU),
- MFPR_MMP2(GPIO98, 0x1D0, GPIO, LCD, TWSI6, SPI, ONE_WIRE, NONE, NONE, TIPU),
- MFPR_MMP2(GPIO99, 0x1D4, GPIO, LCD, SMC, SPI, TWSI5, NONE, NONE, TIPU),
- MFPR_MMP2(GPIO100, 0x1D8, GPIO, LCD, SMC, SPI, TWSI5, NONE, NONE, TIPU),
- MFPR_MMP2(GPIO101, 0x1DC, GPIO, LCD, SMC, SPI, NONE, NONE, NONE, TIPU),
- MFPR_MMP2(GPIO102, 0x000, USIM, GPIO, FSIC, KP_DK, LCD, NONE, NONE, NONE),
- MFPR_MMP2(GPIO103, 0x004, USIM, GPIO, FSIC, KP_DK, LCD, NONE, NONE, NONE),
- MFPR_MMP2(GPIO104, 0x1FC, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO105, 0x1F8, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO106, 0x1F4, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO107, 0x1F0, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO108, 0x21C, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO109, 0x218, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO110, 0x214, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO111, 0x200, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO112, 0x244, NAND, GPIO, MMC3, SMC, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO113, 0x25C, SMC, GPIO, EXT_DMA, MMC3, SMC, HDMI, NONE, NONE),
- MFPR_MMP2(GPIO114, 0x164, G_CLKOUT, 32K_CLKOUT, HDMI, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO115, 0x260, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
- MFPR_MMP2(GPIO116, 0x264, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
- MFPR_MMP2(GPIO117, 0x268, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
- MFPR_MMP2(GPIO118, 0x26C, GPIO, NONE, AC, UART4, UART3, SSP1, NONE, NONE),
- MFPR_MMP2(GPIO119, 0x270, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO120, 0x274, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO121, 0x278, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO122, 0x27C, GPIO, NONE, CA, SSP3, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO123, 0x148, GPIO, SLEEP_IND, ONE_WIRE, 32K_CLKOUT, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO124, 0x00C, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO125, 0x010, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO126, 0x014, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO127, 0x018, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO128, 0x01C, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO129, 0x020, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO130, 0x024, GPIO, MMC1, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO131, 0x028, GPIO, MMC1, NONE, MSP, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO132, 0x02C, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
- MFPR_MMP2(GPIO133, 0x030, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
- MFPR_MMP2(GPIO134, 0x034, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
- MFPR_MMP2(GPIO135, 0x038, GPIO, NONE, LCD, MMC3, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO136, 0x03C, GPIO, MMC1, PRI_JTAG, MSP, SSP3, AAS_JTAG, NONE, NONE),
- MFPR_MMP2(GPIO137, 0x040, GPIO, HDMI, LCD, MSP, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO138, 0x044, GPIO, NONE, LCD, MMC3, SMC, NONE, NONE, NONE),
- MFPR_MMP2(GPIO139, 0x048, GPIO, MMC1, PRI_JTAG, MSP, NONE, AAS_JTAG, NONE, NONE),
- MFPR_MMP2(GPIO140, 0x04C, GPIO, MMC1, LCD, NONE, NONE, UART2, UART1, NONE),
- MFPR_MMP2(GPIO141, 0x050, GPIO, MMC1, LCD, NONE, NONE, UART2, UART1, NONE),
- MFPR_MMP2(GPIO142, 0x008, USIM, GPIO, FSIC, KP_DK, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO143, 0x220, NAND, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO144, 0x224, NAND, GPIO, SMC_INT, SMC, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO145, 0x228, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
- MFPR_MMP2(GPIO146, 0x22C, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
- MFPR_MMP2(GPIO147, 0x230, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO148, 0x234, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO149, 0x238, NAND, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO150, 0x23C, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO151, 0x240, SMC, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO152, 0x248, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
- MFPR_MMP2(GPIO153, 0x24C, SMC, GPIO, NONE, NONE, SMC, NONE, NONE, NONE),
- MFPR_MMP2(GPIO154, 0x254, SMC_INT, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO155, 0x258, EXT_DMA, GPIO, SMC, NONE, EXT_DMA, NONE, NONE, NONE),
- MFPR_MMP2(GPIO156, 0x14C, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO157, 0x150, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO158, 0x154, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO159, 0x158, PRI_JTAG, GPIO, PWM, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO160, 0x250, NAND, GPIO, SMC, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO161, 0x210, NAND, GPIO, NONE, NONE, NAND, NONE, NONE, NONE),
- MFPR_MMP2(GPIO162, 0x20C, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO163, 0x208, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO164, 0x204, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO165, 0x1EC, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO166, 0x1E8, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO167, 0x1E4, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(GPIO168, 0x1E0, NAND, GPIO, MMC3, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(TWSI4_SCL, 0x2BC, TWSI4, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(TWSI4_SDA, 0x2C0, TWSI4, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(G_CLKREQ, 0x160, G_CLKREQ, ONE_WIRE, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(VCXO_REQ, 0x168, VCXO_REQ, ONE_WIRE, PLL, NONE, NONE, NONE, NONE, NONE),
- MFPR_MMP2(VCXO_OUT, 0x16C, VCXO_OUT, 32K_CLKOUT, NONE, NONE, NONE, NONE, NONE, NONE),
-};
-
-static const unsigned mmp2_uart1_pin1[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned mmp2_uart1_pin2[] = {GPIO45, GPIO46};
-static const unsigned mmp2_uart1_pin3[] = {GPIO140, GPIO141};
-static const unsigned mmp2_uart2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_uart2_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart2_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned mmp2_uart2_pin4[] = {GPIO74, GPIO75, GPIO76, GPIO77};
-static const unsigned mmp2_uart2_pin5[] = {GPIO55, GPIO56};
-static const unsigned mmp2_uart2_pin6[] = {GPIO140, GPIO141};
-static const unsigned mmp2_uart3_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_uart3_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart3_pin3[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned mmp2_uart3_pin4[] = {GPIO59, GPIO60, GPIO61, GPIO62};
-static const unsigned mmp2_uart3_pin5[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_uart3_pin6[] = {GPIO51, GPIO52};
-static const unsigned mmp2_uart4_pin1[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_uart4_pin2[] = {GPIO63, GPIO64, GPIO65, GPIO66};
-static const unsigned mmp2_uart4_pin3[] = {GPIO74, GPIO75, GPIO76, GPIO77};
-static const unsigned mmp2_uart4_pin4[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_uart4_pin5[] = {GPIO59, GPIO60};
-static const unsigned mmp2_kpdk_pin1[] = {GPIO16, GPIO17, GPIO18, GPIO19};
-static const unsigned mmp2_kpdk_pin2[] = {GPIO16, GPIO17};
-static const unsigned mmp2_twsi2_pin1[] = {GPIO37, GPIO38};
-static const unsigned mmp2_twsi2_pin2[] = {GPIO39, GPIO40};
-static const unsigned mmp2_twsi2_pin3[] = {GPIO43, GPIO44};
-static const unsigned mmp2_twsi2_pin4[] = {GPIO53, GPIO54};
-static const unsigned mmp2_twsi2_pin5[] = {GPIO55, GPIO56};
-static const unsigned mmp2_twsi3_pin1[] = {GPIO71, GPIO72};
-static const unsigned mmp2_twsi3_pin2[] = {GPIO95, GPIO96};
-static const unsigned mmp2_twsi4_pin1[] = {TWSI4_SCL, TWSI4_SDA};
-static const unsigned mmp2_twsi5_pin1[] = {GPIO41, GPIO42};
-static const unsigned mmp2_twsi5_pin2[] = {GPIO84, GPIO85};
-static const unsigned mmp2_twsi5_pin3[] = {GPIO99, GPIO100};
-static const unsigned mmp2_twsi6_pin1[] = {GPIO47, GPIO48};
-static const unsigned mmp2_twsi6_pin2[] = {GPIO86, GPIO87};
-static const unsigned mmp2_twsi6_pin3[] = {GPIO97, GPIO98};
-static const unsigned mmp2_ccic1_pin1[] = {GPIO12, GPIO13, GPIO14, GPIO15,
- GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23};
-static const unsigned mmp2_ccic1_pin2[] = {GPIO59, GPIO60, GPIO61, GPIO62,
- GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ccic2_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
- GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ccic2_pin2[] = {GPIO82, GPIO83, GPIO86, GPIO87,
- GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95};
-static const unsigned mmp2_ulpi_pin1[] = {GPIO59, GPIO60, GPIO61, GPIO62,
- GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70};
-static const unsigned mmp2_ro_pin1[] = {GPIO16, GPIO17};
-static const unsigned mmp2_ro_pin2[] = {GPIO18, GPIO19};
-static const unsigned mmp2_ro_pin3[] = {GPIO51, GPIO52};
-static const unsigned mmp2_ro_pin4[] = {GPIO55, GPIO56};
-static const unsigned mmp2_i2s_pin1[] = {GPIO24, GPIO25, GPIO26, GPIO27,
- GPIO28};
-static const unsigned mmp2_i2s_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned mmp2_ssp1_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40};
-static const unsigned mmp2_ssp1_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned mmp2_ssp1_pin3[] = {GPIO115, GPIO116, GPIO117, GPIO118};
-static const unsigned mmp2_ssp2_pin1[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned mmp2_ssp3_pin1[] = {GPIO119, GPIO120, GPIO121, GPIO122};
-static const unsigned mmp2_ssp3_pin2[] = {GPIO132, GPIO133, GPIO133, GPIO136};
-static const unsigned mmp2_sspa2_pin1[] = {GPIO25, GPIO26, GPIO27, GPIO28};
-static const unsigned mmp2_sspa2_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned mmp2_mmc1_pin1[] = {GPIO131, GPIO132, GPIO133, GPIO134,
- GPIO136, GPIO139, GPIO140, GPIO141};
-static const unsigned mmp2_mmc2_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
- GPIO41, GPIO42};
-static const unsigned mmp2_mmc3_pin1[] = {GPIO111, GPIO112, GPIO151, GPIO162,
- GPIO163, GPIO164, GPIO165, GPIO166, GPIO167, GPIO168};
-
-static struct pxa3xx_pin_group mmp2_grps[] = {
- GRP_MMP2("uart1 4p1", UART1, mmp2_uart1_pin1),
- GRP_MMP2("uart1 2p2", UART1, mmp2_uart1_pin2),
- GRP_MMP2("uart1 2p3", UART1, mmp2_uart1_pin3),
- GRP_MMP2("uart2 4p1", UART2, mmp2_uart2_pin1),
- GRP_MMP2("uart2 4p2", UART2, mmp2_uart2_pin2),
- GRP_MMP2("uart2 4p3", UART2, mmp2_uart2_pin3),
- GRP_MMP2("uart2 4p4", UART2, mmp2_uart2_pin4),
- GRP_MMP2("uart2 2p5", UART2, mmp2_uart2_pin5),
- GRP_MMP2("uart2 2p6", UART2, mmp2_uart2_pin6),
- GRP_MMP2("uart3 4p1", UART3, mmp2_uart3_pin1),
- GRP_MMP2("uart3 4p2", UART3, mmp2_uart3_pin2),
- GRP_MMP2("uart3 4p3", UART3, mmp2_uart3_pin3),
- GRP_MMP2("uart3 4p4", UART3, mmp2_uart3_pin4),
- GRP_MMP2("uart3 4p5", UART3, mmp2_uart3_pin5),
- GRP_MMP2("uart3 2p6", UART3, mmp2_uart3_pin6),
- GRP_MMP2("uart4 4p1", UART4, mmp2_uart4_pin1),
- GRP_MMP2("uart4 4p2", UART4, mmp2_uart4_pin2),
- GRP_MMP2("uart4 4p3", UART4, mmp2_uart4_pin3),
- GRP_MMP2("uart4 4p4", UART4, mmp2_uart4_pin4),
- GRP_MMP2("uart4 2p5", UART4, mmp2_uart4_pin5),
- GRP_MMP2("kpdk 4p1", KP_DK, mmp2_kpdk_pin1),
- GRP_MMP2("kpdk 4p2", KP_DK, mmp2_kpdk_pin2),
- GRP_MMP2("twsi2-1", TWSI2, mmp2_twsi2_pin1),
- GRP_MMP2("twsi2-2", TWSI2, mmp2_twsi2_pin2),
- GRP_MMP2("twsi2-3", TWSI2, mmp2_twsi2_pin3),
- GRP_MMP2("twsi2-4", TWSI2, mmp2_twsi2_pin4),
- GRP_MMP2("twsi2-5", TWSI2, mmp2_twsi2_pin5),
- GRP_MMP2("twsi3-1", TWSI3, mmp2_twsi3_pin1),
- GRP_MMP2("twsi3-2", TWSI3, mmp2_twsi3_pin2),
- GRP_MMP2("twsi4", TWSI4, mmp2_twsi4_pin1),
- GRP_MMP2("twsi5-1", TWSI5, mmp2_twsi5_pin1),
- GRP_MMP2("twsi5-2", TWSI5, mmp2_twsi5_pin2),
- GRP_MMP2("twsi5-3", TWSI5, mmp2_twsi5_pin3),
- GRP_MMP2("twsi6-1", TWSI6, mmp2_twsi6_pin1),
- GRP_MMP2("twsi6-2", TWSI6, mmp2_twsi6_pin2),
- GRP_MMP2("twsi6-3", TWSI6, mmp2_twsi6_pin3),
- GRP_MMP2("ccic1-1", CCIC1, mmp2_ccic1_pin1),
- GRP_MMP2("ccic1-2", CCIC1, mmp2_ccic1_pin2),
- GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin1),
- GRP_MMP2("ccic2-1", CCIC2, mmp2_ccic2_pin2),
- GRP_MMP2("ulpi", ULPI, mmp2_ulpi_pin1),
- GRP_MMP2("ro-1", ROT, mmp2_ro_pin1),
- GRP_MMP2("ro-2", ROT, mmp2_ro_pin2),
- GRP_MMP2("ro-3", ROT, mmp2_ro_pin3),
- GRP_MMP2("ro-4", ROT, mmp2_ro_pin4),
- GRP_MMP2("i2s 5p1", I2S, mmp2_i2s_pin1),
- GRP_MMP2("i2s 4p2", I2S, mmp2_i2s_pin2),
- GRP_MMP2("ssp1 4p1", SSP1, mmp2_ssp1_pin1),
- GRP_MMP2("ssp1 4p2", SSP1, mmp2_ssp1_pin2),
- GRP_MMP2("ssp1 4p3", SSP1, mmp2_ssp1_pin3),
- GRP_MMP2("ssp2 4p1", SSP2, mmp2_ssp2_pin1),
- GRP_MMP2("ssp3 4p1", SSP3, mmp2_ssp3_pin1),
- GRP_MMP2("ssp3 4p2", SSP3, mmp2_ssp3_pin2),
- GRP_MMP2("sspa2 4p1", SSPA2, mmp2_sspa2_pin1),
- GRP_MMP2("sspa2 4p2", SSPA2, mmp2_sspa2_pin2),
- GRP_MMP2("mmc1 8p1", MMC1, mmp2_mmc1_pin1),
- GRP_MMP2("mmc2 6p1", MMC2, mmp2_mmc2_pin1),
- GRP_MMP2("mmc3 10p1", MMC3, mmp2_mmc3_pin1),
-};
-
-static const char * const mmp2_uart1_grps[] = {"uart1 4p1", "uart1 2p2",
- "uart1 2p3"};
-static const char * const mmp2_uart2_grps[] = {"uart2 4p1", "uart2 4p2",
- "uart2 4p3", "uart2 4p4", "uart2 4p5", "uart2 4p6"};
-static const char * const mmp2_uart3_grps[] = {"uart3 4p1", "uart3 4p2",
- "uart3 4p3", "uart3 4p4", "uart3 4p5", "uart3 2p6"};
-static const char * const mmp2_uart4_grps[] = {"uart4 4p1", "uart4 4p2",
- "uart4 4p3", "uart4 4p4", "uart4 2p5"};
-static const char * const mmp2_kpdk_grps[] = {"kpdk 4p1", "kpdk 4p2"};
-static const char * const mmp2_twsi2_grps[] = {"twsi2-1", "twsi2-2",
- "twsi2-3", "twsi2-4", "twsi2-5"};
-static const char * const mmp2_twsi3_grps[] = {"twsi3-1", "twsi3-2"};
-static const char * const mmp2_twsi4_grps[] = {"twsi4"};
-static const char * const mmp2_twsi5_grps[] = {"twsi5-1", "twsi5-2",
- "twsi5-3"};
-static const char * const mmp2_twsi6_grps[] = {"twsi6-1", "twsi6-2",
- "twsi6-3"};
-static const char * const mmp2_ccic1_grps[] = {"ccic1-1", "ccic1-2"};
-static const char * const mmp2_ccic2_grps[] = {"ccic2-1", "ccic2-2"};
-static const char * const mmp2_ulpi_grps[] = {"ulpi"};
-static const char * const mmp2_ro_grps[] = {"ro-1", "ro-2", "ro-3", "ro-4"};
-static const char * const mmp2_i2s_grps[] = {"i2s 5p1", "i2s 4p2"};
-static const char * const mmp2_ssp1_grps[] = {"ssp1 4p1", "ssp1 4p2",
- "ssp1 4p3"};
-static const char * const mmp2_ssp2_grps[] = {"ssp2 4p1"};
-static const char * const mmp2_ssp3_grps[] = {"ssp3 4p1", "ssp3 4p2"};
-static const char * const mmp2_sspa2_grps[] = {"sspa2 4p1", "sspa2 4p2"};
-static const char * const mmp2_mmc1_grps[] = {"mmc1 8p1"};
-static const char * const mmp2_mmc2_grps[] = {"mmc2 6p1"};
-static const char * const mmp2_mmc3_grps[] = {"mmc3 10p1"};
-
-static struct pxa3xx_pmx_func mmp2_funcs[] = {
- {"uart1", ARRAY_AND_SIZE(mmp2_uart1_grps)},
- {"uart2", ARRAY_AND_SIZE(mmp2_uart2_grps)},
- {"uart3", ARRAY_AND_SIZE(mmp2_uart3_grps)},
- {"uart4", ARRAY_AND_SIZE(mmp2_uart4_grps)},
- {"kpdk", ARRAY_AND_SIZE(mmp2_kpdk_grps)},
- {"twsi2", ARRAY_AND_SIZE(mmp2_twsi2_grps)},
- {"twsi3", ARRAY_AND_SIZE(mmp2_twsi3_grps)},
- {"twsi4", ARRAY_AND_SIZE(mmp2_twsi4_grps)},
- {"twsi5", ARRAY_AND_SIZE(mmp2_twsi5_grps)},
- {"twsi6", ARRAY_AND_SIZE(mmp2_twsi6_grps)},
- {"ccic1", ARRAY_AND_SIZE(mmp2_ccic1_grps)},
- {"ccic2", ARRAY_AND_SIZE(mmp2_ccic2_grps)},
- {"ulpi", ARRAY_AND_SIZE(mmp2_ulpi_grps)},
- {"ro", ARRAY_AND_SIZE(mmp2_ro_grps)},
- {"i2s", ARRAY_AND_SIZE(mmp2_i2s_grps)},
- {"ssp1", ARRAY_AND_SIZE(mmp2_ssp1_grps)},
- {"ssp2", ARRAY_AND_SIZE(mmp2_ssp2_grps)},
- {"ssp3", ARRAY_AND_SIZE(mmp2_ssp3_grps)},
- {"sspa2", ARRAY_AND_SIZE(mmp2_sspa2_grps)},
- {"mmc1", ARRAY_AND_SIZE(mmp2_mmc1_grps)},
- {"mmc2", ARRAY_AND_SIZE(mmp2_mmc2_grps)},
- {"mmc3", ARRAY_AND_SIZE(mmp2_mmc3_grps)},
-};
-
-static struct pinctrl_desc mmp2_pctrl_desc = {
- .name = "mmp2-pinctrl",
- .owner = THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info mmp2_info = {
- .mfp = mmp2_mfp,
- .num_mfp = ARRAY_SIZE(mmp2_mfp),
- .grps = mmp2_grps,
- .num_grps = ARRAY_SIZE(mmp2_grps),
- .funcs = mmp2_funcs,
- .num_funcs = ARRAY_SIZE(mmp2_funcs),
- .num_gpio = 169,
- .desc = &mmp2_pctrl_desc,
- .pads = mmp2_pads,
- .num_pads = ARRAY_SIZE(mmp2_pads),
-
- .cputype = PINCTRL_MMP2,
- .ds_mask = MMP2_DS_MASK,
- .ds_shift = MMP2_DS_SHIFT,
-};
-
-static int mmp2_pinmux_probe(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_register(pdev, &mmp2_info);
-}
-
-static int mmp2_pinmux_remove(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver mmp2_pinmux_driver = {
- .driver = {
- .name = "mmp2-pinmux",
- .owner = THIS_MODULE,
- },
- .probe = mmp2_pinmux_probe,
- .remove = mmp2_pinmux_remove,
-};
-
-static int __init mmp2_pinmux_init(void)
-{
- return platform_driver_register(&mmp2_pinmux_driver);
-}
-core_initcall_sync(mmp2_pinmux_init);
-
-static void __exit mmp2_pinmux_exit(void)
-{
- platform_driver_unregister(&mmp2_pinmux_driver);
-}
-module_exit(mmp2_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index 23af9f1..b45c4eb 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -158,7 +158,7 @@
kfree(map);
}
-static struct pinctrl_ops mxs_pinctrl_ops = {
+static const struct pinctrl_ops mxs_pinctrl_ops = {
.get_groups_count = mxs_get_groups_count,
.get_group_name = mxs_get_group_name,
.get_group_pins = mxs_get_group_pins,
@@ -219,7 +219,7 @@
return 0;
}
-static struct pinmux_ops mxs_pinmux_ops = {
+static const struct pinmux_ops mxs_pinmux_ops = {
.get_functions_count = mxs_pinctrl_get_funcs_count,
.get_function_name = mxs_pinctrl_get_func_name,
.get_function_groups = mxs_pinctrl_get_func_groups,
@@ -319,7 +319,7 @@
seq_printf(s, "0x%lx", config);
}
-static struct pinconf_ops mxs_pinconf_ops = {
+static const struct pinconf_ops mxs_pinconf_ops = {
.pin_config_get = mxs_pinconf_get,
.pin_config_set = mxs_pinconf_set,
.pin_config_group_get = mxs_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-nomadik-db8500.c b/drivers/pinctrl/pinctrl-nomadik-db8500.c
index 30b4da9..c748407 100644
--- a/drivers/pinctrl/pinctrl-nomadik-db8500.c
+++ b/drivers/pinctrl/pinctrl-nomadik-db8500.c
@@ -466,7 +466,7 @@
DB8500_PIN_AJ15, DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,
DB8500_PIN_AH15 };
static const unsigned mc1_a_2_pins[] = { DB8500_PIN_AH16, DB8500_PIN_AJ15,
- DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13,DB8500_PIN_AH15 };
+ DB8500_PIN_AG14, DB8500_PIN_AF13, DB8500_PIN_AG13, DB8500_PIN_AH15 };
static const unsigned mc1dir_a_1_pins[] = { DB8500_PIN_AH13, DB8500_PIN_AG12,
DB8500_PIN_AH12, DB8500_PIN_AH11 };
static const unsigned hsir_a_1_pins[] = { DB8500_PIN_AG10, DB8500_PIN_AH10,
@@ -663,7 +663,7 @@
DB8500_PIN_D21, DB8500_PIN_D20, DB8500_PIN_C20, DB8500_PIN_B21,
DB8500_PIN_C21, DB8500_PIN_A22, DB8500_PIN_B24, DB8500_PIN_C22 };
-#define DB8500_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
+#define DB8500_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \
.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
static const struct nmk_pingroup nmk_db8500_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/pinctrl-nomadik-stn8815.c
index 924a339..ed39dca 100644
--- a/drivers/pinctrl/pinctrl-nomadik-stn8815.c
+++ b/drivers/pinctrl/pinctrl-nomadik-stn8815.c
@@ -299,7 +299,7 @@
static const unsigned u1_b_1_pins[] = { STN8815_PIN_B16, STN8815_PIN_A16 };
static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 };
-#define STN8815_PIN_GROUP(a,b) { .name = #a, .pins = a##_pins, \
+#define STN8815_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins, \
.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
static const struct nmk_pingroup nmk_stn8815_groups[] = {
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 36d2029..435bf30 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -1565,8 +1565,8 @@
return 0;
}
-#define NMK_CONFIG_PIN(x,y) { .property = x, .config = y, }
-#define NMK_CONFIG_PIN_ARRAY(x,y) { .property = x, .choice = y, \
+#define NMK_CONFIG_PIN(x, y) { .property = x, .config = y, }
+#define NMK_CONFIG_PIN_ARRAY(x, y) { .property = x, .choice = y, \
.size = ARRAY_SIZE(y), }
static const unsigned long nmk_pin_input_modes[] = {
@@ -1764,7 +1764,7 @@
return 0;
}
-static struct pinctrl_ops nmk_pinctrl_ops = {
+static const struct pinctrl_ops nmk_pinctrl_ops = {
.get_groups_count = nmk_get_groups_cnt,
.get_group_name = nmk_get_group_name,
.get_group_pins = nmk_get_group_pins,
@@ -1975,7 +1975,7 @@
/* Set the pin to some default state, GPIO is usually default */
}
-static struct pinmux_ops nmk_pinmux_ops = {
+static const struct pinmux_ops nmk_pinmux_ops = {
.get_functions_count = nmk_pmx_get_funcs_cnt,
.get_function_name = nmk_pmx_get_func_name,
.get_function_groups = nmk_pmx_get_func_groups,
@@ -2068,7 +2068,7 @@
pin, cfg, pullnames[pull], slpmnames[slpm],
output ? "output " : "input",
output ? (val ? "high" : "low") : "",
- lowemi ? "on" : "off" );
+ lowemi ? "on" : "off");
clk_enable(nmk_chip->clk);
bit = pin % NMK_GPIO_PER_CHIP;
@@ -2089,7 +2089,7 @@
return 0;
}
-static struct pinconf_ops nmk_pinconf_ops = {
+static const struct pinconf_ops nmk_pinconf_ops = {
.pin_config_get = nmk_pin_config_get,
.pin_config_set = nmk_pin_config_set,
};
@@ -2111,6 +2111,10 @@
.compatible = "stericsson,nmk-pinctrl",
.data = (void *)PINCTRL_NMK_DB8500,
},
+ {
+ .compatible = "stericsson,nmk-pinctrl-db8540",
+ .data = (void *)PINCTRL_NMK_DB8540,
+ },
{},
};
diff --git a/drivers/pinctrl/pinctrl-pxa168.c b/drivers/pinctrl/pinctrl-pxa168.c
deleted file mode 100644
index d9cd2b4..0000000
--- a/drivers/pinctrl/pinctrl-pxa168.c
+++ /dev/null
@@ -1,651 +0,0 @@
-/*
- * linux/drivers/pinctrl/pinmux-pxa168.c
- *
- * 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
- * publishhed by the Free Software Foundation.
- *
- * Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define PXA168_DS_MASK 0x1800
-#define PXA168_DS_SHIFT 11
-#define PXA168_SLEEP_MASK 0x38
-#define PXA168_SLEEP_SELECT (1 << 9)
-#define PXA168_SLEEP_DATA (1 << 8)
-#define PXA168_SLEEP_DIR (1 << 7)
-
-#define MFPR_168(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \
- { \
- .name = #a, \
- .pin = a, \
- .mfpr = r, \
- .func = { \
- PXA168_MUX_##f0, \
- PXA168_MUX_##f1, \
- PXA168_MUX_##f2, \
- PXA168_MUX_##f3, \
- PXA168_MUX_##f4, \
- PXA168_MUX_##f5, \
- PXA168_MUX_##f6, \
- PXA168_MUX_##f7, \
- }, \
- }
-
-#define GRP_168(a, m, p) \
- { .name = a, .mux = PXA168_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 131 pins */
-enum pxa168_pin_list {
- /* 0~122: GPIO0~GPIO122 */
- PWR_SCL = 123,
- PWR_SDA,
- TDI,
- TMS,
- TCK,
- TDO,
- TRST,
- WAKEUP = 130,
-};
-
-enum pxa168_mux {
- /* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
- PXA168_MUX_GPIO = 0,
- PXA168_MUX_DFIO,
- PXA168_MUX_NAND,
- PXA168_MUX_SMC,
- PXA168_MUX_SMC_CS0,
- PXA168_MUX_SMC_CS1,
- PXA168_MUX_SMC_INT,
- PXA168_MUX_SMC_RDY,
- PXA168_MUX_MMC1,
- PXA168_MUX_MMC2,
- PXA168_MUX_MMC2_CMD,
- PXA168_MUX_MMC2_CLK,
- PXA168_MUX_MMC3,
- PXA168_MUX_MMC3_CMD,
- PXA168_MUX_MMC3_CLK,
- PXA168_MUX_MMC4,
- PXA168_MUX_MSP,
- PXA168_MUX_MSP_DAT3,
- PXA168_MUX_MSP_INS,
- PXA168_MUX_I2C,
- PXA168_MUX_PWRI2C,
- PXA168_MUX_AC97,
- PXA168_MUX_AC97_SYSCLK,
- PXA168_MUX_PWM,
- PXA168_MUX_PWM1,
- PXA168_MUX_XD,
- PXA168_MUX_XP,
- PXA168_MUX_LCD,
- PXA168_MUX_CCIC,
- PXA168_MUX_CF,
- PXA168_MUX_CF_RDY,
- PXA168_MUX_CF_nINPACK,
- PXA168_MUX_CF_nWAIT,
- PXA168_MUX_KP_MKOUT,
- PXA168_MUX_KP_MKIN,
- PXA168_MUX_KP_DK,
- PXA168_MUX_ETH,
- PXA168_MUX_ETH_TX,
- PXA168_MUX_ETH_RX,
- PXA168_MUX_ONE_WIRE,
- PXA168_MUX_UART1,
- PXA168_MUX_UART1_TX,
- PXA168_MUX_UART1_CTS,
- PXA168_MUX_UART1_nRI,
- PXA168_MUX_UART1_DTR,
- PXA168_MUX_UART2,
- PXA168_MUX_UART2_TX,
- PXA168_MUX_UART3,
- PXA168_MUX_UART3_TX,
- PXA168_MUX_UART3_CTS,
- PXA168_MUX_SSP1,
- PXA168_MUX_SSP1_TX,
- PXA168_MUX_SSP2,
- PXA168_MUX_SSP2_TX,
- PXA168_MUX_SSP3,
- PXA168_MUX_SSP3_TX,
- PXA168_MUX_SSP4,
- PXA168_MUX_SSP4_TX,
- PXA168_MUX_SSP5,
- PXA168_MUX_SSP5_TX,
- PXA168_MUX_USB,
- PXA168_MUX_JTAG,
- PXA168_MUX_RESET,
- PXA168_MUX_WAKEUP,
- PXA168_MUX_EXT_32K_IN,
- PXA168_MUX_NONE = 0xffff,
-};
-
-static struct pinctrl_pin_desc pxa168_pads[] = {
- PINCTRL_PIN(GPIO0, "GPIO0"),
- PINCTRL_PIN(GPIO1, "GPIO1"),
- PINCTRL_PIN(GPIO2, "GPIO2"),
- PINCTRL_PIN(GPIO3, "GPIO3"),
- PINCTRL_PIN(GPIO4, "GPIO4"),
- PINCTRL_PIN(GPIO5, "GPIO5"),
- PINCTRL_PIN(GPIO6, "GPIO6"),
- PINCTRL_PIN(GPIO7, "GPIO7"),
- PINCTRL_PIN(GPIO8, "GPIO8"),
- PINCTRL_PIN(GPIO9, "GPIO9"),
- PINCTRL_PIN(GPIO10, "GPIO10"),
- PINCTRL_PIN(GPIO11, "GPIO11"),
- PINCTRL_PIN(GPIO12, "GPIO12"),
- PINCTRL_PIN(GPIO13, "GPIO13"),
- PINCTRL_PIN(GPIO14, "GPIO14"),
- PINCTRL_PIN(GPIO15, "GPIO15"),
- PINCTRL_PIN(GPIO16, "GPIO16"),
- PINCTRL_PIN(GPIO17, "GPIO17"),
- PINCTRL_PIN(GPIO18, "GPIO18"),
- PINCTRL_PIN(GPIO19, "GPIO19"),
- PINCTRL_PIN(GPIO20, "GPIO20"),
- PINCTRL_PIN(GPIO21, "GPIO21"),
- PINCTRL_PIN(GPIO22, "GPIO22"),
- PINCTRL_PIN(GPIO23, "GPIO23"),
- PINCTRL_PIN(GPIO24, "GPIO24"),
- PINCTRL_PIN(GPIO25, "GPIO25"),
- PINCTRL_PIN(GPIO26, "GPIO26"),
- PINCTRL_PIN(GPIO27, "GPIO27"),
- PINCTRL_PIN(GPIO28, "GPIO28"),
- PINCTRL_PIN(GPIO29, "GPIO29"),
- PINCTRL_PIN(GPIO30, "GPIO30"),
- PINCTRL_PIN(GPIO31, "GPIO31"),
- PINCTRL_PIN(GPIO32, "GPIO32"),
- PINCTRL_PIN(GPIO33, "GPIO33"),
- PINCTRL_PIN(GPIO34, "GPIO34"),
- PINCTRL_PIN(GPIO35, "GPIO35"),
- PINCTRL_PIN(GPIO36, "GPIO36"),
- PINCTRL_PIN(GPIO37, "GPIO37"),
- PINCTRL_PIN(GPIO38, "GPIO38"),
- PINCTRL_PIN(GPIO39, "GPIO39"),
- PINCTRL_PIN(GPIO40, "GPIO40"),
- PINCTRL_PIN(GPIO41, "GPIO41"),
- PINCTRL_PIN(GPIO42, "GPIO42"),
- PINCTRL_PIN(GPIO43, "GPIO43"),
- PINCTRL_PIN(GPIO44, "GPIO44"),
- PINCTRL_PIN(GPIO45, "GPIO45"),
- PINCTRL_PIN(GPIO46, "GPIO46"),
- PINCTRL_PIN(GPIO47, "GPIO47"),
- PINCTRL_PIN(GPIO48, "GPIO48"),
- PINCTRL_PIN(GPIO49, "GPIO49"),
- PINCTRL_PIN(GPIO50, "GPIO50"),
- PINCTRL_PIN(GPIO51, "GPIO51"),
- PINCTRL_PIN(GPIO52, "GPIO52"),
- PINCTRL_PIN(GPIO53, "GPIO53"),
- PINCTRL_PIN(GPIO54, "GPIO54"),
- PINCTRL_PIN(GPIO55, "GPIO55"),
- PINCTRL_PIN(GPIO56, "GPIO56"),
- PINCTRL_PIN(GPIO57, "GPIO57"),
- PINCTRL_PIN(GPIO58, "GPIO58"),
- PINCTRL_PIN(GPIO59, "GPIO59"),
- PINCTRL_PIN(GPIO60, "GPIO60"),
- PINCTRL_PIN(GPIO61, "GPIO61"),
- PINCTRL_PIN(GPIO62, "GPIO62"),
- PINCTRL_PIN(GPIO63, "GPIO63"),
- PINCTRL_PIN(GPIO64, "GPIO64"),
- PINCTRL_PIN(GPIO65, "GPIO65"),
- PINCTRL_PIN(GPIO66, "GPIO66"),
- PINCTRL_PIN(GPIO67, "GPIO67"),
- PINCTRL_PIN(GPIO68, "GPIO68"),
- PINCTRL_PIN(GPIO69, "GPIO69"),
- PINCTRL_PIN(GPIO70, "GPIO70"),
- PINCTRL_PIN(GPIO71, "GPIO71"),
- PINCTRL_PIN(GPIO72, "GPIO72"),
- PINCTRL_PIN(GPIO73, "GPIO73"),
- PINCTRL_PIN(GPIO74, "GPIO74"),
- PINCTRL_PIN(GPIO75, "GPIO75"),
- PINCTRL_PIN(GPIO76, "GPIO76"),
- PINCTRL_PIN(GPIO77, "GPIO77"),
- PINCTRL_PIN(GPIO78, "GPIO78"),
- PINCTRL_PIN(GPIO79, "GPIO79"),
- PINCTRL_PIN(GPIO80, "GPIO80"),
- PINCTRL_PIN(GPIO81, "GPIO81"),
- PINCTRL_PIN(GPIO82, "GPIO82"),
- PINCTRL_PIN(GPIO83, "GPIO83"),
- PINCTRL_PIN(GPIO84, "GPIO84"),
- PINCTRL_PIN(GPIO85, "GPIO85"),
- PINCTRL_PIN(GPIO86, "GPIO86"),
- PINCTRL_PIN(GPIO87, "GPIO87"),
- PINCTRL_PIN(GPIO88, "GPIO88"),
- PINCTRL_PIN(GPIO89, "GPIO89"),
- PINCTRL_PIN(GPIO90, "GPIO90"),
- PINCTRL_PIN(GPIO91, "GPIO91"),
- PINCTRL_PIN(GPIO92, "GPIO92"),
- PINCTRL_PIN(GPIO93, "GPIO93"),
- PINCTRL_PIN(GPIO94, "GPIO94"),
- PINCTRL_PIN(GPIO95, "GPIO95"),
- PINCTRL_PIN(GPIO96, "GPIO96"),
- PINCTRL_PIN(GPIO97, "GPIO97"),
- PINCTRL_PIN(GPIO98, "GPIO98"),
- PINCTRL_PIN(GPIO99, "GPIO99"),
- PINCTRL_PIN(GPIO100, "GPIO100"),
- PINCTRL_PIN(GPIO101, "GPIO101"),
- PINCTRL_PIN(GPIO102, "GPIO102"),
- PINCTRL_PIN(GPIO103, "GPIO103"),
- PINCTRL_PIN(GPIO104, "GPIO104"),
- PINCTRL_PIN(GPIO105, "GPIO105"),
- PINCTRL_PIN(GPIO106, "GPIO106"),
- PINCTRL_PIN(GPIO107, "GPIO107"),
- PINCTRL_PIN(GPIO108, "GPIO108"),
- PINCTRL_PIN(GPIO109, "GPIO109"),
- PINCTRL_PIN(GPIO110, "GPIO110"),
- PINCTRL_PIN(GPIO111, "GPIO111"),
- PINCTRL_PIN(GPIO112, "GPIO112"),
- PINCTRL_PIN(GPIO113, "GPIO113"),
- PINCTRL_PIN(GPIO114, "GPIO114"),
- PINCTRL_PIN(GPIO115, "GPIO115"),
- PINCTRL_PIN(GPIO116, "GPIO116"),
- PINCTRL_PIN(GPIO117, "GPIO117"),
- PINCTRL_PIN(GPIO118, "GPIO118"),
- PINCTRL_PIN(GPIO119, "GPIO119"),
- PINCTRL_PIN(GPIO120, "GPIO120"),
- PINCTRL_PIN(GPIO121, "GPIO121"),
- PINCTRL_PIN(GPIO122, "GPIO122"),
- PINCTRL_PIN(PWR_SCL, "PWR_SCL"),
- PINCTRL_PIN(PWR_SDA, "PWR_SDA"),
- PINCTRL_PIN(TDI, "TDI"),
- PINCTRL_PIN(TMS, "TMS"),
- PINCTRL_PIN(TCK, "TCK"),
- PINCTRL_PIN(TDO, "TDO"),
- PINCTRL_PIN(TRST, "TRST"),
- PINCTRL_PIN(WAKEUP, "WAKEUP"),
-};
-
-struct pxa3xx_mfp_pin pxa168_mfp[] = {
- /* pin offs f0 f1 f2 f3 f4 f5 f6 f7 */
- MFPR_168(GPIO0, 0x04C, DFIO, NONE, NONE, MSP, MMC3_CMD, GPIO, MMC3, NONE),
- MFPR_168(GPIO1, 0x050, DFIO, NONE, NONE, MSP, MMC3_CLK, GPIO, MMC3, NONE),
- MFPR_168(GPIO2, 0x054, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO3, 0x058, DFIO, NONE, NONE, NONE, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO4, 0x05C, DFIO, NONE, NONE, MSP_DAT3, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO5, 0x060, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO6, 0x064, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO7, 0x068, DFIO, NONE, NONE, MSP, NONE, GPIO, MMC3, NONE),
- MFPR_168(GPIO8, 0x06C, DFIO, MMC2, UART3_TX, NONE, MMC2_CMD, GPIO, MMC3_CLK, NONE),
- MFPR_168(GPIO9, 0x070, DFIO, MMC2, UART3, NONE, MMC2_CLK, GPIO, MMC3_CMD, NONE),
- MFPR_168(GPIO10, 0x074, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP_DAT3, NONE),
- MFPR_168(GPIO11, 0x078, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO12, 0x07C, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO13, 0x080, DFIO, MMC2, UART3, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO14, 0x084, DFIO, MMC2, NONE, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO15, 0x088, DFIO, MMC2, NONE, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO16, 0x08C, GPIO, NAND, SMC_CS0, SMC_CS1, NONE, NONE, MMC3, NONE),
- MFPR_168(GPIO17, 0x090, NAND, NONE, NONE, NONE, NONE, GPIO, MSP, NONE),
- MFPR_168(GPIO18, 0x094, GPIO, NAND, SMC_CS1, SMC_CS0, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO19, 0x098, SMC_CS0, NONE, NONE, CF, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO20, 0x09C, GPIO, NONE, SMC_CS1, CF, CF_RDY, NONE, NONE, NONE),
- MFPR_168(GPIO21, 0x0A0, NAND, MMC2_CLK, NONE, NONE, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO22, 0x0A4, NAND, MMC2_CMD, NONE, NONE, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO23, 0x0A8, SMC, NAND, NONE, CF, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO24, 0x0AC, NAND, NONE, NONE, NONE, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO25, 0x0B0, SMC, NAND, NONE, CF, NONE, GPIO, NONE, NONE),
- MFPR_168(GPIO26, 0x0B4, GPIO, NAND, NONE, NONE, CF, NONE, NONE, NONE),
- MFPR_168(GPIO27, 0x0B8, SMC_INT, NAND, SMC, NONE, SMC_RDY, GPIO, NONE, NONE),
- MFPR_168(GPIO28, 0x0BC, SMC_RDY, MMC4, SMC, CF_RDY, NONE, GPIO, MMC2_CMD, NONE),
- MFPR_168(GPIO29, 0x0C0, SMC, MMC4, NONE, CF, NONE, GPIO, MMC2_CLK, KP_DK),
- MFPR_168(GPIO30, 0x0C4, SMC, MMC4, UART3_TX, CF, NONE, GPIO, MMC2, KP_DK),
- MFPR_168(GPIO31, 0x0C8, SMC, MMC4, UART3, CF, NONE, GPIO, MMC2, KP_DK),
- MFPR_168(GPIO32, 0x0CC, SMC, MMC4, UART3, CF, NONE, GPIO, MMC2, KP_DK),
- MFPR_168(GPIO33, 0x0D0, SMC, MMC4, UART3, CF, CF_nINPACK, GPIO, MMC2, KP_DK),
- MFPR_168(GPIO34, 0x0D4, GPIO, NONE, SMC_CS1, CF, CF_nWAIT, NONE, MMC3, KP_DK),
- MFPR_168(GPIO35, 0x0D8, GPIO, NONE, SMC, CF_nINPACK, NONE, NONE, MMC3_CMD, KP_DK),
- MFPR_168(GPIO36, 0x0DC, GPIO, NONE, SMC, CF_nWAIT, NONE, NONE, MMC3_CLK, KP_DK),
- MFPR_168(GPIO37, 0x000, GPIO, MMC1, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO38, 0x004, GPIO, MMC1, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO39, 0x008, GPIO, NONE, NONE, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO40, 0x00C, GPIO, MMC1, MSP, KP_MKOUT, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO41, 0x010, GPIO, MMC1, MSP, NONE, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO42, 0x014, GPIO, I2C, NONE, MSP, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO43, 0x018, GPIO, MMC1, MSP, MSP_INS, NONE, NONE, KP_MKIN, KP_DK),
- MFPR_168(GPIO44, 0x01C, GPIO, MMC1, MSP_DAT3, MSP, CCIC, XP, KP_MKIN, KP_DK),
- MFPR_168(GPIO45, 0x020, GPIO, NONE, NONE, MSP, CCIC, XP, NONE, KP_DK),
- MFPR_168(GPIO46, 0x024, GPIO, MMC1, MSP_INS, MSP, CCIC, NONE, KP_MKOUT, KP_DK),
- MFPR_168(GPIO47, 0x028, GPIO, NONE, NONE, MSP_INS, NONE, XP, NONE, KP_DK),
- MFPR_168(GPIO48, 0x02C, GPIO, MMC1, NONE, MSP_DAT3, CCIC, NONE, NONE, KP_DK),
- MFPR_168(GPIO49, 0x030, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO50, 0x034, GPIO, I2C, NONE, MSP, CCIC, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO51, 0x038, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO52, 0x03C, GPIO, MMC1, NONE, MSP, NONE, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO53, 0x040, GPIO, MMC1, NONE, NONE, NONE, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO54, 0x044, GPIO, MMC1, NONE, NONE, CCIC, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO55, 0x048, GPIO, NONE, NONE, MSP, CCIC, XD, KP_MKOUT, NONE),
- MFPR_168(GPIO56, 0x0E0, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO57, 0x0E4, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO58, 0x0E8, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO59, 0x0EC, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO60, 0x0F0, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO61, 0x0F4, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO62, 0x0F8, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO63, 0x0FC, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO64, 0x100, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO65, 0x104, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO66, 0x108, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO67, 0x10C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO68, 0x110, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO69, 0x114, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO70, 0x118, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO71, 0x11C, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO72, 0x120, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO73, 0x124, GPIO, LCD, NONE, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO74, 0x128, GPIO, LCD, PWM, XD, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO75, 0x12C, GPIO, LCD, PWM, XD, ONE_WIRE, NONE, NONE, NONE),
- MFPR_168(GPIO76, 0x130, GPIO, LCD, PWM, I2C, NONE, NONE, MSP_INS, NONE),
- MFPR_168(GPIO77, 0x134, GPIO, LCD, PWM1, I2C, ONE_WIRE, NONE, XD, NONE),
- MFPR_168(GPIO78, 0x138, GPIO, LCD, NONE, NONE, NONE, MMC4, NONE, NONE),
- MFPR_168(GPIO79, 0x13C, GPIO, LCD, NONE, NONE, ONE_WIRE, MMC4, NONE, NONE),
- MFPR_168(GPIO80, 0x140, GPIO, LCD, NONE, I2C, NONE, MMC4, NONE, NONE),
- MFPR_168(GPIO81, 0x144, GPIO, LCD, NONE, I2C, ONE_WIRE, MMC4, NONE, NONE),
- MFPR_168(GPIO82, 0x148, GPIO, LCD, PWM, NONE, NONE, MMC4, NONE, NONE),
- MFPR_168(GPIO83, 0x14C, GPIO, LCD, PWM, NONE, RESET, MMC4, NONE, NONE),
- MFPR_168(GPIO84, 0x150, GPIO, NONE, PWM, ONE_WIRE, PWM1, NONE, NONE, EXT_32K_IN),
- MFPR_168(GPIO85, 0x154, GPIO, NONE, PWM1, NONE, NONE, NONE, NONE, USB),
- MFPR_168(GPIO86, 0x158, GPIO, MMC2, UART2, NONE, JTAG, ETH_TX, SSP5_TX, SSP5),
- MFPR_168(GPIO87, 0x15C, GPIO, MMC2, UART2, NONE, JTAG, ETH_TX, SSP5, SSP5_TX),
- MFPR_168(GPIO88, 0x160, GPIO, MMC2, UART2, UART2_TX, JTAG, ETH_TX, ETH_RX, SSP5),
- MFPR_168(GPIO89, 0x164, GPIO, MMC2, UART2_TX, UART2, JTAG, ETH_TX, ETH_RX, SSP5),
- MFPR_168(GPIO90, 0x168, GPIO, MMC2, NONE, SSP3, JTAG, ETH_TX, ETH_RX, NONE),
- MFPR_168(GPIO91, 0x16C, GPIO, MMC2, NONE, SSP3, SSP4, ETH_TX, ETH_RX, NONE),
- MFPR_168(GPIO92, 0x170, GPIO, MMC2, NONE, SSP3, SSP3_TX, ETH, NONE, NONE),
- MFPR_168(GPIO93, 0x174, GPIO, MMC2, NONE, SSP3_TX, SSP3, ETH, NONE, NONE),
- MFPR_168(GPIO94, 0x178, GPIO, MMC2_CMD, SSP3, AC97_SYSCLK, AC97, ETH, NONE, NONE),
- MFPR_168(GPIO95, 0x17C, GPIO, MMC2_CLK, NONE, NONE, AC97, ETH, NONE, NONE),
- MFPR_168(GPIO96, 0x180, GPIO, PWM, NONE, MMC2, NONE, ETH_RX, ETH_TX, NONE),
- MFPR_168(GPIO97, 0x184, GPIO, PWM, ONE_WIRE, NONE, NONE, ETH_RX, ETH_TX, NONE),
- MFPR_168(GPIO98, 0x188, GPIO, PWM1, UART3_TX, UART3, NONE, ETH_RX, ETH_TX, NONE),
- MFPR_168(GPIO99, 0x18C, GPIO, ONE_WIRE, UART3, UART3_TX, NONE, ETH_RX, ETH_TX, NONE),
- MFPR_168(GPIO100, 0x190, GPIO, NONE, UART3_CTS, UART3, NONE, ETH, NONE, NONE),
- MFPR_168(GPIO101, 0x194, GPIO, NONE, UART3, UART3_CTS, NONE, ETH, NONE, NONE),
- MFPR_168(GPIO102, 0x198, GPIO, I2C, UART3, SSP4, NONE, NONE, NONE, NONE),
- MFPR_168(GPIO103, 0x19C, GPIO, I2C, UART3, SSP4, SSP2, ETH, NONE, NONE),
- MFPR_168(GPIO104, 0x1A0, GPIO, PWM, UART1, SSP4, SSP4_TX, AC97, KP_MKOUT, NONE),
- MFPR_168(GPIO105, 0x1A4, GPIO, I2C, UART1, SSP4_TX, SSP4, AC97, KP_MKOUT, NONE),
- MFPR_168(GPIO106, 0x1A8, GPIO, I2C, PWM1, AC97_SYSCLK, MMC2, NONE, KP_MKOUT, NONE),
- MFPR_168(GPIO107, 0x1AC, GPIO, UART1_TX, UART1, NONE, SSP2, MSP_DAT3, NONE, KP_MKIN),
- MFPR_168(GPIO108, 0x1B0, GPIO, UART1, UART1_TX, NONE, SSP2_TX, MSP, NONE, KP_MKIN),
- MFPR_168(GPIO109, 0x1B4, GPIO, UART1_CTS, UART1, NONE, AC97_SYSCLK, MSP, NONE, KP_MKIN),
- MFPR_168(GPIO110, 0x1B8, GPIO, UART1, UART1_CTS, NONE, SMC_RDY, MSP, NONE, KP_MKIN),
- MFPR_168(GPIO111, 0x1BC, GPIO, UART1_nRI, UART1, SSP3, SSP2, MSP, XD, KP_MKOUT),
- MFPR_168(GPIO112, 0x1C0, GPIO, UART1_DTR, UART1, ONE_WIRE, SSP2, MSP, XD, KP_MKOUT),
- MFPR_168(GPIO113, 0x1C4, GPIO, NONE, NONE, NONE, NONE, NONE, AC97_SYSCLK, NONE),
- MFPR_168(GPIO114, 0x1C8, GPIO, SSP1, NONE, NONE, NONE, NONE, AC97, NONE),
- MFPR_168(GPIO115, 0x1CC, GPIO, SSP1, NONE, NONE, NONE, NONE, AC97, NONE),
- MFPR_168(GPIO116, 0x1D0, GPIO, SSP1_TX, SSP1, NONE, NONE, NONE, AC97, NONE),
- MFPR_168(GPIO117, 0x1D4, GPIO, SSP1, SSP1_TX, NONE, MMC2_CMD, NONE, AC97, NONE),
- MFPR_168(GPIO118, 0x1D8, GPIO, SSP2, NONE, NONE, MMC2_CLK, NONE, AC97, KP_MKIN),
- MFPR_168(GPIO119, 0x1DC, GPIO, SSP2, NONE, NONE, MMC2, NONE, AC97, KP_MKIN),
- MFPR_168(GPIO120, 0x1E0, GPIO, SSP2, SSP2_TX, NONE, MMC2, NONE, NONE, KP_MKIN),
- MFPR_168(GPIO121, 0x1E4, GPIO, SSP2_TX, SSP2, NONE, MMC2, NONE, NONE, KP_MKIN),
- MFPR_168(GPIO122, 0x1E8, GPIO, AC97_SYSCLK, SSP2, PWM, MMC2, NONE, NONE, NONE),
- MFPR_168(PWR_SCL, 0x1EC, PWRI2C, NONE, NONE, NONE, NONE, NONE, GPIO, MMC4),
- MFPR_168(PWR_SDA, 0x1F0, PWRI2C, NONE, NONE, NONE, NONE, NONE, GPIO, NONE),
- MFPR_168(TDI, 0x1F4, JTAG, PWM1, UART2, MMC4, SSP5, NONE, XD, MMC4),
- MFPR_168(TMS, 0x1F8, JTAG, PWM, UART2, NONE, SSP5, NONE, XD, MMC4),
- MFPR_168(TCK, 0x1FC, JTAG, PWM, UART2, UART2_TX, SSP5, NONE, XD, MMC4),
- MFPR_168(TDO, 0x200, JTAG, PWM, UART2_TX, UART2, SSP5_TX, NONE, XD, MMC4),
- MFPR_168(TRST, 0x204, JTAG, ONE_WIRE, SSP2, SSP3, AC97_SYSCLK, NONE, XD, MMC4),
- MFPR_168(WAKEUP, 0x208, WAKEUP, ONE_WIRE, PWM1, PWM, SSP2, NONE, GPIO, MMC4),
-};
-
-static const unsigned p168_jtag_pin1[] = {TDI, TMS, TCK, TDO, TRST};
-static const unsigned p168_wakeup_pin1[] = {WAKEUP};
-static const unsigned p168_ssp1rx_pin1[] = {GPIO114, GPIO115, GPIO116};
-static const unsigned p168_ssp1tx_pin1[] = {GPIO117};
-static const unsigned p168_ssp4rx_pin1[] = {GPIO102, GPIO103, GPIO104};
-static const unsigned p168_ssp4tx_pin1[] = {GPIO105};
-static const unsigned p168_ssp5rx_pin1[] = {GPIO86, GPIO88, GPIO89};
-static const unsigned p168_ssp5tx_pin1[] = {GPIO87};
-static const unsigned p168_i2c_pin1[] = {GPIO105, GPIO106};
-static const unsigned p168_pwri2c_pin1[] = {PWR_SCL, PWR_SDA};
-static const unsigned p168_mmc1_pin1[] = {GPIO40, GPIO41, GPIO43, GPIO46,
- GPIO49, GPIO51, GPIO52, GPIO53};
-static const unsigned p168_mmc2_data_pin1[] = {GPIO90, GPIO91, GPIO92, GPIO93};
-static const unsigned p168_mmc2_cmd_pin1[] = {GPIO94};
-static const unsigned p168_mmc2_clk_pin1[] = {GPIO95};
-static const unsigned p168_mmc3_data_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
- GPIO4, GPIO5, GPIO6, GPIO7};
-static const unsigned p168_mmc3_cmd_pin1[] = {GPIO9};
-static const unsigned p168_mmc3_clk_pin1[] = {GPIO8};
-static const unsigned p168_eth_pin1[] = {GPIO92, GPIO93, GPIO100, GPIO101,
- GPIO103};
-static const unsigned p168_ethtx_pin1[] = {GPIO86, GPIO87, GPIO88, GPIO89,
- GPIO90, GPIO91};
-static const unsigned p168_ethrx_pin1[] = {GPIO94, GPIO95, GPIO96, GPIO97,
- GPIO98, GPIO99};
-static const unsigned p168_uart1rx_pin1[] = {GPIO107};
-static const unsigned p168_uart1tx_pin1[] = {GPIO108};
-static const unsigned p168_uart3rx_pin1[] = {GPIO98, GPIO100, GPIO101};
-static const unsigned p168_uart3tx_pin1[] = {GPIO99};
-static const unsigned p168_msp_pin1[] = {GPIO40, GPIO41, GPIO42, GPIO43,
- GPIO44, GPIO50};
-static const unsigned p168_ccic_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
- GPIO41, GPIO42, GPIO44, GPIO45, GPIO46, GPIO48, GPIO54, GPIO55};
-static const unsigned p168_xd_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
- GPIO41, GPIO42, GPIO44, GPIO45, GPIO47, GPIO48, GPIO49, GPIO50,
- GPIO51, GPIO52};
-static const unsigned p168_lcd_pin1[] = {GPIO56, GPIO57, GPIO58, GPIO59,
- GPIO60, GPIO61, GPIO62, GPIO63, GPIO64, GPIO65, GPIO66, GPIO67,
- GPIO68, GPIO69, GPIO70, GPIO71, GPIO72, GPIO73, GPIO74, GPIO75,
- GPIO76, GPIO77, GPIO78, GPIO79, GPIO80, GPIO81, GPIO82, GPIO83};
-static const unsigned p168_dfio_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3,
- GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12,
- GPIO13, GPIO14, GPIO15};
-static const unsigned p168_nand_pin1[] = {GPIO16, GPIO17, GPIO21, GPIO22,
- GPIO24, GPIO26};
-static const unsigned p168_smc_pin1[] = {GPIO23, GPIO25, GPIO29, GPIO35,
- GPIO36};
-static const unsigned p168_smccs0_pin1[] = {GPIO18};
-static const unsigned p168_smccs1_pin1[] = {GPIO34};
-static const unsigned p168_smcrdy_pin1[] = {GPIO28};
-static const unsigned p168_ac97sysclk_pin1[] = {GPIO113};
-static const unsigned p168_ac97_pin1[] = {GPIO114, GPIO115, GPIO117, GPIO118,
- GPIO119};
-static const unsigned p168_cf_pin1[] = {GPIO19, GPIO20, GPIO23, GPIO25,
- GPIO28, GPIO29, GPIO30, GPIO31, GPIO32, GPIO33, GPIO34, GPIO35,
- GPIO36};
-static const unsigned p168_kpmkin_pin1[] = {GPIO109, GPIO110, GPIO121};
-static const unsigned p168_kpmkout_pin1[] = {GPIO111, GPIO112};
-static const unsigned p168_gpio86_pin1[] = {WAKEUP};
-static const unsigned p168_gpio86_pin2[] = {GPIO86};
-static const unsigned p168_gpio87_pin1[] = {GPIO87};
-static const unsigned p168_gpio87_pin2[] = {PWR_SDA};
-static const unsigned p168_gpio88_pin1[] = {GPIO88};
-static const unsigned p168_gpio88_pin2[] = {PWR_SCL};
-
-static struct pxa3xx_pin_group pxa168_grps[] = {
- GRP_168("uart1rx-1", UART1, p168_uart1rx_pin1),
- GRP_168("uart1tx-1", UART1_TX, p168_uart1tx_pin1),
- GRP_168("uart3rx-1", UART3, p168_uart3rx_pin1),
- GRP_168("uart3tx-1", UART3_TX, p168_uart3tx_pin1),
- GRP_168("ssp1rx-1", SSP1, p168_ssp1rx_pin1),
- GRP_168("ssp1tx-1", SSP1_TX, p168_ssp1tx_pin1),
- GRP_168("ssp4rx-1", SSP4, p168_ssp4rx_pin1),
- GRP_168("ssp4tx-1", SSP4_TX, p168_ssp4tx_pin1),
- GRP_168("ssp5rx-1", SSP5, p168_ssp5rx_pin1),
- GRP_168("ssp5tx-1", SSP5_TX, p168_ssp5tx_pin1),
- GRP_168("jtag", JTAG, p168_jtag_pin1),
- GRP_168("wakeup", WAKEUP, p168_wakeup_pin1),
- GRP_168("i2c", I2C, p168_i2c_pin1),
- GRP_168("pwri2c", PWRI2C, p168_pwri2c_pin1),
- GRP_168("mmc1 8p1", MMC1, p168_mmc1_pin1),
- GRP_168("mmc2 4p1", MMC2, p168_mmc2_data_pin1),
- GRP_168("mmc2 cmd1", MMC2_CMD, p168_mmc2_cmd_pin1),
- GRP_168("mmc2 clk1", MMC2_CLK, p168_mmc2_clk_pin1),
- GRP_168("mmc3 8p1", MMC3, p168_mmc3_data_pin1),
- GRP_168("mmc3 cmd1", MMC3_CMD, p168_mmc3_cmd_pin1),
- GRP_168("mmc3 clk1", MMC3_CLK, p168_mmc3_clk_pin1),
- GRP_168("eth", ETH, p168_eth_pin1),
- GRP_168("eth rx", ETH_RX, p168_ethrx_pin1),
- GRP_168("eth tx", ETH_TX, p168_ethtx_pin1),
- GRP_168("msp", MSP, p168_msp_pin1),
- GRP_168("ccic", CCIC, p168_ccic_pin1),
- GRP_168("xd", XD, p168_xd_pin1),
- GRP_168("lcd", LCD, p168_lcd_pin1),
- GRP_168("dfio", DFIO, p168_dfio_pin1),
- GRP_168("nand", NAND, p168_nand_pin1),
- GRP_168("smc", SMC, p168_smc_pin1),
- GRP_168("smc cs0", SMC_CS0, p168_smccs0_pin1),
- GRP_168("smc cs1", SMC_CS1, p168_smccs1_pin1),
- GRP_168("smc rdy", SMC_RDY, p168_smcrdy_pin1),
- GRP_168("ac97 sysclk", AC97_SYSCLK, p168_ac97sysclk_pin1),
- GRP_168("ac97", AC97, p168_ac97_pin1),
- GRP_168("cf", CF, p168_cf_pin1),
- GRP_168("kp mkin 3p1", KP_MKIN, p168_kpmkin_pin1),
- GRP_168("kp mkout 2p1", KP_MKOUT, p168_kpmkout_pin1),
- GRP_168("gpio86-1", GPIO, p168_gpio86_pin1),
- GRP_168("gpio86-2", GPIO, p168_gpio86_pin2),
- GRP_168("gpio87-1", GPIO, p168_gpio87_pin1),
- GRP_168("gpio87-2", GPIO, p168_gpio87_pin2),
- GRP_168("gpio88-1", GPIO, p168_gpio88_pin1),
- GRP_168("gpio88-2", GPIO, p168_gpio88_pin2),
-};
-
-static const char * const p168_uart1rx_grps[] = {"uart1rx-1"};
-static const char * const p168_uart1tx_grps[] = {"uart1tx-1"};
-static const char * const p168_uart3rx_grps[] = {"uart3rx-1"};
-static const char * const p168_uart3tx_grps[] = {"uart3tx-1"};
-static const char * const p168_ssp1rx_grps[] = {"ssp1rx-1"};
-static const char * const p168_ssp1tx_grps[] = {"ssp1tx-1"};
-static const char * const p168_ssp4rx_grps[] = {"ssp4rx-1"};
-static const char * const p168_ssp4tx_grps[] = {"ssp4tx-1"};
-static const char * const p168_ssp5rx_grps[] = {"ssp5rx-1"};
-static const char * const p168_ssp5tx_grps[] = {"ssp5tx-1"};
-static const char * const p168_i2c_grps[] = {"i2c"};
-static const char * const p168_pwri2c_grps[] = {"pwri2c"};
-static const char * const p168_mmc1_grps[] = {"mmc1 8p1"};
-static const char * const p168_mmc2_data_grps[] = {"mmc2 4p1"};
-static const char * const p168_mmc2_cmd_grps[] = {"mmc2 cmd1"};
-static const char * const p168_mmc2_clk_grps[] = {"mmc2 clk1"};
-static const char * const p168_mmc3_data_grps[] = {"mmc3 8p1"};
-static const char * const p168_mmc3_cmd_grps[] = {"mmc3 cmd1"};
-static const char * const p168_mmc3_clk_grps[] = {"mmc3 clk1"};
-static const char * const p168_eth_grps[] = {"eth"};
-static const char * const p168_ethrx_grps[] = {"eth rx"};
-static const char * const p168_ethtx_grps[] = {"eth tx"};
-static const char * const p168_msp_grps[] = {"msp"};
-static const char * const p168_ccic_grps[] = {"ccic"};
-static const char * const p168_xd_grps[] = {"xd"};
-static const char * const p168_lcd_grps[] = {"lcd"};
-static const char * const p168_dfio_grps[] = {"dfio"};
-static const char * const p168_nand_grps[] = {"nand"};
-static const char * const p168_smc_grps[] = {"smc"};
-static const char * const p168_smccs0_grps[] = {"smc cs0"};
-static const char * const p168_smccs1_grps[] = {"smc cs1"};
-static const char * const p168_smcrdy_grps[] = {"smc rdy"};
-static const char * const p168_ac97sysclk_grps[] = {"ac97 sysclk"};
-static const char * const p168_ac97_grps[] = {"ac97"};
-static const char * const p168_cf_grps[] = {"cf"};
-static const char * const p168_kpmkin_grps[] = {"kp mkin 3p1"};
-static const char * const p168_kpmkout_grps[] = {"kp mkout 2p1"};
-static const char * const p168_gpio86_grps[] = {"gpio86-1", "gpio86-2"};
-static const char * const p168_gpio87_grps[] = {"gpio87-1", "gpio87-2"};
-static const char * const p168_gpio88_grps[] = {"gpio88-1", "gpio88-2"};
-
-static struct pxa3xx_pmx_func pxa168_funcs[] = {
- {"uart1 rx", ARRAY_AND_SIZE(p168_uart1rx_grps)},
- {"uart1 tx", ARRAY_AND_SIZE(p168_uart1tx_grps)},
- {"uart3 rx", ARRAY_AND_SIZE(p168_uart3rx_grps)},
- {"uart3 tx", ARRAY_AND_SIZE(p168_uart3tx_grps)},
- {"ssp1 rx", ARRAY_AND_SIZE(p168_ssp1rx_grps)},
- {"ssp1 tx", ARRAY_AND_SIZE(p168_ssp1tx_grps)},
- {"ssp4 rx", ARRAY_AND_SIZE(p168_ssp4rx_grps)},
- {"ssp4 tx", ARRAY_AND_SIZE(p168_ssp4tx_grps)},
- {"ssp5 rx", ARRAY_AND_SIZE(p168_ssp5rx_grps)},
- {"ssp5 tx", ARRAY_AND_SIZE(p168_ssp5tx_grps)},
- {"i2c", ARRAY_AND_SIZE(p168_i2c_grps)},
- {"pwri2c", ARRAY_AND_SIZE(p168_pwri2c_grps)},
- {"mmc1", ARRAY_AND_SIZE(p168_mmc1_grps)},
- {"mmc2", ARRAY_AND_SIZE(p168_mmc2_data_grps)},
- {"mmc2 cmd", ARRAY_AND_SIZE(p168_mmc2_cmd_grps)},
- {"mmc2 clk", ARRAY_AND_SIZE(p168_mmc2_clk_grps)},
- {"mmc3", ARRAY_AND_SIZE(p168_mmc3_data_grps)},
- {"mmc3 cmd", ARRAY_AND_SIZE(p168_mmc3_cmd_grps)},
- {"mmc3 clk", ARRAY_AND_SIZE(p168_mmc3_clk_grps)},
- {"eth", ARRAY_AND_SIZE(p168_eth_grps)},
- {"eth rx", ARRAY_AND_SIZE(p168_ethrx_grps)},
- {"eth tx", ARRAY_AND_SIZE(p168_ethtx_grps)},
- {"msp", ARRAY_AND_SIZE(p168_msp_grps)},
- {"ccic", ARRAY_AND_SIZE(p168_ccic_grps)},
- {"xd", ARRAY_AND_SIZE(p168_xd_grps)},
- {"lcd", ARRAY_AND_SIZE(p168_lcd_grps)},
- {"dfio", ARRAY_AND_SIZE(p168_dfio_grps)},
- {"nand", ARRAY_AND_SIZE(p168_nand_grps)},
- {"smc", ARRAY_AND_SIZE(p168_smc_grps)},
- {"smc cs0", ARRAY_AND_SIZE(p168_smccs0_grps)},
- {"smc cs1", ARRAY_AND_SIZE(p168_smccs1_grps)},
- {"smc rdy", ARRAY_AND_SIZE(p168_smcrdy_grps)},
- {"ac97", ARRAY_AND_SIZE(p168_ac97_grps)},
- {"ac97 sysclk", ARRAY_AND_SIZE(p168_ac97sysclk_grps)},
- {"cf", ARRAY_AND_SIZE(p168_cf_grps)},
- {"kpmkin", ARRAY_AND_SIZE(p168_kpmkin_grps)},
- {"kpmkout", ARRAY_AND_SIZE(p168_kpmkout_grps)},
- {"gpio86", ARRAY_AND_SIZE(p168_gpio86_grps)},
- {"gpio87", ARRAY_AND_SIZE(p168_gpio87_grps)},
- {"gpio88", ARRAY_AND_SIZE(p168_gpio88_grps)},
-};
-
-static struct pinctrl_desc pxa168_pctrl_desc = {
- .name = "pxa168-pinctrl",
- .owner = THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info pxa168_info = {
- .mfp = pxa168_mfp,
- .num_mfp = ARRAY_SIZE(pxa168_mfp),
- .grps = pxa168_grps,
- .num_grps = ARRAY_SIZE(pxa168_grps),
- .funcs = pxa168_funcs,
- .num_funcs = ARRAY_SIZE(pxa168_funcs),
- .num_gpio = 128,
- .desc = &pxa168_pctrl_desc,
- .pads = pxa168_pads,
- .num_pads = ARRAY_SIZE(pxa168_pads),
-
- .cputype = PINCTRL_PXA168,
- .ds_mask = PXA168_DS_MASK,
- .ds_shift = PXA168_DS_SHIFT,
-};
-
-static int pxa168_pinmux_probe(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_register(pdev, &pxa168_info);
-}
-
-static int pxa168_pinmux_remove(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver pxa168_pinmux_driver = {
- .driver = {
- .name = "pxa168-pinmux",
- .owner = THIS_MODULE,
- },
- .probe = pxa168_pinmux_probe,
- .remove = pxa168_pinmux_remove,
-};
-
-static int __init pxa168_pinmux_init(void)
-{
- return platform_driver_register(&pxa168_pinmux_driver);
-}
-core_initcall_sync(pxa168_pinmux_init);
-
-static void __exit pxa168_pinmux_exit(void)
-{
- platform_driver_unregister(&pxa168_pinmux_driver);
-}
-module_exit(pxa168_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.c b/drivers/pinctrl/pinctrl-pxa3xx.c
deleted file mode 100644
index 1f49bb0..0000000
--- a/drivers/pinctrl/pinctrl-pxa3xx.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * linux/drivers/pinctrl/pinctrl-pxa3xx.c
- *
- * 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
- * publishhed by the Free Software Foundation.
- *
- * Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include "pinctrl-pxa3xx.h"
-
-static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
- .name = "PXA3xx GPIO",
- .id = 0,
- .base = 0,
- .pin_base = 0,
-};
-
-static int pxa3xx_get_groups_count(struct pinctrl_dev *pctrldev)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
- return info->num_grps;
-}
-
-static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
- unsigned selector)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
- return info->grps[selector].name;
-}
-
-static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
- unsigned selector,
- const unsigned **pins,
- unsigned *num_pins)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
- *pins = info->grps[selector].pins;
- *num_pins = info->grps[selector].npins;
- return 0;
-}
-
-static struct pinctrl_ops pxa3xx_pctrl_ops = {
- .get_groups_count = pxa3xx_get_groups_count,
- .get_group_name = pxa3xx_get_group_name,
- .get_group_pins = pxa3xx_get_group_pins,
-};
-
-static int pxa3xx_pmx_get_funcs_count(struct pinctrl_dev *pctrldev)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
-
- return info->num_funcs;
-}
-
-static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
- unsigned func)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- return info->funcs[func].name;
-}
-
-static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
- const char * const **groups,
- unsigned * const num_groups)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- *groups = info->funcs[func].groups;
- *num_groups = info->funcs[func].num_groups;
- return 0;
-}
-
-/* Return function number. If failure, return negative value. */
-static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
-{
- int i;
- for (i = 0; i < PXA3xx_MAX_MUX; i++) {
- if (mfp->func[i] == mux)
- break;
- }
- if (i >= PXA3xx_MAX_MUX)
- return -EINVAL;
- return i;
-}
-
-/* check whether current pin configuration is valid. Negative for failure */
-static int match_group_mux(struct pxa3xx_pin_group *grp,
- struct pxa3xx_pinmux_info *info,
- unsigned mux)
-{
- int i, pin, ret = 0;
- for (i = 0; i < grp->npins; i++) {
- pin = grp->pins[i];
- ret = match_mux(&info->mfp[pin], mux);
- if (ret < 0) {
- dev_err(info->dev, "Can't find mux %d on pin%d\n",
- mux, pin);
- break;
- }
- }
- return ret;
-}
-
-static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
- unsigned group)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- struct pxa3xx_pin_group *pin_grp = &info->grps[group];
- unsigned int data;
- int i, mfpr, pin, pin_func;
-
- if (!pin_grp->npins ||
- (match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
- dev_err(info->dev, "Failed to set the pin group: %d\n", group);
- return -EINVAL;
- }
- for (i = 0; i < pin_grp->npins; i++) {
- pin = pin_grp->pins[i];
- pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
- mfpr = info->mfp[pin].mfpr;
- data = readl_relaxed(info->virt_base + mfpr);
- data &= ~MFPR_FUNC_MASK;
- data |= pin_func;
- writel_relaxed(data, info->virt_base + mfpr);
- }
- return 0;
-}
-
-static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
- struct pinctrl_gpio_range *range,
- unsigned pin)
-{
- struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
- unsigned int data;
- int pin_func, mfpr;
-
- pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
- if (pin_func < 0) {
- dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
- pin, info->pads[pin].name);
- return -EINVAL;
- }
- mfpr = info->mfp[pin].mfpr;
- /* write gpio function into mfpr register */
- data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
- data |= pin_func;
- writel_relaxed(data, info->virt_base + mfpr);
- return 0;
-}
-
-static struct pinmux_ops pxa3xx_pmx_ops = {
- .get_functions_count = pxa3xx_pmx_get_funcs_count,
- .get_function_name = pxa3xx_pmx_get_func_name,
- .get_function_groups = pxa3xx_pmx_get_groups,
- .enable = pxa3xx_pmx_enable,
- .gpio_request_enable = pxa3xx_pmx_request_gpio,
-};
-
-int pxa3xx_pinctrl_register(struct platform_device *pdev,
- struct pxa3xx_pinmux_info *info)
-{
- struct pinctrl_desc *desc;
- struct resource *res;
-
- if (!info || !info->cputype)
- return -EINVAL;
- desc = info->desc;
- desc->pins = info->pads;
- desc->npins = info->num_pads;
- desc->pctlops = &pxa3xx_pctrl_ops;
- desc->pmxops = &pxa3xx_pmx_ops;
- info->dev = &pdev->dev;
- pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENOENT;
- info->virt_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(info->virt_base))
- return PTR_ERR(info->virt_base);
- info->pctrl = pinctrl_register(desc, &pdev->dev, info);
- if (!info->pctrl) {
- dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
- return -EINVAL;
- }
- pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
- platform_set_drvdata(pdev, info);
- return 0;
-}
-
-int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
-{
- struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
-
- pinctrl_unregister(info->pctrl);
- platform_set_drvdata(pdev, NULL);
- return 0;
-}
-
-static int __init pxa3xx_pinctrl_init(void)
-{
- pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
- return 0;
-}
-core_initcall_sync(pxa3xx_pinctrl_init);
-
-static void __exit pxa3xx_pinctrl_exit(void)
-{
-}
-module_exit(pxa3xx_pinctrl_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-pxa3xx.h b/drivers/pinctrl/pinctrl-pxa3xx.h
deleted file mode 100644
index 92fad08..0000000
--- a/drivers/pinctrl/pinctrl-pxa3xx.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * linux/drivers/pinctrl/pinctrl-pxa3xx.h
- *
- * 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
- * publishhed by the Free Software Foundation.
- *
- * Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#ifndef __PINCTRL_PXA3XX_H
-
-#include <linux/pinctrl/pinctrl.h>
-#include <linux/pinctrl/pinmux.h>
-
-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
-
-#define PXA3xx_MUX_GPIO 0
-
-#define PXA3xx_MAX_MUX 8
-#define MFPR_FUNC_MASK 0x7
-
-enum pxa_cpu_type {
- PINCTRL_INVALID = 0,
- PINCTRL_PXA300,
- PINCTRL_PXA310,
- PINCTRL_PXA320,
- PINCTRL_PXA168,
- PINCTRL_PXA910,
- PINCTRL_PXA930,
- PINCTRL_PXA955,
- PINCTRL_MMP2,
- PINCTRL_MAX,
-};
-
-struct pxa3xx_mfp_pin {
- const char *name;
- const unsigned int pin;
- const unsigned int mfpr; /* register offset */
- const unsigned short func[8];
-};
-
-struct pxa3xx_pin_group {
- const char *name;
- const unsigned mux;
- const unsigned *pins;
- const unsigned npins;
-};
-
-struct pxa3xx_pmx_func {
- const char *name;
- const char * const * groups;
- const unsigned num_groups;
-};
-
-struct pxa3xx_pinmux_info {
- struct device *dev;
- struct pinctrl_dev *pctrl;
- enum pxa_cpu_type cputype;
- void __iomem *virt_base;
-
- struct pxa3xx_mfp_pin *mfp;
- unsigned int num_mfp;
- struct pxa3xx_pin_group *grps;
- unsigned int num_grps;
- struct pxa3xx_pmx_func *funcs;
- unsigned int num_funcs;
- unsigned int num_gpio;
- struct pinctrl_desc *desc;
- struct pinctrl_pin_desc *pads;
- unsigned int num_pads;
-
- unsigned ds_mask; /* drive strength mask */
- unsigned ds_shift; /* drive strength shift */
- unsigned slp_mask; /* sleep mask */
- unsigned slp_input_low;
- unsigned slp_input_high;
- unsigned slp_output_low;
- unsigned slp_output_high;
- unsigned slp_float;
-};
-
-enum pxa3xx_pin_list {
- GPIO0 = 0,
- GPIO1,
- GPIO2,
- GPIO3,
- GPIO4,
- GPIO5,
- GPIO6,
- GPIO7,
- GPIO8,
- GPIO9,
- GPIO10, /* 10 */
- GPIO11,
- GPIO12,
- GPIO13,
- GPIO14,
- GPIO15,
- GPIO16,
- GPIO17,
- GPIO18,
- GPIO19,
- GPIO20, /* 20 */
- GPIO21,
- GPIO22,
- GPIO23,
- GPIO24,
- GPIO25,
- GPIO26,
- GPIO27,
- GPIO28,
- GPIO29,
- GPIO30, /* 30 */
- GPIO31,
- GPIO32,
- GPIO33,
- GPIO34,
- GPIO35,
- GPIO36,
- GPIO37,
- GPIO38,
- GPIO39,
- GPIO40, /* 40 */
- GPIO41,
- GPIO42,
- GPIO43,
- GPIO44,
- GPIO45,
- GPIO46,
- GPIO47,
- GPIO48,
- GPIO49,
- GPIO50, /* 50 */
- GPIO51,
- GPIO52,
- GPIO53,
- GPIO54,
- GPIO55,
- GPIO56,
- GPIO57,
- GPIO58,
- GPIO59,
- GPIO60, /* 60 */
- GPIO61,
- GPIO62,
- GPIO63,
- GPIO64,
- GPIO65,
- GPIO66,
- GPIO67,
- GPIO68,
- GPIO69,
- GPIO70, /* 70 */
- GPIO71,
- GPIO72,
- GPIO73,
- GPIO74,
- GPIO75,
- GPIO76,
- GPIO77,
- GPIO78,
- GPIO79,
- GPIO80, /* 80 */
- GPIO81,
- GPIO82,
- GPIO83,
- GPIO84,
- GPIO85,
- GPIO86,
- GPIO87,
- GPIO88,
- GPIO89,
- GPIO90, /* 90 */
- GPIO91,
- GPIO92,
- GPIO93,
- GPIO94,
- GPIO95,
- GPIO96,
- GPIO97,
- GPIO98,
- GPIO99,
- GPIO100, /* 100 */
- GPIO101,
- GPIO102,
- GPIO103,
- GPIO104,
- GPIO105,
- GPIO106,
- GPIO107,
- GPIO108,
- GPIO109,
- GPIO110, /* 110 */
- GPIO111,
- GPIO112,
- GPIO113,
- GPIO114,
- GPIO115,
- GPIO116,
- GPIO117,
- GPIO118,
- GPIO119,
- GPIO120, /* 120 */
- GPIO121,
- GPIO122,
- GPIO123,
- GPIO124,
- GPIO125,
- GPIO126,
- GPIO127,
- GPIO128,
- GPIO129,
- GPIO130, /* 130 */
- GPIO131,
- GPIO132,
- GPIO133,
- GPIO134,
- GPIO135,
- GPIO136,
- GPIO137,
- GPIO138,
- GPIO139,
- GPIO140, /* 140 */
- GPIO141,
- GPIO142,
- GPIO143,
- GPIO144,
- GPIO145,
- GPIO146,
- GPIO147,
- GPIO148,
- GPIO149,
- GPIO150, /* 150 */
- GPIO151,
- GPIO152,
- GPIO153,
- GPIO154,
- GPIO155,
- GPIO156,
- GPIO157,
- GPIO158,
- GPIO159,
- GPIO160, /* 160 */
- GPIO161,
- GPIO162,
- GPIO163,
- GPIO164,
- GPIO165,
- GPIO166,
- GPIO167,
- GPIO168,
- GPIO169,
-};
-
-extern int pxa3xx_pinctrl_register(struct platform_device *pdev,
- struct pxa3xx_pinmux_info *info);
-extern int pxa3xx_pinctrl_unregister(struct platform_device *pdev);
-#endif /* __PINCTRL_PXA3XX_H */
diff --git a/drivers/pinctrl/pinctrl-pxa910.c b/drivers/pinctrl/pinctrl-pxa910.c
deleted file mode 100644
index a2f917b..0000000
--- a/drivers/pinctrl/pinctrl-pxa910.c
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * linux/drivers/pinctrl/pinmux-pxa910.c
- *
- * 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
- * publishhed by the Free Software Foundation.
- *
- * Copyright (C) 2011, Marvell Technology Group Ltd.
- *
- * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
- *
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include "pinctrl-pxa3xx.h"
-
-#define PXA910_DS_MASK 0x1800
-#define PXA910_DS_SHIFT 11
-#define PXA910_SLEEP_MASK 0x38
-#define PXA910_SLEEP_SELECT (1 << 9)
-#define PXA910_SLEEP_DATA (1 << 8)
-#define PXA910_SLEEP_DIR (1 << 7)
-
-#define MFPR_910(a, r, f0, f1, f2, f3, f4, f5, f6, f7) \
- { \
- .name = #a, \
- .pin = a, \
- .mfpr = r, \
- .func = { \
- PXA910_MUX_##f0, \
- PXA910_MUX_##f1, \
- PXA910_MUX_##f2, \
- PXA910_MUX_##f3, \
- PXA910_MUX_##f4, \
- PXA910_MUX_##f5, \
- PXA910_MUX_##f6, \
- PXA910_MUX_##f7, \
- }, \
- }
-
-#define GRP_910(a, m, p) \
- { .name = a, .mux = PXA910_MUX_##m, .pins = p, .npins = ARRAY_SIZE(p), }
-
-/* 170 pins */
-enum pxa910_pin_list {
- /* 0~127: GPIO0~GPIO127 */
- ND_IO15 = 128,
- ND_IO14,
- ND_IO13, /* 130 */
- ND_IO12,
- ND_IO11,
- ND_IO10,
- ND_IO9,
- ND_IO8,
- ND_IO7,
- ND_IO6,
- ND_IO5,
- ND_IO4,
- ND_IO3, /* 140 */
- ND_IO2,
- ND_IO1,
- ND_IO0,
- ND_NCS0,
- ND_NCS1,
- SM_NCS0,
- SM_NCS1,
- ND_NWE,
- ND_NRE,
- ND_CLE, /* 150 */
- ND_ALE,
- SM_SCLK,
- ND_RDY0,
- SM_ADV,
- ND_RDY1,
- SM_ADVMUX,
- SM_RDY,
- MMC1_DAT7,
- MMC1_DAT6,
- MMC1_DAT5, /* 160 */
- MMC1_DAT4,
- MMC1_DAT3,
- MMC1_DAT2,
- MMC1_DAT1,
- MMC1_DAT0,
- MMC1_CMD,
- MMC1_CLK,
- MMC1_CD,
- VCXO_OUT,
-};
-
-enum pxa910_mux {
- /* PXA3xx_MUX_GPIO = 0 (predefined in pinctrl-pxa3xx.h) */
- PXA910_MUX_GPIO = 0,
- PXA910_MUX_NAND,
- PXA910_MUX_USIM2,
- PXA910_MUX_EXT_DMA,
- PXA910_MUX_EXT_INT,
- PXA910_MUX_MMC1,
- PXA910_MUX_MMC2,
- PXA910_MUX_MMC3,
- PXA910_MUX_SM_INT,
- PXA910_MUX_PRI_JTAG,
- PXA910_MUX_SEC1_JTAG,
- PXA910_MUX_SEC2_JTAG,
- PXA910_MUX_RESET, /* SLAVE RESET OUT */
- PXA910_MUX_CLK_REQ,
- PXA910_MUX_VCXO_REQ,
- PXA910_MUX_VCXO_OUT,
- PXA910_MUX_VCXO_REQ2,
- PXA910_MUX_VCXO_OUT2,
- PXA910_MUX_SPI,
- PXA910_MUX_SPI2,
- PXA910_MUX_GSSP,
- PXA910_MUX_SSP0,
- PXA910_MUX_SSP1,
- PXA910_MUX_SSP2,
- PXA910_MUX_DSSP2,
- PXA910_MUX_DSSP3,
- PXA910_MUX_UART0,
- PXA910_MUX_UART1,
- PXA910_MUX_UART2,
- PXA910_MUX_TWSI,
- PXA910_MUX_CCIC,
- PXA910_MUX_PWM0,
- PXA910_MUX_PWM1,
- PXA910_MUX_PWM2,
- PXA910_MUX_PWM3,
- PXA910_MUX_HSL,
- PXA910_MUX_ONE_WIRE,
- PXA910_MUX_LCD,
- PXA910_MUX_DAC_ST23,
- PXA910_MUX_ULPI,
- PXA910_MUX_TB,
- PXA910_MUX_KP_MK,
- PXA910_MUX_KP_DK,
- PXA910_MUX_TCU_GPOA,
- PXA910_MUX_TCU_GPOB,
- PXA910_MUX_ROT,
- PXA910_MUX_TDS,
- PXA910_MUX_32K_CLK, /* 32KHz CLK OUT */
- PXA910_MUX_MN_CLK, /* MN CLK OUT */
- PXA910_MUX_SMC,
- PXA910_MUX_SM_ADDR18,
- PXA910_MUX_SM_ADDR19,
- PXA910_MUX_SM_ADDR20,
- PXA910_MUX_NONE = 0xffff,
-};
-
-
-static struct pinctrl_pin_desc pxa910_pads[] = {
- PINCTRL_PIN(GPIO0, "GPIO0"),
- PINCTRL_PIN(GPIO1, "GPIO1"),
- PINCTRL_PIN(GPIO2, "GPIO2"),
- PINCTRL_PIN(GPIO3, "GPIO3"),
- PINCTRL_PIN(GPIO4, "GPIO4"),
- PINCTRL_PIN(GPIO5, "GPIO5"),
- PINCTRL_PIN(GPIO6, "GPIO6"),
- PINCTRL_PIN(GPIO7, "GPIO7"),
- PINCTRL_PIN(GPIO8, "GPIO8"),
- PINCTRL_PIN(GPIO9, "GPIO9"),
- PINCTRL_PIN(GPIO10, "GPIO10"),
- PINCTRL_PIN(GPIO11, "GPIO11"),
- PINCTRL_PIN(GPIO12, "GPIO12"),
- PINCTRL_PIN(GPIO13, "GPIO13"),
- PINCTRL_PIN(GPIO14, "GPIO14"),
- PINCTRL_PIN(GPIO15, "GPIO15"),
- PINCTRL_PIN(GPIO16, "GPIO16"),
- PINCTRL_PIN(GPIO17, "GPIO17"),
- PINCTRL_PIN(GPIO18, "GPIO18"),
- PINCTRL_PIN(GPIO19, "GPIO19"),
- PINCTRL_PIN(GPIO20, "GPIO20"),
- PINCTRL_PIN(GPIO21, "GPIO21"),
- PINCTRL_PIN(GPIO22, "GPIO22"),
- PINCTRL_PIN(GPIO23, "GPIO23"),
- PINCTRL_PIN(GPIO24, "GPIO24"),
- PINCTRL_PIN(GPIO25, "GPIO25"),
- PINCTRL_PIN(GPIO26, "GPIO26"),
- PINCTRL_PIN(GPIO27, "GPIO27"),
- PINCTRL_PIN(GPIO28, "GPIO28"),
- PINCTRL_PIN(GPIO29, "GPIO29"),
- PINCTRL_PIN(GPIO30, "GPIO30"),
- PINCTRL_PIN(GPIO31, "GPIO31"),
- PINCTRL_PIN(GPIO32, "GPIO32"),
- PINCTRL_PIN(GPIO33, "GPIO33"),
- PINCTRL_PIN(GPIO34, "GPIO34"),
- PINCTRL_PIN(GPIO35, "GPIO35"),
- PINCTRL_PIN(GPIO36, "GPIO36"),
- PINCTRL_PIN(GPIO37, "GPIO37"),
- PINCTRL_PIN(GPIO38, "GPIO38"),
- PINCTRL_PIN(GPIO39, "GPIO39"),
- PINCTRL_PIN(GPIO40, "GPIO40"),
- PINCTRL_PIN(GPIO41, "GPIO41"),
- PINCTRL_PIN(GPIO42, "GPIO42"),
- PINCTRL_PIN(GPIO43, "GPIO43"),
- PINCTRL_PIN(GPIO44, "GPIO44"),
- PINCTRL_PIN(GPIO45, "GPIO45"),
- PINCTRL_PIN(GPIO46, "GPIO46"),
- PINCTRL_PIN(GPIO47, "GPIO47"),
- PINCTRL_PIN(GPIO48, "GPIO48"),
- PINCTRL_PIN(GPIO49, "GPIO49"),
- PINCTRL_PIN(GPIO50, "GPIO50"),
- PINCTRL_PIN(GPIO51, "GPIO51"),
- PINCTRL_PIN(GPIO52, "GPIO52"),
- PINCTRL_PIN(GPIO53, "GPIO53"),
- PINCTRL_PIN(GPIO54, "GPIO54"),
- PINCTRL_PIN(GPIO55, "GPIO55"),
- PINCTRL_PIN(GPIO56, "GPIO56"),
- PINCTRL_PIN(GPIO57, "GPIO57"),
- PINCTRL_PIN(GPIO58, "GPIO58"),
- PINCTRL_PIN(GPIO59, "GPIO59"),
- PINCTRL_PIN(GPIO60, "GPIO60"),
- PINCTRL_PIN(GPIO61, "GPIO61"),
- PINCTRL_PIN(GPIO62, "GPIO62"),
- PINCTRL_PIN(GPIO63, "GPIO63"),
- PINCTRL_PIN(GPIO64, "GPIO64"),
- PINCTRL_PIN(GPIO65, "GPIO65"),
- PINCTRL_PIN(GPIO66, "GPIO66"),
- PINCTRL_PIN(GPIO67, "GPIO67"),
- PINCTRL_PIN(GPIO68, "GPIO68"),
- PINCTRL_PIN(GPIO69, "GPIO69"),
- PINCTRL_PIN(GPIO70, "GPIO70"),
- PINCTRL_PIN(GPIO71, "GPIO71"),
- PINCTRL_PIN(GPIO72, "GPIO72"),
- PINCTRL_PIN(GPIO73, "GPIO73"),
- PINCTRL_PIN(GPIO74, "GPIO74"),
- PINCTRL_PIN(GPIO75, "GPIO75"),
- PINCTRL_PIN(GPIO76, "GPIO76"),
- PINCTRL_PIN(GPIO77, "GPIO77"),
- PINCTRL_PIN(GPIO78, "GPIO78"),
- PINCTRL_PIN(GPIO79, "GPIO79"),
- PINCTRL_PIN(GPIO80, "GPIO80"),
- PINCTRL_PIN(GPIO81, "GPIO81"),
- PINCTRL_PIN(GPIO82, "GPIO82"),
- PINCTRL_PIN(GPIO83, "GPIO83"),
- PINCTRL_PIN(GPIO84, "GPIO84"),
- PINCTRL_PIN(GPIO85, "GPIO85"),
- PINCTRL_PIN(GPIO86, "GPIO86"),
- PINCTRL_PIN(GPIO87, "GPIO87"),
- PINCTRL_PIN(GPIO88, "GPIO88"),
- PINCTRL_PIN(GPIO89, "GPIO89"),
- PINCTRL_PIN(GPIO90, "GPIO90"),
- PINCTRL_PIN(GPIO91, "GPIO91"),
- PINCTRL_PIN(GPIO92, "GPIO92"),
- PINCTRL_PIN(GPIO93, "GPIO93"),
- PINCTRL_PIN(GPIO94, "GPIO94"),
- PINCTRL_PIN(GPIO95, "GPIO95"),
- PINCTRL_PIN(GPIO96, "GPIO96"),
- PINCTRL_PIN(GPIO97, "GPIO97"),
- PINCTRL_PIN(GPIO98, "GPIO98"),
- PINCTRL_PIN(GPIO99, "GPIO99"),
- PINCTRL_PIN(GPIO100, "GPIO100"),
- PINCTRL_PIN(GPIO101, "GPIO101"),
- PINCTRL_PIN(GPIO102, "GPIO102"),
- PINCTRL_PIN(GPIO103, "GPIO103"),
- PINCTRL_PIN(GPIO104, "GPIO104"),
- PINCTRL_PIN(GPIO105, "GPIO105"),
- PINCTRL_PIN(GPIO106, "GPIO106"),
- PINCTRL_PIN(GPIO107, "GPIO107"),
- PINCTRL_PIN(GPIO108, "GPIO108"),
- PINCTRL_PIN(GPIO109, "GPIO109"),
- PINCTRL_PIN(GPIO110, "GPIO110"),
- PINCTRL_PIN(GPIO111, "GPIO111"),
- PINCTRL_PIN(GPIO112, "GPIO112"),
- PINCTRL_PIN(GPIO113, "GPIO113"),
- PINCTRL_PIN(GPIO114, "GPIO114"),
- PINCTRL_PIN(GPIO115, "GPIO115"),
- PINCTRL_PIN(GPIO116, "GPIO116"),
- PINCTRL_PIN(GPIO117, "GPIO117"),
- PINCTRL_PIN(GPIO118, "GPIO118"),
- PINCTRL_PIN(GPIO119, "GPIO119"),
- PINCTRL_PIN(GPIO120, "GPIO120"),
- PINCTRL_PIN(GPIO121, "GPIO121"),
- PINCTRL_PIN(GPIO122, "GPIO122"),
- PINCTRL_PIN(GPIO123, "GPIO123"),
- PINCTRL_PIN(GPIO124, "GPIO124"),
- PINCTRL_PIN(GPIO125, "GPIO125"),
- PINCTRL_PIN(GPIO126, "GPIO126"),
- PINCTRL_PIN(GPIO127, "GPIO127"),
- PINCTRL_PIN(ND_IO15, "ND_IO15"),
- PINCTRL_PIN(ND_IO14, "ND_IO14"),
- PINCTRL_PIN(ND_IO13, "ND_IO13"),
- PINCTRL_PIN(ND_IO12, "ND_IO12"),
- PINCTRL_PIN(ND_IO11, "ND_IO11"),
- PINCTRL_PIN(ND_IO10, "ND_IO10"),
- PINCTRL_PIN(ND_IO9, "ND_IO9"),
- PINCTRL_PIN(ND_IO8, "ND_IO8"),
- PINCTRL_PIN(ND_IO7, "ND_IO7"),
- PINCTRL_PIN(ND_IO6, "ND_IO6"),
- PINCTRL_PIN(ND_IO5, "ND_IO5"),
- PINCTRL_PIN(ND_IO4, "ND_IO4"),
- PINCTRL_PIN(ND_IO3, "ND_IO3"),
- PINCTRL_PIN(ND_IO2, "ND_IO2"),
- PINCTRL_PIN(ND_IO1, "ND_IO1"),
- PINCTRL_PIN(ND_IO0, "ND_IO0"),
- PINCTRL_PIN(ND_NCS0, "ND_NCS0_SM_NCS2"),
- PINCTRL_PIN(ND_NCS1, "ND_NCS1_SM_NCS3"),
- PINCTRL_PIN(SM_NCS0, "SM_NCS0"),
- PINCTRL_PIN(SM_NCS1, "SM_NCS1"),
- PINCTRL_PIN(ND_NWE, "ND_NWE"),
- PINCTRL_PIN(ND_NRE, "ND_NRE"),
- PINCTRL_PIN(ND_CLE, "ND_CLE_SM_NOE"),
- PINCTRL_PIN(ND_ALE, "ND_ALE_SM_NWE"),
- PINCTRL_PIN(SM_SCLK, "SM_SCLK"),
- PINCTRL_PIN(ND_RDY0, "ND_RDY0"),
- PINCTRL_PIN(SM_ADV, "SM_ADV"),
- PINCTRL_PIN(ND_RDY1, "ND_RDY1"),
- PINCTRL_PIN(SM_RDY, "SM_RDY"),
- PINCTRL_PIN(MMC1_DAT7, "MMC1_DAT7"),
- PINCTRL_PIN(MMC1_DAT6, "MMC1_DAT6"),
- PINCTRL_PIN(MMC1_DAT5, "MMC1_DAT5"),
- PINCTRL_PIN(MMC1_DAT4, "MMC1_DAT4"),
- PINCTRL_PIN(MMC1_DAT3, "MMC1_DAT3"),
- PINCTRL_PIN(MMC1_DAT2, "MMC1_DAT2"),
- PINCTRL_PIN(MMC1_DAT1, "MMC1_DAT1"),
- PINCTRL_PIN(MMC1_DAT0, "MMC1_DAT0"),
- PINCTRL_PIN(MMC1_CMD, "MMC1 CMD"),
- PINCTRL_PIN(MMC1_CLK, "MMC1 CLK"),
- PINCTRL_PIN(MMC1_CD, "MMC1 CD"),
- PINCTRL_PIN(VCXO_OUT, "VCXO_OUT"),
-};
-
-struct pxa3xx_mfp_pin pxa910_mfp[] = {
- /* pin offs f0 f1 f2 f3 f4 f5 f6 f7 */
- MFPR_910(GPIO0, 0x0DC, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO1, 0x0E0, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO2, 0x0E4, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO3, 0x0E8, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO4, 0x0EC, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO5, 0x0F0, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO6, 0x0F4, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO7, 0x0F8, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO8, 0x0FC, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO9, 0x100, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO10, 0x104, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO11, 0x108, GPIO, KP_MK, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO12, 0x10C, GPIO, KP_MK, NONE, NONE, KP_DK, NONE, NONE, NONE),
- MFPR_910(GPIO13, 0x110, GPIO, KP_MK, NONE, NONE, KP_DK, NONE, NONE, NONE),
- MFPR_910(GPIO14, 0x114, GPIO, KP_MK, NONE, NONE, KP_DK, TB, NONE, NONE),
- MFPR_910(GPIO15, 0x118, GPIO, KP_MK, NONE, NONE, KP_DK, TB, NONE, NONE),
- MFPR_910(GPIO16, 0x11C, GPIO, KP_DK, NONE, NONE, NONE, TB, NONE, NONE),
- MFPR_910(GPIO17, 0x120, GPIO, KP_DK, NONE, NONE, NONE, TB, NONE, NONE),
- MFPR_910(GPIO18, 0x124, GPIO, KP_DK, NONE, NONE, ROT, NONE, NONE, NONE),
- MFPR_910(GPIO19, 0x128, GPIO, KP_DK, NONE, NONE, ROT, NONE, NONE, NONE),
- MFPR_910(GPIO20, 0x12C, GPIO, SSP1, NONE, NONE, VCXO_OUT, NONE, NONE, NONE),
- MFPR_910(GPIO21, 0x130, GPIO, SSP1, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO22, 0x134, GPIO, SSP1, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO23, 0x138, GPIO, SSP1, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO24, 0x13C, GPIO, SSP1, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO25, 0x140, GPIO, GSSP, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO26, 0x144, GPIO, GSSP, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO27, 0x148, GPIO, GSSP, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO28, 0x14C, GPIO, GSSP, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO29, 0x150, GPIO, UART0, NONE, NONE, UART1, NONE, NONE, NONE),
- MFPR_910(GPIO30, 0x154, GPIO, UART0, NONE, NONE, UART1, NONE, NONE, NONE),
- MFPR_910(GPIO31, 0x158, GPIO, UART0, NONE, NONE, UART1, NONE, NONE, NONE),
- MFPR_910(GPIO32, 0x15C, GPIO, UART0, DAC_ST23, NONE, UART1, NONE, NONE, NONE),
- MFPR_910(GPIO33, 0x160, GPIO, MMC2, SSP0, SSP2, NONE, SPI, NONE, MMC3),
- MFPR_910(GPIO34, 0x164, GPIO, MMC2, SSP0, SSP2, NONE, SPI, NONE, MMC3),
- MFPR_910(GPIO35, 0x168, GPIO, MMC2, SSP0, SSP2, NONE, SPI, NONE, MMC3),
- MFPR_910(GPIO36, 0x16C, GPIO, MMC2, SSP0, SSP2, NONE, SPI, NONE, MMC3),
- MFPR_910(GPIO37, 0x170, GPIO, MMC2, NONE, NONE, NONE, SPI, HSL, NONE),
- MFPR_910(GPIO38, 0x174, GPIO, MMC2, NONE, NONE, NONE, NONE, HSL, NONE),
- MFPR_910(GPIO39, 0x178, GPIO, MMC2, NONE, NONE, NONE, NONE, HSL, NONE),
- MFPR_910(GPIO40, 0x17C, GPIO, MMC2, NONE, NONE, NONE, NONE, HSL, NONE),
- MFPR_910(GPIO41, 0x180, GPIO, MMC2, NONE, NONE, NONE, NONE, HSL, NONE),
- MFPR_910(GPIO42, 0x184, GPIO, MMC2, NONE, NONE, NONE, NONE, HSL, NONE),
- MFPR_910(GPIO43, 0x188, GPIO, UART1, NONE, DAC_ST23, NONE, DSSP2, SPI, UART2),
- MFPR_910(GPIO44, 0x18C, GPIO, UART1, NONE, EXT_INT, NONE, DSSP2, SPI, UART2),
- MFPR_910(GPIO45, 0x190, GPIO, UART1, NONE, EXT_INT, NONE, DSSP2, SPI, UART2),
- MFPR_910(GPIO46, 0x194, GPIO, UART1, NONE, EXT_INT, NONE, DSSP2, SPI, UART2),
- MFPR_910(GPIO47, 0x198, GPIO, SSP0, NONE, NONE, NONE, SSP2, UART1, NONE),
- MFPR_910(GPIO48, 0x19C, GPIO, SSP0, NONE, NONE, NONE, SSP2, UART1, NONE),
- MFPR_910(GPIO49, 0x1A0, GPIO, SSP0, UART0, VCXO_REQ, NONE, SSP2, NONE, MMC3),
- MFPR_910(GPIO50, 0x1A4, GPIO, SSP0, UART0, VCXO_OUT, NONE, SSP2, NONE, MMC3),
- MFPR_910(GPIO51, 0x1A8, GPIO, UART2, PWM1, TWSI, SSP0, NONE, DSSP3, NONE),
- MFPR_910(GPIO52, 0x1AC, GPIO, UART2, DAC_ST23, TWSI, SSP0, NONE, DSSP3, NONE),
- MFPR_910(GPIO53, 0x1B0, GPIO, UART2, TWSI, NONE, SSP0, NONE, DSSP3, NONE),
- MFPR_910(GPIO54, 0x1B4, GPIO, UART2, TWSI, SSP0, NONE, NONE, DSSP3, NONE),
- MFPR_910(GPIO55, 0x2F0, TDS, GPIO, TB, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO56, 0x2F4, TDS, GPIO, TB, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO57, 0x2F8, TDS, GPIO, TB, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO58, 0x2FC, TDS, GPIO, TB, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO59, 0x300, TDS, GPIO, TCU_GPOA, TCU_GPOB, ONE_WIRE, NONE, NONE, NONE),
- MFPR_910(GPIO60, 0x304, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO61, 0x308, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, HSL),
- MFPR_910(GPIO62, 0x30C, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, HSL),
- MFPR_910(GPIO63, 0x310, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, HSL),
- MFPR_910(GPIO64, 0x314, GPIO, SPI2, NONE, NONE, NONE, NONE, NONE, HSL),
- MFPR_910(GPIO65, 0x318, GPIO, SPI2, NONE, NONE, NONE, NONE, ONE_WIRE, HSL),
- MFPR_910(GPIO66, 0x31C, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, HSL),
- MFPR_910(GPIO67, 0x1B8, GPIO, CCIC, SPI, NONE, NONE, ULPI, NONE, USIM2),
- MFPR_910(GPIO68, 0x1BC, GPIO, CCIC, SPI, NONE, NONE, ULPI, NONE, USIM2),
- MFPR_910(GPIO69, 0x1C0, GPIO, CCIC, SPI, NONE, NONE, ULPI, NONE, USIM2),
- MFPR_910(GPIO70, 0x1C4, GPIO, CCIC, SPI, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO71, 0x1C8, GPIO, CCIC, SPI, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO72, 0x1CC, GPIO, CCIC, EXT_DMA, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO73, 0x1D0, GPIO, CCIC, EXT_DMA, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO74, 0x1D4, GPIO, CCIC, EXT_DMA, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO75, 0x1D8, GPIO, CCIC, NONE, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO76, 0x1DC, GPIO, CCIC, NONE, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO77, 0x1E0, GPIO, CCIC, NONE, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO78, 0x1E4, GPIO, CCIC, NONE, NONE, NONE, ULPI, NONE, NONE),
- MFPR_910(GPIO79, 0x1E8, GPIO, TWSI, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO80, 0x1EC, GPIO, TWSI, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO81, 0x1F0, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO82, 0x1F4, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO83, 0x1F8, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO84, 0x1FC, GPIO, LCD, VCXO_REQ2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO85, 0x200, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO86, 0x204, GPIO, LCD, VCXO_OUT2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO87, 0x208, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO88, 0x20C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO89, 0x210, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO90, 0x214, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO91, 0x218, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO92, 0x21C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO93, 0x220, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO94, 0x224, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO95, 0x228, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO96, 0x22C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO97, 0x230, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO98, 0x234, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO99, 0x0B0, MMC1, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO100, 0x238, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO101, 0x23C, GPIO, LCD, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO102, 0x240, GPIO, LCD, DSSP2, SPI, NONE, NONE, NONE, SPI2),
- MFPR_910(GPIO103, 0x244, GPIO, LCD, DSSP2, SPI, NONE, NONE, NONE, SPI2),
- MFPR_910(GPIO104, 0x248, GPIO, LCD, DSSP2, SPI, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO105, 0x24C, GPIO, LCD, DSSP2, SPI, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO106, 0x250, GPIO, LCD, DSSP3, ONE_WIRE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO107, 0x254, GPIO, LCD, DSSP3, SPI, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO108, 0x258, GPIO, LCD, DSSP3, SPI, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO109, 0x25C, GPIO, LCD, DSSP3, SPI, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO110, 0x298, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO111, 0x29C, GPIO, NONE, DSSP2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO112, 0x2A0, GPIO, NONE, DSSP2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO113, 0x2A4, GPIO, NONE, DSSP2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO114, 0x2A8, GPIO, NONE, DSSP3, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO115, 0x2AC, GPIO, NONE, DSSP3, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO116, 0x2B0, GPIO, NONE, DSSP3, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO117, 0x0B4, PRI_JTAG, GPIO, PWM0, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO118, 0x0B8, PRI_JTAG, GPIO, PWM1, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO119, 0x0BC, PRI_JTAG, GPIO, PWM2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO120, 0x0C0, PRI_JTAG, GPIO, PWM3, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO121, 0x32C, GPIO, NONE, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO122, 0x0C8, RESET, GPIO, 32K_CLK, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO123, 0x0CC, CLK_REQ, GPIO, ONE_WIRE, EXT_DMA, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO124, 0x0D0, GPIO, MN_CLK, DAC_ST23, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO125, 0x0D4, VCXO_REQ, GPIO, NONE, EXT_INT, NONE, NONE, NONE, NONE),
- MFPR_910(GPIO126, 0x06C, GPIO, SMC, NONE, SM_ADDR18, NONE, EXT_DMA, NONE, NONE),
- MFPR_910(GPIO127, 0x070, GPIO, SMC, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO15, 0x004, NAND, GPIO, USIM2, EXT_DMA, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO14, 0x008, NAND, GPIO, USIM2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO13, 0x00C, NAND, GPIO, USIM2, EXT_INT, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO12, 0x010, NAND, GPIO, SSP2, EXT_INT, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO11, 0x014, NAND, GPIO, SSP2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO10, 0x018, NAND, GPIO, SSP2, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO9, 0x01C, NAND, GPIO, SSP2, NONE, VCXO_OUT2, NONE, NONE, NONE),
- MFPR_910(ND_IO8, 0x020, NAND, GPIO, NONE, NONE, PWM3, NONE, NONE, NONE),
- MFPR_910(ND_IO7, 0x024, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO6, 0x028, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO5, 0x02C, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO4, 0x030, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO3, 0x034, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO2, 0x038, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO1, 0x03C, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_IO0, 0x040, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_NCS0, 0x044, NAND, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_NCS1, 0x048, NAND, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(SM_NCS0, 0x04C, SMC, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(SM_NCS1, 0x050, SMC, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_NWE, 0x054, GPIO, NAND, NONE, SM_ADDR20, NONE, SMC, NONE, NONE),
- MFPR_910(ND_NRE, 0x058, GPIO, NAND, NONE, SMC, NONE, EXT_DMA, NONE, NONE),
- MFPR_910(ND_CLE, 0x05C, NAND, MMC3, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_ALE, 0x060, GPIO, NAND, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(SM_SCLK, 0x064, MMC3, NONE, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_RDY0, 0x068, NAND, GPIO, NONE, SMC, NONE, NONE, NONE, NONE),
- MFPR_910(SM_ADV, 0x074, SMC, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(ND_RDY1, 0x078, NAND, GPIO, NONE, SMC, NONE, NONE, NONE, NONE),
- MFPR_910(SM_ADVMUX, 0x07C, SMC, GPIO, NONE, SM_ADDR19, NONE, NONE, NONE, NONE),
- MFPR_910(SM_RDY, 0x080, SMC, GPIO, NONE, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT7, 0x084, MMC1, GPIO, SEC1_JTAG, TB, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT6, 0x088, MMC1, GPIO, SEC1_JTAG, TB, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT5, 0x08C, MMC1, GPIO, SEC1_JTAG, TB, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT4, 0x090, MMC1, GPIO, NONE, TB, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT3, 0x094, MMC1, HSL, SEC2_JTAG, SSP0, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT2, 0x098, MMC1, HSL, SEC2_JTAG, SSP2, SSP0, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT1, 0x09C, MMC1, HSL, SEC2_JTAG, SSP2, SSP0, NONE, NONE, NONE),
- MFPR_910(MMC1_DAT0, 0x0A0, MMC1, HSL, SEC2_JTAG, SSP2, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_CMD, 0x0A4, MMC1, HSL, SEC1_JTAG, SSP2, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_CLK, 0x0A8, MMC1, HSL, SEC2_JTAG, SSP0, NONE, NONE, NONE, NONE),
- MFPR_910(MMC1_CD, 0x0AC, MMC1, GPIO, SEC1_JTAG, NONE, NONE, NONE, NONE, NONE),
- MFPR_910(VCXO_OUT, 0x0D8, VCXO_OUT, PWM3, NONE, NONE, NONE, NONE, NONE, NONE),
-};
-
-
-static const unsigned p910_usim2_pin1[] = {GPIO67, GPIO68, GPIO69};
-static const unsigned p910_usim2_pin2[] = {ND_IO15, ND_IO14, ND_IO13};
-static const unsigned p910_mmc1_pin1[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
- MMC1_DAT4, MMC1_DAT3, MMC1_DAT2, MMC1_DAT1, MMC1_DAT0, MMC1_CMD,
- MMC1_CLK, MMC1_CD, GPIO99};
-static const unsigned p910_mmc2_pin1[] = {GPIO33, GPIO34, GPIO35, GPIO36,
- GPIO37, GPIO38, GPIO39, GPIO40, GPIO41, GPIO42};
-static const unsigned p910_mmc3_pin1[] = {GPIO33, GPIO34, GPIO35, GPIO36,
- GPIO49, GPIO50};
-static const unsigned p910_mmc3_pin2[] = {ND_IO7, ND_IO6, ND_IO5, ND_IO4,
- ND_IO3, ND_IO2, ND_IO1, ND_IO0, ND_CLE, SM_SCLK};
-static const unsigned p910_uart0_pin1[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned p910_uart1_pin1[] = {GPIO47, GPIO48};
-static const unsigned p910_uart1_pin2[] = {GPIO31, GPIO32};
-static const unsigned p910_uart1_pin3[] = {GPIO45, GPIO46};
-static const unsigned p910_uart1_pin4[] = {GPIO29, GPIO30, GPIO31, GPIO32};
-static const unsigned p910_uart1_pin5[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_uart2_pin1[] = {GPIO43, GPIO44};
-static const unsigned p910_uart2_pin2[] = {GPIO51, GPIO52};
-static const unsigned p910_uart2_pin3[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_uart2_pin4[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_twsi_pin1[] = {GPIO51, GPIO52};
-static const unsigned p910_twsi_pin2[] = {GPIO53, GPIO54};
-static const unsigned p910_twsi_pin3[] = {GPIO79, GPIO80};
-static const unsigned p910_ccic_pin1[] = {GPIO67, GPIO68, GPIO69, GPIO70,
- GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78};
-static const unsigned p910_lcd_pin1[] = {GPIO81, GPIO82, GPIO83, GPIO84,
- GPIO85, GPIO86, GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92,
- GPIO93, GPIO94, GPIO95, GPIO96, GPIO97, GPIO98, GPIO100, GPIO101,
- GPIO102, GPIO103};
-static const unsigned p910_spi_pin1[] = {GPIO104, GPIO105, GPIO107, GPIO108};
-static const unsigned p910_spi_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_spi_pin3[] = {GPIO33, GPIO34, GPIO35, GPIO36,
- GPIO37};
-static const unsigned p910_spi_pin4[] = {GPIO67, GPIO68, GPIO69, GPIO70,
- GPIO71};
-static const unsigned p910_spi2_pin1[] = {GPIO64, GPIO65};
-static const unsigned p910_spi2_pin2[] = {GPIO102, GPIO103};
-static const unsigned p910_dssp2_pin1[] = {GPIO102, GPIO103, GPIO104, GPIO105};
-static const unsigned p910_dssp2_pin2[] = {GPIO43, GPIO44, GPIO45, GPIO46};
-static const unsigned p910_dssp2_pin3[] = {GPIO111, GPIO112, GPIO113};
-static const unsigned p910_dssp3_pin1[] = {GPIO106, GPIO107, GPIO108, GPIO109};
-static const unsigned p910_dssp3_pin2[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_dssp3_pin3[] = {GPIO114, GPIO115, GPIO116};
-static const unsigned p910_ssp0_pin1[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
- MMC1_CLK};
-static const unsigned p910_ssp0_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned p910_ssp0_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned p910_ssp0_pin4[] = {GPIO51, GPIO52, GPIO53, GPIO54};
-static const unsigned p910_ssp1_pin1[] = {GPIO21, GPIO22, GPIO23, GPIO24};
-static const unsigned p910_ssp1_pin2[] = {GPIO20, GPIO21, GPIO22, GPIO23,
- GPIO24};
-static const unsigned p910_ssp2_pin1[] = {MMC1_DAT2, MMC1_DAT1, MMC1_DAT0,
- MMC1_CMD};
-static const unsigned p910_ssp2_pin2[] = {GPIO33, GPIO34, GPIO35, GPIO36};
-static const unsigned p910_ssp2_pin3[] = {GPIO47, GPIO48, GPIO49, GPIO50};
-static const unsigned p910_ssp2_pin4[] = {ND_IO12, ND_IO11, ND_IO10, ND_IO9};
-static const unsigned p910_gssp_pin1[] = {GPIO25, GPIO26, GPIO27, GPIO28};
-static const unsigned p910_pwm0_pin1[] = {GPIO117};
-static const unsigned p910_pwm1_pin1[] = {GPIO118};
-static const unsigned p910_pwm1_pin2[] = {GPIO51};
-static const unsigned p910_pwm2_pin1[] = {GPIO119};
-static const unsigned p910_pwm3_pin1[] = {GPIO120};
-static const unsigned p910_pwm3_pin2[] = {ND_IO8};
-static const unsigned p910_pwm3_pin3[] = {VCXO_OUT};
-static const unsigned p910_pri_jtag_pin1[] = {GPIO117, GPIO118, GPIO119,
- GPIO120};
-static const unsigned p910_sec1_jtag_pin1[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
- MMC1_CMD, MMC1_CD};
-static const unsigned p910_sec2_jtag_pin1[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
- MMC1_DAT0, MMC1_CLK};
-static const unsigned p910_hsl_pin1[] = {GPIO37, GPIO38, GPIO39, GPIO40,
- GPIO41, GPIO42};
-static const unsigned p910_hsl_pin2[] = {GPIO61, GPIO62, GPIO63, GPIO64,
- GPIO65, GPIO66};
-static const unsigned p910_hsl_pin3[] = {MMC1_DAT3, MMC1_DAT2, MMC1_DAT1,
- MMC1_DAT0, MMC1_CMD, MMC1_CLK};
-static const unsigned p910_w1_pin1[] = {GPIO59};
-static const unsigned p910_w1_pin2[] = {GPIO65};
-static const unsigned p910_w1_pin3[] = {GPIO106};
-static const unsigned p910_w1_pin4[] = {GPIO123};
-static const unsigned p910_kpmk_pin1[] = {GPIO0, GPIO1, GPIO2, GPIO3, GPIO4,
- GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13,
- GPIO14, GPIO15};
-static const unsigned p910_kpmk_pin2[] = {GPIO0, GPIO1, GPIO2, GPIO3, GPIO4,
- GPIO5, GPIO6, GPIO7, GPIO8, GPIO9, GPIO12};
-static const unsigned p910_kpdk_pin1[] = {GPIO12, GPIO13, GPIO14, GPIO15,
- GPIO16, GPIO17, GPIO18, GPIO19};
-static const unsigned p910_tds_pin1[] = {GPIO55, GPIO56, GPIO57, GPIO58,
- GPIO59};
-static const unsigned p910_tds_pin2[] = {GPIO55, GPIO57, GPIO58, GPIO59};
-static const unsigned p910_tb_pin1[] = {GPIO14, GPIO15, GPIO16, GPIO17};
-static const unsigned p910_tb_pin2[] = {GPIO55, GPIO56, GPIO57, GPIO58};
-static const unsigned p910_tb_pin3[] = {MMC1_DAT7, MMC1_DAT6, MMC1_DAT5,
- MMC1_DAT4};
-static const unsigned p910_ext_dma0_pin1[] = {GPIO72};
-static const unsigned p910_ext_dma0_pin2[] = {ND_IO15};
-static const unsigned p910_ext_dma0_pin3[] = {ND_NRE};
-static const unsigned p910_ext_dma1_pin1[] = {GPIO73};
-static const unsigned p910_ext_dma1_pin2[] = {GPIO123};
-static const unsigned p910_ext_dma1_pin3[] = {GPIO126};
-static const unsigned p910_ext_dma2_pin1[] = {GPIO74};
-static const unsigned p910_ext0_int_pin1[] = {GPIO44};
-static const unsigned p910_ext0_int_pin2[] = {ND_IO13};
-static const unsigned p910_ext1_int_pin1[] = {GPIO45};
-static const unsigned p910_ext1_int_pin2[] = {ND_IO12};
-static const unsigned p910_ext2_int_pin1[] = {GPIO46};
-static const unsigned p910_ext2_int_pin2[] = {GPIO125};
-static const unsigned p910_dac_st23_pin1[] = {GPIO32};
-static const unsigned p910_dac_st23_pin2[] = {GPIO43};
-static const unsigned p910_dac_st23_pin3[] = {GPIO52};
-static const unsigned p910_dac_st23_pin4[] = {GPIO124};
-static const unsigned p910_vcxo_out_pin1[] = {GPIO50};
-static const unsigned p910_vcxo_out_pin2[] = {VCXO_OUT};
-static const unsigned p910_vcxo_out_pin3[] = {GPIO20};
-static const unsigned p910_vcxo_req_pin1[] = {GPIO49};
-static const unsigned p910_vcxo_req_pin2[] = {GPIO125};
-static const unsigned p910_vcxo_out2_pin1[] = {GPIO86};
-static const unsigned p910_vcxo_out2_pin2[] = {ND_IO9};
-static const unsigned p910_vcxo_req2_pin1[] = {GPIO84};
-static const unsigned p910_ulpi_pin1[] = {GPIO67, GPIO68, GPIO69, GPIO70,
- GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78};
-static const unsigned p910_nand_pin1[] = {ND_IO15, ND_IO14, ND_IO13, ND_IO12,
- ND_IO11, ND_IO10, ND_IO9, ND_IO8, ND_IO7, ND_IO6, ND_IO5, ND_IO4,
- ND_IO3, ND_IO2, ND_IO1, ND_IO0, ND_NCS0, ND_NWE, ND_NRE, ND_CLE,
- ND_ALE, ND_RDY0};
-static const unsigned p910_gpio0_pin1[] = {GPIO0};
-static const unsigned p910_gpio0_pin2[] = {SM_ADV};
-static const unsigned p910_gpio1_pin1[] = {GPIO1};
-static const unsigned p910_gpio1_pin2[] = {ND_RDY1};
-static const unsigned p910_gpio2_pin1[] = {GPIO2};
-static const unsigned p910_gpio2_pin2[] = {SM_ADVMUX};
-static const unsigned p910_gpio3_pin1[] = {GPIO3};
-static const unsigned p910_gpio3_pin2[] = {SM_RDY};
-static const unsigned p910_gpio20_pin1[] = {GPIO20};
-static const unsigned p910_gpio20_pin2[] = {ND_IO15};
-static const unsigned p910_gpio20_pin3[] = {MMC1_DAT6};
-static const unsigned p910_gpio21_pin1[] = {GPIO21};
-static const unsigned p910_gpio21_pin2[] = {ND_IO14};
-static const unsigned p910_gpio21_pin3[] = {MMC1_DAT5};
-static const unsigned p910_gpio22_pin1[] = {GPIO22};
-static const unsigned p910_gpio22_pin2[] = {ND_IO13};
-static const unsigned p910_gpio22_pin3[] = {MMC1_DAT4};
-static const unsigned p910_gpio23_pin1[] = {GPIO23};
-static const unsigned p910_gpio23_pin2[] = {ND_IO12};
-static const unsigned p910_gpio23_pin3[] = {MMC1_CD};
-static const unsigned p910_gpio24_pin1[] = {GPIO24};
-static const unsigned p910_gpio24_pin2[] = {ND_IO11};
-static const unsigned p910_gpio24_pin3[] = {MMC1_DAT7};
-static const unsigned p910_gpio25_pin1[] = {GPIO25};
-static const unsigned p910_gpio25_pin2[] = {ND_IO10};
-static const unsigned p910_gpio26_pin1[] = {GPIO26};
-static const unsigned p910_gpio26_pin2[] = {ND_IO9};
-static const unsigned p910_gpio27_pin1[] = {GPIO27};
-static const unsigned p910_gpio27_pin2[] = {ND_IO8};
-static const unsigned p910_gpio85_pin1[] = {GPIO85};
-static const unsigned p910_gpio85_pin2[] = {ND_NCS0};
-static const unsigned p910_gpio86_pin1[] = {GPIO86};
-static const unsigned p910_gpio86_pin2[] = {ND_NCS1};
-static const unsigned p910_gpio87_pin1[] = {GPIO87};
-static const unsigned p910_gpio87_pin2[] = {SM_NCS0};
-static const unsigned p910_gpio88_pin1[] = {GPIO88};
-static const unsigned p910_gpio88_pin2[] = {SM_NCS1};
-static const unsigned p910_gpio89_pin1[] = {GPIO89};
-static const unsigned p910_gpio89_pin2[] = {ND_NWE};
-static const unsigned p910_gpio90_pin1[] = {GPIO90};
-static const unsigned p910_gpio90_pin2[] = {ND_NRE};
-static const unsigned p910_gpio91_pin1[] = {GPIO91};
-static const unsigned p910_gpio91_pin2[] = {ND_ALE};
-static const unsigned p910_gpio92_pin1[] = {GPIO92};
-static const unsigned p910_gpio92_pin2[] = {ND_RDY0};
-
-static struct pxa3xx_pin_group pxa910_grps[] = {
- GRP_910("usim2 3p1", USIM2, p910_usim2_pin1),
- GRP_910("usim2 3p2", USIM2, p910_usim2_pin2),
- GRP_910("mmc1 12p", MMC1, p910_mmc1_pin1),
- GRP_910("mmc2 10p", MMC2, p910_mmc2_pin1),
- GRP_910("mmc3 6p", MMC3, p910_mmc3_pin1),
- GRP_910("mmc3 10p", MMC3, p910_mmc3_pin2),
- GRP_910("uart0 4p", UART0, p910_uart0_pin1),
- GRP_910("uart1 2p1", UART1, p910_uart1_pin1),
- GRP_910("uart1 2p2", UART1, p910_uart1_pin2),
- GRP_910("uart1 2p3", UART1, p910_uart1_pin3),
- GRP_910("uart1 4p4", UART1, p910_uart1_pin4),
- GRP_910("uart1 4p5", UART1, p910_uart1_pin5),
- GRP_910("uart2 2p1", UART2, p910_uart2_pin1),
- GRP_910("uart2 2p2", UART2, p910_uart2_pin2),
- GRP_910("uart2 4p3", UART2, p910_uart2_pin3),
- GRP_910("uart2 4p4", UART2, p910_uart2_pin4),
- GRP_910("twsi 2p1", TWSI, p910_twsi_pin1),
- GRP_910("twsi 2p2", TWSI, p910_twsi_pin2),
- GRP_910("twsi 2p3", TWSI, p910_twsi_pin3),
- GRP_910("ccic", CCIC, p910_ccic_pin1),
- GRP_910("lcd", LCD, p910_lcd_pin1),
- GRP_910("spi 4p1", SPI, p910_spi_pin1),
- GRP_910("spi 4p2", SPI, p910_spi_pin2),
- GRP_910("spi 5p3", SPI, p910_spi_pin3),
- GRP_910("spi 5p4", SPI, p910_spi_pin4),
- GRP_910("dssp2 4p1", DSSP2, p910_dssp2_pin1),
- GRP_910("dssp2 4p2", DSSP2, p910_dssp2_pin2),
- GRP_910("dssp2 3p3", DSSP2, p910_dssp2_pin3),
- GRP_910("dssp3 4p1", DSSP3, p910_dssp3_pin1),
- GRP_910("dssp3 4p2", DSSP3, p910_dssp3_pin2),
- GRP_910("dssp3 3p3", DSSP3, p910_dssp3_pin3),
- GRP_910("ssp0 4p1", SSP0, p910_ssp0_pin1),
- GRP_910("ssp0 4p2", SSP0, p910_ssp0_pin2),
- GRP_910("ssp0 4p3", SSP0, p910_ssp0_pin3),
- GRP_910("ssp0 4p4", SSP0, p910_ssp0_pin4),
- GRP_910("ssp1 4p1", SSP1, p910_ssp1_pin1),
- GRP_910("ssp1 5p2", SSP1, p910_ssp1_pin2),
- GRP_910("ssp2 4p1", SSP2, p910_ssp2_pin1),
- GRP_910("ssp2 4p2", SSP2, p910_ssp2_pin2),
- GRP_910("ssp2 4p3", SSP2, p910_ssp2_pin3),
- GRP_910("ssp2 4p4", SSP2, p910_ssp2_pin4),
- GRP_910("gssp", GSSP, p910_gssp_pin1),
- GRP_910("pwm0", PWM0, p910_pwm0_pin1),
- GRP_910("pwm1-1", PWM1, p910_pwm1_pin1),
- GRP_910("pwm1-2", PWM1, p910_pwm1_pin2),
- GRP_910("pwm2", PWM2, p910_pwm2_pin1),
- GRP_910("pwm3-1", PWM3, p910_pwm3_pin1),
- GRP_910("pwm3-2", PWM3, p910_pwm3_pin2),
- GRP_910("pwm3-3", PWM3, p910_pwm3_pin3),
- GRP_910("pri jtag", PRI_JTAG, p910_pri_jtag_pin1),
- GRP_910("sec1 jtag", SEC1_JTAG, p910_sec1_jtag_pin1),
- GRP_910("sec2 jtag", SEC2_JTAG, p910_sec2_jtag_pin1),
- GRP_910("hsl 6p1", HSL, p910_hsl_pin1),
- GRP_910("hsl 6p2", HSL, p910_hsl_pin2),
- GRP_910("hsl 6p3", HSL, p910_hsl_pin3),
- GRP_910("w1-1", ONE_WIRE, p910_w1_pin1),
- GRP_910("w1-2", ONE_WIRE, p910_w1_pin2),
- GRP_910("w1-3", ONE_WIRE, p910_w1_pin3),
- GRP_910("w1-4", ONE_WIRE, p910_w1_pin4),
- GRP_910("kpmk 16p1", KP_MK, p910_kpmk_pin1),
- GRP_910("kpmk 11p2", KP_MK, p910_kpmk_pin2),
- GRP_910("kpdk 8p1", KP_DK, p910_kpdk_pin1),
- GRP_910("tds 5p1", TDS, p910_tds_pin1),
- GRP_910("tds 4p2", TDS, p910_tds_pin2),
- GRP_910("tb 4p1", TB, p910_tb_pin1),
- GRP_910("tb 4p2", TB, p910_tb_pin2),
- GRP_910("tb 4p3", TB, p910_tb_pin3),
- GRP_910("ext dma0-1", EXT_DMA, p910_ext_dma0_pin1),
- GRP_910("ext dma0-2", EXT_DMA, p910_ext_dma0_pin2),
- GRP_910("ext dma0-3", EXT_DMA, p910_ext_dma0_pin3),
- GRP_910("ext dma1-1", EXT_DMA, p910_ext_dma1_pin1),
- GRP_910("ext dma1-2", EXT_DMA, p910_ext_dma1_pin2),
- GRP_910("ext dma1-3", EXT_DMA, p910_ext_dma1_pin3),
- GRP_910("ext dma2", EXT_DMA, p910_ext_dma2_pin1),
- GRP_910("ext0 int-1", EXT_INT, p910_ext0_int_pin1),
- GRP_910("ext0 int-2", EXT_INT, p910_ext0_int_pin2),
- GRP_910("ext1 int-1", EXT_INT, p910_ext1_int_pin1),
- GRP_910("ext1 int-2", EXT_INT, p910_ext1_int_pin2),
- GRP_910("ext2 int-1", EXT_INT, p910_ext2_int_pin1),
- GRP_910("ext2 int-2", EXT_INT, p910_ext2_int_pin2),
- GRP_910("dac st23-1", DAC_ST23, p910_dac_st23_pin1),
- GRP_910("dac st23-2", DAC_ST23, p910_dac_st23_pin2),
- GRP_910("dac st23-3", DAC_ST23, p910_dac_st23_pin3),
- GRP_910("dac st23-4", DAC_ST23, p910_dac_st23_pin4),
- GRP_910("vcxo out-1", VCXO_OUT, p910_vcxo_out_pin1),
- GRP_910("vcxo out-2", VCXO_OUT, p910_vcxo_out_pin2),
- GRP_910("vcxo out-3", VCXO_OUT, p910_vcxo_out_pin3),
- GRP_910("vcxo req-1", VCXO_REQ, p910_vcxo_req_pin1),
- GRP_910("vcxo req-2", VCXO_REQ, p910_vcxo_req_pin2),
- GRP_910("vcxo out2-1", VCXO_OUT2, p910_vcxo_out2_pin1),
- GRP_910("vcxo out2-2", VCXO_OUT2, p910_vcxo_out2_pin2),
- GRP_910("vcxo req2", VCXO_REQ2, p910_vcxo_req2_pin1),
- GRP_910("ulpi", ULPI, p910_ulpi_pin1),
- GRP_910("nand", NAND, p910_nand_pin1),
- GRP_910("gpio0-1", GPIO, p910_gpio0_pin1),
- GRP_910("gpio0-2", GPIO, p910_gpio0_pin2),
- GRP_910("gpio1-1", GPIO, p910_gpio1_pin1),
- GRP_910("gpio1-2", GPIO, p910_gpio1_pin2),
- GRP_910("gpio2-1", GPIO, p910_gpio2_pin1),
- GRP_910("gpio2-2", GPIO, p910_gpio2_pin2),
- GRP_910("gpio3-1", GPIO, p910_gpio3_pin1),
- GRP_910("gpio3-2", GPIO, p910_gpio3_pin2),
- GRP_910("gpio20-1", GPIO, p910_gpio20_pin1),
- GRP_910("gpio20-2", GPIO, p910_gpio20_pin2),
- GRP_910("gpio21-1", GPIO, p910_gpio21_pin1),
- GRP_910("gpio21-2", GPIO, p910_gpio21_pin2),
- GRP_910("gpio22-1", GPIO, p910_gpio22_pin1),
- GRP_910("gpio22-2", GPIO, p910_gpio22_pin2),
- GRP_910("gpio23-1", GPIO, p910_gpio23_pin1),
- GRP_910("gpio23-2", GPIO, p910_gpio23_pin2),
- GRP_910("gpio24-1", GPIO, p910_gpio24_pin1),
- GRP_910("gpio24-2", GPIO, p910_gpio24_pin2),
- GRP_910("gpio25-1", GPIO, p910_gpio25_pin1),
- GRP_910("gpio25-2", GPIO, p910_gpio25_pin2),
- GRP_910("gpio26-1", GPIO, p910_gpio26_pin1),
- GRP_910("gpio26-2", GPIO, p910_gpio26_pin2),
- GRP_910("gpio27-1", GPIO, p910_gpio27_pin1),
- GRP_910("gpio27-2", GPIO, p910_gpio27_pin2),
- GRP_910("gpio85-1", GPIO, p910_gpio85_pin1),
- GRP_910("gpio85-2", GPIO, p910_gpio85_pin2),
- GRP_910("gpio86-1", GPIO, p910_gpio86_pin1),
- GRP_910("gpio86-2", GPIO, p910_gpio86_pin2),
- GRP_910("gpio87-1", GPIO, p910_gpio87_pin1),
- GRP_910("gpio87-2", GPIO, p910_gpio87_pin2),
- GRP_910("gpio88-1", GPIO, p910_gpio88_pin1),
- GRP_910("gpio88-2", GPIO, p910_gpio88_pin2),
- GRP_910("gpio89-1", GPIO, p910_gpio89_pin1),
- GRP_910("gpio89-2", GPIO, p910_gpio89_pin2),
- GRP_910("gpio90-1", GPIO, p910_gpio90_pin1),
- GRP_910("gpio90-2", GPIO, p910_gpio90_pin2),
- GRP_910("gpio91-1", GPIO, p910_gpio91_pin1),
- GRP_910("gpio91-2", GPIO, p910_gpio91_pin2),
- GRP_910("gpio92-1", GPIO, p910_gpio92_pin1),
- GRP_910("gpio92-2", GPIO, p910_gpio92_pin2),
-};
-
-static const char * const p910_usim2_grps[] = {"usim2 3p1", "usim2 3p2"};
-static const char * const p910_mmc1_grps[] = {"mmc1 12p"};
-static const char * const p910_mmc2_grps[] = {"mmc2 10p"};
-static const char * const p910_mmc3_grps[] = {"mmc3 6p", "mmc3 10p"};
-static const char * const p910_uart0_grps[] = {"uart0 4p"};
-static const char * const p910_uart1_grps[] = {"uart1 2p1", "uart1 2p2",
- "uart1 2p3", "uart1 4p4", "uart1 4p5"};
-static const char * const p910_uart2_grps[] = {"uart2 2p1", "uart2 2p2",
- "uart2 4p3", "uart2 4p4"};
-static const char * const p910_twsi_grps[] = {"twsi 2p1", "twsi 2p2",
- "twsi 2p3"};
-static const char * const p910_ccic_grps[] = {"ccic"};
-static const char * const p910_lcd_grps[] = {"lcd"};
-static const char * const p910_spi_grps[] = {"spi 4p1", "spi 4p2", "spi 5p3",
- "spi 5p4"};
-static const char * const p910_dssp2_grps[] = {"dssp2 4p1", "dssp2 4p2",
- "dssp2 3p3"};
-static const char * const p910_dssp3_grps[] = {"dssp3 4p1", "dssp3 4p2",
- "dssp3 3p3"};
-static const char * const p910_ssp0_grps[] = {"ssp0 4p1", "ssp0 4p2",
- "ssp0 4p3", "ssp0 4p4"};
-static const char * const p910_ssp1_grps[] = {"ssp1 4p1", "ssp1 5p2"};
-static const char * const p910_ssp2_grps[] = {"ssp2 4p1", "ssp2 4p2",
- "ssp2 4p3", "ssp2 4p4"};
-static const char * const p910_gssp_grps[] = {"gssp"};
-static const char * const p910_pwm0_grps[] = {"pwm0"};
-static const char * const p910_pwm1_grps[] = {"pwm1-1", "pwm1-2"};
-static const char * const p910_pwm2_grps[] = {"pwm2"};
-static const char * const p910_pwm3_grps[] = {"pwm3-1", "pwm3-2", "pwm3-3"};
-static const char * const p910_pri_jtag_grps[] = {"pri jtag"};
-static const char * const p910_sec1_jtag_grps[] = {"sec1 jtag"};
-static const char * const p910_sec2_jtag_grps[] = {"sec2 jtag"};
-static const char * const p910_hsl_grps[] = {"hsl 6p1", "hsl 6p2", "hsl 6p3"};
-static const char * const p910_w1_grps[] = {"w1-1", "w1-2", "w1-3", "w1-4"};
-static const char * const p910_kpmk_grps[] = {"kpmk 16p1", "kpmk 11p2"};
-static const char * const p910_kpdk_grps[] = {"kpdk 8p1"};
-static const char * const p910_tds_grps[] = {"tds 5p1", "tds 4p2"};
-static const char * const p910_tb_grps[] = {"tb 4p1", "tb 4p2", "tb 4p3"};
-static const char * const p910_dma0_grps[] = {"ext dma0-1", "ext dma0-2",
- "ext dma0-3"};
-static const char * const p910_dma1_grps[] = {"ext dma1-1", "ext dma1-2",
- "ext dma1-3"};
-static const char * const p910_dma2_grps[] = {"ext dma2"};
-static const char * const p910_int0_grps[] = {"ext0 int-1", "ext0 int-2"};
-static const char * const p910_int1_grps[] = {"ext1 int-1", "ext1 int-2"};
-static const char * const p910_int2_grps[] = {"ext2 int-1", "ext2 int-2"};
-static const char * const p910_dac_st23_grps[] = {"dac st23-1", "dac st23-2",
- "dac st23-3", "dac st23-4"};
-static const char * const p910_vcxo_out_grps[] = {"vcxo out-1", "vcxo out-2",
- "vcxo out-3"};
-static const char * const p910_vcxo_req_grps[] = {"vcxo req-1", "vcxo req-2"};
-static const char * const p910_vcxo_out2_grps[] = {"vcxo out2-1",
- "vcxo out2-2"};
-static const char * const p910_vcxo_req2_grps[] = {"vcxo req2"};
-static const char * const p910_ulpi_grps[] = {"ulpi"};
-static const char * const p910_nand_grps[] = {"nand"};
-static const char * const p910_gpio0_grps[] = {"gpio0-1", "gpio0-2"};
-static const char * const p910_gpio1_grps[] = {"gpio1-1", "gpio1-2"};
-static const char * const p910_gpio2_grps[] = {"gpio2-1", "gpio2-2"};
-static const char * const p910_gpio3_grps[] = {"gpio3-1", "gpio3-2"};
-static const char * const p910_gpio20_grps[] = {"gpio20-1", "gpio20-2"};
-static const char * const p910_gpio21_grps[] = {"gpio21-1", "gpio21-2"};
-static const char * const p910_gpio22_grps[] = {"gpio22-1", "gpio22-2"};
-static const char * const p910_gpio23_grps[] = {"gpio23-1", "gpio23-2"};
-static const char * const p910_gpio24_grps[] = {"gpio24-1", "gpio24-2"};
-static const char * const p910_gpio25_grps[] = {"gpio25-1", "gpio25-2"};
-static const char * const p910_gpio26_grps[] = {"gpio26-1", "gpio26-2"};
-static const char * const p910_gpio27_grps[] = {"gpio27-1", "gpio27-2"};
-static const char * const p910_gpio85_grps[] = {"gpio85-1", "gpio85-2"};
-static const char * const p910_gpio86_grps[] = {"gpio86-1", "gpio86-2"};
-static const char * const p910_gpio87_grps[] = {"gpio87-1", "gpio87-2"};
-static const char * const p910_gpio88_grps[] = {"gpio88-1", "gpio88-2"};
-static const char * const p910_gpio89_grps[] = {"gpio89-1", "gpio89-2"};
-static const char * const p910_gpio90_grps[] = {"gpio90-1", "gpio90-2"};
-static const char * const p910_gpio91_grps[] = {"gpio91-1", "gpio91-2"};
-static const char * const p910_gpio92_grps[] = {"gpio92-1", "gpio92-2"};
-
-static struct pxa3xx_pmx_func pxa910_funcs[] = {
- {"usim2", ARRAY_AND_SIZE(p910_usim2_grps)},
- {"mmc1", ARRAY_AND_SIZE(p910_mmc1_grps)},
- {"mmc2", ARRAY_AND_SIZE(p910_mmc2_grps)},
- {"mmc3", ARRAY_AND_SIZE(p910_mmc3_grps)},
- {"uart0", ARRAY_AND_SIZE(p910_uart0_grps)},
- {"uart1", ARRAY_AND_SIZE(p910_uart1_grps)},
- {"uart2", ARRAY_AND_SIZE(p910_uart2_grps)},
- {"twsi", ARRAY_AND_SIZE(p910_twsi_grps)},
- {"ccic", ARRAY_AND_SIZE(p910_ccic_grps)},
- {"lcd", ARRAY_AND_SIZE(p910_lcd_grps)},
- {"spi", ARRAY_AND_SIZE(p910_spi_grps)},
- {"dssp2", ARRAY_AND_SIZE(p910_dssp2_grps)},
- {"dssp3", ARRAY_AND_SIZE(p910_dssp3_grps)},
- {"ssp0", ARRAY_AND_SIZE(p910_ssp0_grps)},
- {"ssp1", ARRAY_AND_SIZE(p910_ssp1_grps)},
- {"ssp2", ARRAY_AND_SIZE(p910_ssp2_grps)},
- {"gssp", ARRAY_AND_SIZE(p910_gssp_grps)},
- {"pwm0", ARRAY_AND_SIZE(p910_pwm0_grps)},
- {"pwm1", ARRAY_AND_SIZE(p910_pwm1_grps)},
- {"pwm2", ARRAY_AND_SIZE(p910_pwm2_grps)},
- {"pwm3", ARRAY_AND_SIZE(p910_pwm3_grps)},
- {"pri_jtag", ARRAY_AND_SIZE(p910_pri_jtag_grps)},
- {"sec1_jtag", ARRAY_AND_SIZE(p910_sec1_jtag_grps)},
- {"sec2_jtag", ARRAY_AND_SIZE(p910_sec2_jtag_grps)},
- {"hsl", ARRAY_AND_SIZE(p910_hsl_grps)},
- {"w1", ARRAY_AND_SIZE(p910_w1_grps)},
- {"kpmk", ARRAY_AND_SIZE(p910_kpmk_grps)},
- {"kpdk", ARRAY_AND_SIZE(p910_kpdk_grps)},
- {"tds", ARRAY_AND_SIZE(p910_tds_grps)},
- {"tb", ARRAY_AND_SIZE(p910_tb_grps)},
- {"dma0", ARRAY_AND_SIZE(p910_dma0_grps)},
- {"dma1", ARRAY_AND_SIZE(p910_dma1_grps)},
- {"dma2", ARRAY_AND_SIZE(p910_dma2_grps)},
- {"int0", ARRAY_AND_SIZE(p910_int0_grps)},
- {"int1", ARRAY_AND_SIZE(p910_int1_grps)},
- {"int2", ARRAY_AND_SIZE(p910_int2_grps)},
- {"dac_st23", ARRAY_AND_SIZE(p910_dac_st23_grps)},
- {"vcxo_out", ARRAY_AND_SIZE(p910_vcxo_out_grps)},
- {"vcxo_req", ARRAY_AND_SIZE(p910_vcxo_req_grps)},
- {"vcxo_out2", ARRAY_AND_SIZE(p910_vcxo_out2_grps)},
- {"vcxo_req2", ARRAY_AND_SIZE(p910_vcxo_req2_grps)},
- {"ulpi", ARRAY_AND_SIZE(p910_ulpi_grps)},
- {"nand", ARRAY_AND_SIZE(p910_nand_grps)},
- {"gpio0", ARRAY_AND_SIZE(p910_gpio0_grps)},
- {"gpio1", ARRAY_AND_SIZE(p910_gpio1_grps)},
- {"gpio2", ARRAY_AND_SIZE(p910_gpio2_grps)},
- {"gpio3", ARRAY_AND_SIZE(p910_gpio3_grps)},
- {"gpio20", ARRAY_AND_SIZE(p910_gpio20_grps)},
- {"gpio21", ARRAY_AND_SIZE(p910_gpio21_grps)},
- {"gpio22", ARRAY_AND_SIZE(p910_gpio22_grps)},
- {"gpio23", ARRAY_AND_SIZE(p910_gpio23_grps)},
- {"gpio24", ARRAY_AND_SIZE(p910_gpio24_grps)},
- {"gpio25", ARRAY_AND_SIZE(p910_gpio25_grps)},
- {"gpio26", ARRAY_AND_SIZE(p910_gpio26_grps)},
- {"gpio27", ARRAY_AND_SIZE(p910_gpio27_grps)},
- {"gpio85", ARRAY_AND_SIZE(p910_gpio85_grps)},
- {"gpio86", ARRAY_AND_SIZE(p910_gpio86_grps)},
- {"gpio87", ARRAY_AND_SIZE(p910_gpio87_grps)},
- {"gpio88", ARRAY_AND_SIZE(p910_gpio88_grps)},
- {"gpio89", ARRAY_AND_SIZE(p910_gpio89_grps)},
- {"gpio90", ARRAY_AND_SIZE(p910_gpio90_grps)},
- {"gpio91", ARRAY_AND_SIZE(p910_gpio91_grps)},
- {"gpio92", ARRAY_AND_SIZE(p910_gpio92_grps)},
-};
-
-static struct pinctrl_desc pxa910_pctrl_desc = {
- .name = "pxa910-pinctrl",
- .owner = THIS_MODULE,
-};
-
-static struct pxa3xx_pinmux_info pxa910_info = {
- .mfp = pxa910_mfp,
- .num_mfp = ARRAY_SIZE(pxa910_mfp),
- .grps = pxa910_grps,
- .num_grps = ARRAY_SIZE(pxa910_grps),
- .funcs = pxa910_funcs,
- .num_funcs = ARRAY_SIZE(pxa910_funcs),
- .num_gpio = 128,
- .desc = &pxa910_pctrl_desc,
- .pads = pxa910_pads,
- .num_pads = ARRAY_SIZE(pxa910_pads),
-
- .cputype = PINCTRL_PXA910,
- .ds_mask = PXA910_DS_MASK,
- .ds_shift = PXA910_DS_SHIFT,
-};
-
-static int pxa910_pinmux_probe(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_register(pdev, &pxa910_info);
-}
-
-static int pxa910_pinmux_remove(struct platform_device *pdev)
-{
- return pxa3xx_pinctrl_unregister(pdev);
-}
-
-static struct platform_driver pxa910_pinmux_driver = {
- .driver = {
- .name = "pxa910-pinmux",
- .owner = THIS_MODULE,
- },
- .probe = pxa910_pinmux_probe,
- .remove = pxa910_pinmux_remove,
-};
-
-static int __init pxa910_pinmux_init(void)
-{
- return platform_driver_register(&pxa910_pinmux_driver);
-}
-core_initcall_sync(pxa910_pinmux_init);
-
-static void __exit pxa910_pinmux_exit(void)
-{
- platform_driver_unregister(&pxa910_pinmux_driver);
-}
-module_exit(pxa910_pinmux_exit);
-
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_DESCRIPTION("PXA3xx pin control driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pinctrl-s3c64xx.c b/drivers/pinctrl/pinctrl-s3c64xx.c
new file mode 100644
index 0000000..89143c9
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-s3c64xx.c
@@ -0,0 +1,816 @@
+/*
+ * S3C64xx specific support for pinctrl-samsung driver.
+ *
+ * Copyright (c) 2013 Tomasz Figa <tomasz.figa@gmail.com>
+ *
+ * Based on pinctrl-exynos.c, please see the file for original copyrights.
+ *
+ * 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 file contains the Samsung S3C64xx specific information required by the
+ * the Samsung pinctrl/gpiolib driver. It also includes the implementation of
+ * external gpio and wakeup interrupt support.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "pinctrl-samsung.h"
+
+#define NUM_EINT0 28
+#define NUM_EINT0_IRQ 4
+#define EINT_MAX_PER_REG 16
+#define EINT_MAX_PER_GROUP 16
+
+/* External GPIO and wakeup interrupt related definitions */
+#define SVC_GROUP_SHIFT 4
+#define SVC_GROUP_MASK 0xf
+#define SVC_NUM_MASK 0xf
+#define SVC_GROUP(x) ((x >> SVC_GROUP_SHIFT) & \
+ SVC_GROUP_MASK)
+
+#define EINT12CON_REG 0x200
+#define EINT12MASK_REG 0x240
+#define EINT12PEND_REG 0x260
+
+#define EINT_OFFS(i) ((i) % (2 * EINT_MAX_PER_GROUP))
+#define EINT_GROUP(i) ((i) / EINT_MAX_PER_GROUP)
+#define EINT_REG(g) (4 * ((g) / 2))
+
+#define EINTCON_REG(i) (EINT12CON_REG + EINT_REG(EINT_GROUP(i)))
+#define EINTMASK_REG(i) (EINT12MASK_REG + EINT_REG(EINT_GROUP(i)))
+#define EINTPEND_REG(i) (EINT12PEND_REG + EINT_REG(EINT_GROUP(i)))
+
+#define SERVICE_REG 0x284
+#define SERVICEPEND_REG 0x288
+
+#define EINT0CON0_REG 0x900
+#define EINT0MASK_REG 0x920
+#define EINT0PEND_REG 0x924
+
+/* S3C64xx specific external interrupt trigger types */
+#define EINT_LEVEL_LOW 0
+#define EINT_LEVEL_HIGH 1
+#define EINT_EDGE_FALLING 2
+#define EINT_EDGE_RISING 4
+#define EINT_EDGE_BOTH 6
+#define EINT_CON_MASK 0xF
+#define EINT_CON_LEN 4
+
+static struct samsung_pin_bank_type bank_type_4bit_off = {
+ .fld_width = { 4, 1, 2, 0, 2, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit_alive = {
+ .fld_width = { 4, 1, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit2_off = {
+ .fld_width = { 4, 1, 2, 0, 2, 2, },
+ .reg_offset = { 0x00, 0x08, 0x0c, 0, 0x10, 0x14, },
+};
+
+static struct samsung_pin_bank_type bank_type_4bit2_alive = {
+ .fld_width = { 4, 1, 2, },
+ .reg_offset = { 0x00, 0x08, 0x0c, },
+};
+
+static struct samsung_pin_bank_type bank_type_2bit_off = {
+ .fld_width = { 2, 1, 2, 0, 2, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, 0, 0x0c, 0x10, },
+};
+
+static struct samsung_pin_bank_type bank_type_2bit_alive = {
+ .fld_width = { 2, 1, 2, },
+ .reg_offset = { 0x00, 0x04, 0x08, },
+};
+
+#define PIN_BANK_4BIT(pins, reg, id) \
+ { \
+ .type = &bank_type_4bit_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_NONE, \
+ .name = id \
+ }
+
+#define PIN_BANK_4BIT_EINTG(pins, reg, id, eoffs) \
+ { \
+ .type = &bank_type_4bit_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .eint_func = 7, \
+ .eint_mask = (1 << (pins)) - 1, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+#define PIN_BANK_4BIT_EINTW(pins, reg, id, eoffs, emask) \
+ { \
+ .type = &bank_type_4bit_alive,\
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_func = 3, \
+ .eint_mask = emask, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+#define PIN_BANK_4BIT2_EINTG(pins, reg, id, eoffs) \
+ { \
+ .type = &bank_type_4bit2_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .eint_func = 7, \
+ .eint_mask = (1 << (pins)) - 1, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+#define PIN_BANK_4BIT2_EINTW(pins, reg, id, eoffs, emask) \
+ { \
+ .type = &bank_type_4bit2_alive,\
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_func = 3, \
+ .eint_mask = emask, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+#define PIN_BANK_4BIT2_ALIVE(pins, reg, id) \
+ { \
+ .type = &bank_type_4bit2_alive,\
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_NONE, \
+ .name = id \
+ }
+
+#define PIN_BANK_2BIT(pins, reg, id) \
+ { \
+ .type = &bank_type_2bit_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_NONE, \
+ .name = id \
+ }
+
+#define PIN_BANK_2BIT_EINTG(pins, reg, id, eoffs, emask) \
+ { \
+ .type = &bank_type_2bit_off, \
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_GPIO, \
+ .eint_func = 3, \
+ .eint_mask = emask, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+#define PIN_BANK_2BIT_EINTW(pins, reg, id, eoffs) \
+ { \
+ .type = &bank_type_2bit_alive,\
+ .pctl_offset = reg, \
+ .nr_pins = pins, \
+ .eint_type = EINT_TYPE_WKUP, \
+ .eint_func = 2, \
+ .eint_mask = (1 << (pins)) - 1, \
+ .eint_offset = eoffs, \
+ .name = id \
+ }
+
+/**
+ * struct s3c64xx_eint0_data: EINT0 common data
+ * @drvdata: pin controller driver data
+ * @domains: IRQ domains of particular EINT0 interrupts
+ * @pins: pin offsets inside of banks of particular EINT0 interrupts
+ */
+struct s3c64xx_eint0_data {
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct irq_domain *domains[NUM_EINT0];
+ u8 pins[NUM_EINT0];
+};
+
+/**
+ * struct s3c64xx_eint0_domain_data: EINT0 per-domain data
+ * @bank: pin bank related to the domain
+ * @eints: EINT0 interrupts related to the domain
+ */
+struct s3c64xx_eint0_domain_data {
+ struct samsung_pin_bank *bank;
+ u8 eints[];
+};
+
+/**
+ * struct s3c64xx_eint_gpio_data: GPIO EINT data
+ * @drvdata: pin controller driver data
+ * @domains: array of domains related to EINT interrupt groups
+ */
+struct s3c64xx_eint_gpio_data {
+ struct samsung_pinctrl_drv_data *drvdata;
+ struct irq_domain *domains[];
+};
+
+/*
+ * Common functions for S3C64xx EINT configuration
+ */
+
+static int s3c64xx_irq_get_trigger(unsigned int type)
+{
+ int trigger;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ trigger = EINT_EDGE_RISING;
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ trigger = EINT_EDGE_FALLING;
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ trigger = EINT_EDGE_BOTH;
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ trigger = EINT_LEVEL_HIGH;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ trigger = EINT_LEVEL_LOW;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return trigger;
+}
+
+static void s3c64xx_irq_set_handler(unsigned int irq, unsigned int type)
+{
+ /* Edge- and level-triggered interrupts need different handlers */
+ if (type & IRQ_TYPE_EDGE_BOTH)
+ __irq_set_handler_locked(irq, handle_edge_irq);
+ else
+ __irq_set_handler_locked(irq, handle_level_irq);
+}
+
+static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d,
+ struct samsung_pin_bank *bank, int pin)
+{
+ struct samsung_pin_bank_type *bank_type = bank->type;
+ unsigned long flags;
+ void __iomem *reg;
+ u8 shift;
+ u32 mask;
+ u32 val;
+
+ /* Make sure that pin is configured as interrupt */
+ reg = d->virt_base + bank->pctl_offset;
+ shift = pin;
+ if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) {
+ /* 4-bit bank type with 2 con regs */
+ reg += 4;
+ shift -= 8;
+ }
+
+ shift = shift * bank_type->fld_width[PINCFG_TYPE_FUNC];
+ mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+ spin_lock_irqsave(&bank->slock, flags);
+
+ val = readl(reg);
+ val &= ~(mask << shift);
+ val |= bank->eint_func << shift;
+ writel(val, reg);
+
+ spin_unlock_irqrestore(&bank->slock, flags);
+}
+
+/*
+ * Functions for EINT GPIO configuration (EINT groups 1-9)
+ */
+
+static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask)
+{
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+ void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset);
+ u32 val;
+
+ val = readl(reg);
+ if (mask)
+ val |= 1 << index;
+ else
+ val &= ~(1 << index);
+ writel(val, reg);
+}
+
+static void s3c64xx_gpio_irq_unmask(struct irq_data *irqd)
+{
+ s3c64xx_gpio_irq_set_mask(irqd, false);
+}
+
+static void s3c64xx_gpio_irq_mask(struct irq_data *irqd)
+{
+ s3c64xx_gpio_irq_set_mask(irqd, true);
+}
+
+static void s3c64xx_gpio_irq_ack(struct irq_data *irqd)
+{
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+ void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset);
+
+ writel(1 << index, reg);
+}
+
+static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ void __iomem *reg;
+ int trigger;
+ u8 shift;
+ u32 val;
+
+ trigger = s3c64xx_irq_get_trigger(type);
+ if (trigger < 0) {
+ pr_err("unsupported external interrupt type\n");
+ return -EINVAL;
+ }
+
+ s3c64xx_irq_set_handler(irqd->irq, type);
+
+ /* Set up interrupt trigger */
+ reg = d->virt_base + EINTCON_REG(bank->eint_offset);
+ shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq;
+ shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */
+
+ val = readl(reg);
+ val &= ~(EINT_CON_MASK << shift);
+ val |= trigger << shift;
+ writel(val, reg);
+
+ s3c64xx_irq_set_function(d, bank, irqd->hwirq);
+
+ return 0;
+}
+
+/*
+ * irq_chip for gpio interrupts.
+ */
+static struct irq_chip s3c64xx_gpio_irq_chip = {
+ .name = "GPIO",
+ .irq_unmask = s3c64xx_gpio_irq_unmask,
+ .irq_mask = s3c64xx_gpio_irq_mask,
+ .irq_ack = s3c64xx_gpio_irq_ack,
+ .irq_set_type = s3c64xx_gpio_irq_set_type,
+};
+
+static int s3c64xx_gpio_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct samsung_pin_bank *bank = h->host_data;
+
+ if (!(bank->eint_mask & (1 << hw)))
+ return -EINVAL;
+
+ irq_set_chip_and_handler(virq,
+ &s3c64xx_gpio_irq_chip, handle_level_irq);
+ irq_set_chip_data(virq, bank);
+ set_irq_flags(virq, IRQF_VALID);
+
+ return 0;
+}
+
+/*
+ * irq domain callbacks for external gpio interrupt controller.
+ */
+static const struct irq_domain_ops s3c64xx_gpio_irqd_ops = {
+ .map = s3c64xx_gpio_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void s3c64xx_eint_gpio_irq(unsigned int irq, struct irq_desc *desc)
+{
+ struct irq_chip *chip = irq_get_chip(irq);
+ struct s3c64xx_eint_gpio_data *data = irq_get_handler_data(irq);
+ struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+
+ chained_irq_enter(chip, desc);
+
+ do {
+ unsigned int svc;
+ unsigned int group;
+ unsigned int pin;
+ unsigned int virq;
+
+ svc = readl(drvdata->virt_base + SERVICE_REG);
+ group = SVC_GROUP(svc);
+ pin = svc & SVC_NUM_MASK;
+
+ if (!group)
+ break;
+
+ /* Group 1 is used for two pin banks */
+ if (group == 1) {
+ if (pin < 8)
+ group = 0;
+ else
+ pin -= 8;
+ }
+
+ virq = irq_linear_revmap(data->domains[group], pin);
+ /*
+ * Something must be really wrong if an unmapped EINT
+ * was unmasked...
+ */
+ BUG_ON(!virq);
+
+ generic_handle_irq(virq);
+ } while (1);
+
+ chained_irq_exit(chip, desc);
+}
+
+/**
+ * s3c64xx_eint_gpio_init() - setup handling of external gpio interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int s3c64xx_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
+{
+ struct s3c64xx_eint_gpio_data *data;
+ struct samsung_pin_bank *bank;
+ struct device *dev = d->dev;
+ unsigned int nr_domains;
+ unsigned int i;
+
+ if (!d->irq) {
+ dev_err(dev, "irq number not available\n");
+ return -EINVAL;
+ }
+
+ nr_domains = 0;
+ bank = d->ctrl->pin_banks;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ unsigned int nr_eints;
+ unsigned int mask;
+
+ if (bank->eint_type != EINT_TYPE_GPIO)
+ continue;
+
+ mask = bank->eint_mask;
+ nr_eints = fls(mask);
+
+ bank->irq_domain = irq_domain_add_linear(bank->of_node,
+ nr_eints, &s3c64xx_gpio_irqd_ops, bank);
+ if (!bank->irq_domain) {
+ dev_err(dev, "gpio irq domain add failed\n");
+ return -ENXIO;
+ }
+
+ ++nr_domains;
+ }
+
+ data = devm_kzalloc(dev, sizeof(*data)
+ + nr_domains * sizeof(*data->domains), GFP_KERNEL);
+ if (!data) {
+ dev_err(dev, "failed to allocate handler data\n");
+ return -ENOMEM;
+ }
+ data->drvdata = d;
+
+ bank = d->ctrl->pin_banks;
+ nr_domains = 0;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ if (bank->eint_type != EINT_TYPE_GPIO)
+ continue;
+
+ data->domains[nr_domains++] = bank->irq_domain;
+ }
+
+ irq_set_chained_handler(d->irq, s3c64xx_eint_gpio_irq);
+ irq_set_handler_data(d->irq, data);
+
+ return 0;
+}
+
+/*
+ * Functions for configuration of EINT0 wake-up interrupts
+ */
+
+static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask)
+{
+ struct s3c64xx_eint0_domain_data *ddata =
+ irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+ u32 val;
+
+ val = readl(d->virt_base + EINT0MASK_REG);
+ if (mask)
+ val |= 1 << ddata->eints[irqd->hwirq];
+ else
+ val &= ~(1 << ddata->eints[irqd->hwirq]);
+ writel(val, d->virt_base + EINT0MASK_REG);
+}
+
+static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd)
+{
+ s3c64xx_eint0_irq_set_mask(irqd, false);
+}
+
+static void s3c64xx_eint0_irq_mask(struct irq_data *irqd)
+{
+ s3c64xx_eint0_irq_set_mask(irqd, true);
+}
+
+static void s3c64xx_eint0_irq_ack(struct irq_data *irqd)
+{
+ struct s3c64xx_eint0_domain_data *ddata =
+ irq_data_get_irq_chip_data(irqd);
+ struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata;
+
+ writel(1 << ddata->eints[irqd->hwirq],
+ d->virt_base + EINT0PEND_REG);
+}
+
+static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type)
+{
+ struct s3c64xx_eint0_domain_data *ddata =
+ irq_data_get_irq_chip_data(irqd);
+ struct samsung_pin_bank *bank = ddata->bank;
+ struct samsung_pinctrl_drv_data *d = bank->drvdata;
+ void __iomem *reg;
+ int trigger;
+ u8 shift;
+ u32 val;
+
+ trigger = s3c64xx_irq_get_trigger(type);
+ if (trigger < 0) {
+ pr_err("unsupported external interrupt type\n");
+ return -EINVAL;
+ }
+
+ s3c64xx_irq_set_handler(irqd->irq, type);
+
+ /* Set up interrupt trigger */
+ reg = d->virt_base + EINT0CON0_REG;
+ shift = ddata->eints[irqd->hwirq];
+ if (shift >= EINT_MAX_PER_REG) {
+ reg += 4;
+ shift -= EINT_MAX_PER_REG;
+ }
+ shift = EINT_CON_LEN * (shift / 2);
+
+ val = readl(reg);
+ val &= ~(EINT_CON_MASK << shift);
+ val |= trigger << shift;
+ writel(val, reg);
+
+ s3c64xx_irq_set_function(d, bank, irqd->hwirq);
+
+ return 0;
+}
+
+/*
+ * irq_chip for wakeup interrupts
+ */
+static struct irq_chip s3c64xx_eint0_irq_chip = {
+ .name = "EINT0",
+ .irq_unmask = s3c64xx_eint0_irq_unmask,
+ .irq_mask = s3c64xx_eint0_irq_mask,
+ .irq_ack = s3c64xx_eint0_irq_ack,
+ .irq_set_type = s3c64xx_eint0_irq_set_type,
+};
+
+static inline void s3c64xx_irq_demux_eint(unsigned int irq,
+ struct irq_desc *desc, u32 range)
+{
+ struct irq_chip *chip = irq_get_chip(irq);
+ struct s3c64xx_eint0_data *data = irq_get_handler_data(irq);
+ struct samsung_pinctrl_drv_data *drvdata = data->drvdata;
+ unsigned int pend, mask;
+
+ chained_irq_enter(chip, desc);
+
+ pend = readl(drvdata->virt_base + EINT0PEND_REG);
+ mask = readl(drvdata->virt_base + EINT0MASK_REG);
+
+ pend = pend & range & ~mask;
+ pend &= range;
+
+ while (pend) {
+ unsigned int virq;
+
+ irq = fls(pend) - 1;
+ pend &= ~(1 << irq);
+
+ virq = irq_linear_revmap(data->domains[irq], data->pins[irq]);
+ /*
+ * Something must be really wrong if an unmapped EINT
+ * was unmasked...
+ */
+ BUG_ON(!virq);
+
+ generic_handle_irq(virq);
+ }
+
+ chained_irq_exit(chip, desc);
+}
+
+static void s3c64xx_demux_eint0_3(unsigned int irq, struct irq_desc *desc)
+{
+ s3c64xx_irq_demux_eint(irq, desc, 0xf);
+}
+
+static void s3c64xx_demux_eint4_11(unsigned int irq, struct irq_desc *desc)
+{
+ s3c64xx_irq_demux_eint(irq, desc, 0xff0);
+}
+
+static void s3c64xx_demux_eint12_19(unsigned int irq, struct irq_desc *desc)
+{
+ s3c64xx_irq_demux_eint(irq, desc, 0xff000);
+}
+
+static void s3c64xx_demux_eint20_27(unsigned int irq, struct irq_desc *desc)
+{
+ s3c64xx_irq_demux_eint(irq, desc, 0xff00000);
+}
+
+static irq_flow_handler_t s3c64xx_eint0_handlers[NUM_EINT0_IRQ] = {
+ s3c64xx_demux_eint0_3,
+ s3c64xx_demux_eint4_11,
+ s3c64xx_demux_eint12_19,
+ s3c64xx_demux_eint20_27,
+};
+
+static int s3c64xx_eint0_irq_map(struct irq_domain *h, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct s3c64xx_eint0_domain_data *ddata = h->host_data;
+ struct samsung_pin_bank *bank = ddata->bank;
+
+ if (!(bank->eint_mask & (1 << hw)))
+ return -EINVAL;
+
+ irq_set_chip_and_handler(virq,
+ &s3c64xx_eint0_irq_chip, handle_level_irq);
+ irq_set_chip_data(virq, ddata);
+ set_irq_flags(virq, IRQF_VALID);
+
+ return 0;
+}
+
+/*
+ * irq domain callbacks for external wakeup interrupt controller.
+ */
+static const struct irq_domain_ops s3c64xx_eint0_irqd_ops = {
+ .map = s3c64xx_eint0_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+/* list of external wakeup controllers supported */
+static const struct of_device_id s3c64xx_eint0_irq_ids[] = {
+ { .compatible = "samsung,s3c64xx-wakeup-eint", },
+ { }
+};
+
+/**
+ * s3c64xx_eint_eint0_init() - setup handling of external wakeup interrupts.
+ * @d: driver data of samsung pinctrl driver.
+ */
+static int s3c64xx_eint_eint0_init(struct samsung_pinctrl_drv_data *d)
+{
+ struct device *dev = d->dev;
+ struct device_node *eint0_np = NULL;
+ struct device_node *np;
+ struct samsung_pin_bank *bank;
+ struct s3c64xx_eint0_data *data;
+ unsigned int i;
+
+ for_each_child_of_node(dev->of_node, np) {
+ if (of_match_node(s3c64xx_eint0_irq_ids, np)) {
+ eint0_np = np;
+ break;
+ }
+ }
+ if (!eint0_np)
+ return -ENODEV;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(dev, "could not allocate memory for wkup eint data\n");
+ return -ENOMEM;
+ }
+ data->drvdata = d;
+
+ for (i = 0; i < NUM_EINT0_IRQ; ++i) {
+ unsigned int irq;
+
+ irq = irq_of_parse_and_map(eint0_np, i);
+ if (!irq) {
+ dev_err(dev, "failed to get wakeup EINT IRQ %d\n", i);
+ return -ENXIO;
+ }
+
+ irq_set_chained_handler(irq, s3c64xx_eint0_handlers[i]);
+ irq_set_handler_data(irq, data);
+ }
+
+ bank = d->ctrl->pin_banks;
+ for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+ struct s3c64xx_eint0_domain_data *ddata;
+ unsigned int nr_eints;
+ unsigned int mask;
+ unsigned int irq;
+ unsigned int pin;
+
+ if (bank->eint_type != EINT_TYPE_WKUP)
+ continue;
+
+ mask = bank->eint_mask;
+ nr_eints = fls(mask);
+
+ ddata = devm_kzalloc(dev,
+ sizeof(*ddata) + nr_eints, GFP_KERNEL);
+ if (!ddata) {
+ dev_err(dev, "failed to allocate domain data\n");
+ return -ENOMEM;
+ }
+ ddata->bank = bank;
+
+ bank->irq_domain = irq_domain_add_linear(bank->of_node,
+ nr_eints, &s3c64xx_eint0_irqd_ops, ddata);
+ if (!bank->irq_domain) {
+ dev_err(dev, "wkup irq domain add failed\n");
+ return -ENXIO;
+ }
+
+ irq = bank->eint_offset;
+ mask = bank->eint_mask;
+ for (pin = 0; mask; ++pin, mask >>= 1) {
+ if (!(mask & 1))
+ continue;
+ data->domains[irq] = bank->irq_domain;
+ data->pins[irq] = pin;
+ ddata->eints[pin] = irq;
+ ++irq;
+ }
+ }
+
+ return 0;
+}
+
+/* pin banks of s3c64xx pin-controller 0 */
+static struct samsung_pin_bank s3c64xx_pin_banks0[] = {
+ PIN_BANK_4BIT_EINTG(8, 0x000, "gpa", 0),
+ PIN_BANK_4BIT_EINTG(7, 0x020, "gpb", 8),
+ PIN_BANK_4BIT_EINTG(8, 0x040, "gpc", 16),
+ PIN_BANK_4BIT_EINTG(5, 0x060, "gpd", 32),
+ PIN_BANK_4BIT(5, 0x080, "gpe"),
+ PIN_BANK_2BIT_EINTG(16, 0x0a0, "gpf", 48, 0x3fff),
+ PIN_BANK_4BIT_EINTG(7, 0x0c0, "gpg", 64),
+ PIN_BANK_4BIT2_EINTG(10, 0x0e0, "gph", 80),
+ PIN_BANK_2BIT(16, 0x100, "gpi"),
+ PIN_BANK_2BIT(12, 0x120, "gpj"),
+ PIN_BANK_4BIT2_ALIVE(16, 0x800, "gpk"),
+ PIN_BANK_4BIT2_EINTW(15, 0x810, "gpl", 16, 0x7f00),
+ PIN_BANK_4BIT_EINTW(6, 0x820, "gpm", 23, 0x1f),
+ PIN_BANK_2BIT_EINTW(16, 0x830, "gpn", 0),
+ PIN_BANK_2BIT_EINTG(16, 0x140, "gpo", 96, 0xffff),
+ PIN_BANK_2BIT_EINTG(15, 0x160, "gpp", 112, 0x7fff),
+ PIN_BANK_2BIT_EINTG(9, 0x180, "gpq", 128, 0x1ff),
+};
+
+/*
+ * Samsung pinctrl driver data for S3C64xx SoC. S3C64xx SoC includes
+ * one gpio/pin-mux/pinconfig controller.
+ */
+struct samsung_pin_ctrl s3c64xx_pin_ctrl[] = {
+ {
+ /* pin-controller instance 1 data */
+ .pin_banks = s3c64xx_pin_banks0,
+ .nr_banks = ARRAY_SIZE(s3c64xx_pin_banks0),
+ .eint_gpio_init = s3c64xx_eint_gpio_init,
+ .eint_wkup_init = s3c64xx_eint_eint0_init,
+ .label = "S3C64xx-GPIO",
+ },
+};
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index f206df1..4f54faf 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
#include "core.h"
#include "pinctrl-samsung.h"
@@ -214,7 +215,7 @@
}
/* list of pinctrl callbacks for the pinctrl core */
-static struct pinctrl_ops samsung_pctrl_ops = {
+static const struct pinctrl_ops samsung_pctrl_ops = {
.get_groups_count = samsung_get_group_count,
.get_group_name = samsung_get_group_name,
.get_group_pins = samsung_get_group_pins,
@@ -274,10 +275,6 @@
*offset = pin - b->pin_base;
if (bank)
*bank = b;
-
- /* some banks have two config registers in a single bank */
- if (*offset * b->func_width > BITS_PER_LONG)
- *reg += 4;
}
/* enable or disable a pinmux function */
@@ -289,6 +286,7 @@
struct samsung_pin_bank *bank;
void __iomem *reg;
u32 mask, shift, data, pin_offset, cnt;
+ unsigned long flags;
drvdata = pinctrl_dev_get_drvdata(pctldev);
pins = drvdata->pin_groups[group].pins;
@@ -298,16 +296,28 @@
* pin function number in the config register.
*/
for (cnt = 0; cnt < drvdata->pin_groups[group].num_pins; cnt++) {
+ struct samsung_pin_bank_type *type;
+
pin_to_reg_bank(drvdata, pins[cnt] - drvdata->ctrl->base,
®, &pin_offset, &bank);
- mask = (1 << bank->func_width) - 1;
- shift = pin_offset * bank->func_width;
+ type = bank->type;
+ mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+ shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
+ if (shift >= 32) {
+ /* Some banks have two config registers */
+ shift -= 32;
+ reg += 4;
+ }
- data = readl(reg);
+ spin_lock_irqsave(&bank->slock, flags);
+
+ data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]);
data &= ~(mask << shift);
if (enable)
data |= drvdata->pin_groups[group].func << shift;
- writel(data, reg);
+ writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]);
+
+ spin_unlock_irqrestore(&bank->slock, flags);
}
}
@@ -334,30 +344,44 @@
static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range, unsigned offset, bool input)
{
+ struct samsung_pin_bank_type *type;
struct samsung_pin_bank *bank;
struct samsung_pinctrl_drv_data *drvdata;
void __iomem *reg;
u32 data, pin_offset, mask, shift;
+ unsigned long flags;
bank = gc_to_pin_bank(range->gc);
+ type = bank->type;
drvdata = pinctrl_dev_get_drvdata(pctldev);
pin_offset = offset - bank->pin_base;
- reg = drvdata->virt_base + bank->pctl_offset;
+ reg = drvdata->virt_base + bank->pctl_offset +
+ type->reg_offset[PINCFG_TYPE_FUNC];
- mask = (1 << bank->func_width) - 1;
- shift = pin_offset * bank->func_width;
+ mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+ shift = pin_offset * type->fld_width[PINCFG_TYPE_FUNC];
+ if (shift >= 32) {
+ /* Some banks have two config registers */
+ shift -= 32;
+ reg += 4;
+ }
+
+ spin_lock_irqsave(&bank->slock, flags);
data = readl(reg);
data &= ~(mask << shift);
if (!input)
data |= FUNC_OUTPUT << shift;
writel(data, reg);
+
+ spin_unlock_irqrestore(&bank->slock, flags);
+
return 0;
}
/* list of pinmux callbacks for the pinmux vertical in pinctrl core */
-static struct pinmux_ops samsung_pinmux_ops = {
+static const struct pinmux_ops samsung_pinmux_ops = {
.get_functions_count = samsung_get_functions_count,
.get_function_name = samsung_pinmux_get_fname,
.get_function_groups = samsung_pinmux_get_groups,
@@ -371,40 +395,26 @@
unsigned long *config, bool set)
{
struct samsung_pinctrl_drv_data *drvdata;
+ struct samsung_pin_bank_type *type;
struct samsung_pin_bank *bank;
void __iomem *reg_base;
enum pincfg_type cfg_type = PINCFG_UNPACK_TYPE(*config);
u32 data, width, pin_offset, mask, shift;
u32 cfg_value, cfg_reg;
+ unsigned long flags;
drvdata = pinctrl_dev_get_drvdata(pctldev);
pin_to_reg_bank(drvdata, pin - drvdata->ctrl->base, ®_base,
&pin_offset, &bank);
+ type = bank->type;
- switch (cfg_type) {
- case PINCFG_TYPE_PUD:
- width = bank->pud_width;
- cfg_reg = PUD_REG;
- break;
- case PINCFG_TYPE_DRV:
- width = bank->drv_width;
- cfg_reg = DRV_REG;
- break;
- case PINCFG_TYPE_CON_PDN:
- width = bank->conpdn_width;
- cfg_reg = CONPDN_REG;
- break;
- case PINCFG_TYPE_PUD_PDN:
- width = bank->pudpdn_width;
- cfg_reg = PUDPDN_REG;
- break;
- default:
- WARN_ON(1);
+ if (cfg_type >= PINCFG_TYPE_NUM || !type->fld_width[cfg_type])
return -EINVAL;
- }
- if (!width)
- return -EINVAL;
+ width = type->fld_width[cfg_type];
+ cfg_reg = type->reg_offset[cfg_type];
+
+ spin_lock_irqsave(&bank->slock, flags);
mask = (1 << width) - 1;
shift = pin_offset * width;
@@ -420,6 +430,9 @@
data &= mask;
*config = PINCFG_PACK(cfg_type, data);
}
+
+ spin_unlock_irqrestore(&bank->slock, flags);
+
return 0;
}
@@ -468,7 +481,7 @@
}
/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code */
-static struct pinconf_ops samsung_pinconf_ops = {
+static const struct pinconf_ops samsung_pinconf_ops = {
.pin_config_get = samsung_pinconf_get,
.pin_config_set = samsung_pinconf_set,
.pin_config_group_get = samsung_pinconf_group_get,
@@ -479,16 +492,22 @@
static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
{
struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+ struct samsung_pin_bank_type *type = bank->type;
+ unsigned long flags;
void __iomem *reg;
u32 data;
reg = bank->drvdata->virt_base + bank->pctl_offset;
- data = readl(reg + DAT_REG);
+ spin_lock_irqsave(&bank->slock, flags);
+
+ data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
data &= ~(1 << offset);
if (value)
data |= 1 << offset;
- writel(data, reg + DAT_REG);
+ writel(data, reg + type->reg_offset[PINCFG_TYPE_DAT]);
+
+ spin_unlock_irqrestore(&bank->slock, flags);
}
/* gpiolib gpio_get callback function */
@@ -497,10 +516,11 @@
void __iomem *reg;
u32 data;
struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+ struct samsung_pin_bank_type *type = bank->type;
reg = bank->drvdata->virt_base + bank->pctl_offset;
- data = readl(reg + DAT_REG);
+ data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]);
data >>= offset;
data &= 1;
return data;
@@ -859,6 +879,7 @@
bank = ctrl->pin_banks;
for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+ spin_lock_init(&bank->slock);
bank->drvdata = d;
bank->pin_base = ctrl->nr_pins;
ctrl->nr_pins += bank->nr_pins;
@@ -944,10 +965,16 @@
}
static const struct of_device_id samsung_pinctrl_dt_match[] = {
+#ifdef CONFIG_PINCTRL_EXYNOS
{ .compatible = "samsung,exynos4210-pinctrl",
.data = (void *)exynos4210_pin_ctrl },
{ .compatible = "samsung,exynos4x12-pinctrl",
.data = (void *)exynos4x12_pin_ctrl },
+#endif
+#ifdef CONFIG_PINCTRL_S3C64XX
+ { .compatible = "samsung,s3c64xx-pinctrl",
+ .data = s3c64xx_pin_ctrl },
+#endif
{},
};
MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e2d4e67..45f27b4 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -25,28 +25,27 @@
#include <linux/gpio.h>
-/* register offsets within a pin bank */
-#define DAT_REG 0x4
-#define PUD_REG 0x8
-#define DRV_REG 0xC
-#define CONPDN_REG 0x10
-#define PUDPDN_REG 0x14
-
/* pinmux function number for pin as gpio output line */
#define FUNC_OUTPUT 0x1
/**
* enum pincfg_type - possible pin configuration types supported.
+ * @PINCFG_TYPE_FUNC: Function configuration.
+ * @PINCFG_TYPE_DAT: Pin value configuration.
* @PINCFG_TYPE_PUD: Pull up/down configuration.
* @PINCFG_TYPE_DRV: Drive strength configuration.
* @PINCFG_TYPE_CON_PDN: Pin function in power down mode.
* @PINCFG_TYPE_PUD_PDN: Pull up/down configuration in power down mode.
*/
enum pincfg_type {
+ PINCFG_TYPE_FUNC,
+ PINCFG_TYPE_DAT,
PINCFG_TYPE_PUD,
PINCFG_TYPE_DRV,
PINCFG_TYPE_CON_PDN,
PINCFG_TYPE_PUD_PDN,
+
+ PINCFG_TYPE_NUM
};
/*
@@ -103,33 +102,40 @@
struct samsung_pinctrl_drv_data;
/**
+ * struct samsung_pin_bank_type: pin bank type description
+ * @fld_width: widths of configuration bitfields (0 if unavailable)
+ * @reg_offset: offsets of configuration registers (don't care of width is 0)
+ */
+struct samsung_pin_bank_type {
+ u8 fld_width[PINCFG_TYPE_NUM];
+ u8 reg_offset[PINCFG_TYPE_NUM];
+};
+
+/**
* struct samsung_pin_bank: represent a controller pin-bank.
+ * @type: type of the bank (register offsets and bitfield widths)
* @pctl_offset: starting offset of the pin-bank registers.
* @pin_base: starting pin number of the bank.
* @nr_pins: number of pins included in this bank.
- * @func_width: width of the function selector bit field.
- * @pud_width: width of the pin pull up/down selector bit field.
- * @drv_width: width of the pin driver strength selector bit field.
- * @conpdn_width: width of the sleep mode function selector bin field.
- * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
+ * @eint_func: function to set in CON register to configure pin as EINT.
* @eint_type: type of the external interrupt supported by the bank.
+ * @eint_mask: bit mask of pins which support EINT function.
* @name: name to be prefixed for each pin in this pin bank.
* @of_node: OF node of the bank.
* @drvdata: link to controller driver data
* @irq_domain: IRQ domain of the bank.
* @gpio_chip: GPIO chip of the bank.
* @grange: linux gpio pin range supported by this bank.
+ * @slock: spinlock protecting bank registers
*/
struct samsung_pin_bank {
+ struct samsung_pin_bank_type *type;
u32 pctl_offset;
u32 pin_base;
u8 nr_pins;
- u8 func_width;
- u8 pud_width;
- u8 drv_width;
- u8 conpdn_width;
- u8 pudpdn_width;
+ u8 eint_func;
enum eint_type eint_type;
+ u32 eint_mask;
u32 eint_offset;
char *name;
struct device_node *of_node;
@@ -137,6 +143,7 @@
struct irq_domain *irq_domain;
struct gpio_chip gpio_chip;
struct pinctrl_gpio_range grange;
+ spinlock_t slock;
};
/**
@@ -237,5 +244,6 @@
/* list of all exported SoC specific data */
extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
+extern struct samsung_pin_ctrl s3c64xx_pin_ctrl[];
#endif /* __PINCTRL_SAMSUNG_H */
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 5c32e88..5f2d2bf 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -22,8 +22,10 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include "core.h"
+#include "pinconf.h"
#define DRIVER_NAME "pinctrl-single"
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
@@ -59,6 +61,33 @@
};
/**
+ * struct pcs_conf_vals - pinconf parameter, pinconf register offset
+ * and value, enable, disable, mask
+ * @param: config parameter
+ * @val: user input bits in the pinconf register
+ * @enable: enable bits in the pinconf register
+ * @disable: disable bits in the pinconf register
+ * @mask: mask bits in the register value
+ */
+struct pcs_conf_vals {
+ enum pin_config_param param;
+ unsigned val;
+ unsigned enable;
+ unsigned disable;
+ unsigned mask;
+};
+
+/**
+ * struct pcs_conf_type - pinconf property name, pinconf param pair
+ * @name: property name in DTS file
+ * @param: config parameter
+ */
+struct pcs_conf_type {
+ const char *name;
+ enum pin_config_param param;
+};
+
+/**
* struct pcs_function - pinctrl function
* @name: pinctrl function name
* @vals: register and vals array
@@ -73,6 +102,22 @@
unsigned nvals;
const char **pgnames;
int npgnames;
+ struct pcs_conf_vals *conf;
+ int nconfs;
+ struct list_head node;
+};
+
+/**
+ * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
+ * @offset: offset base of pins
+ * @npins: number pins with the same mux value of gpio function
+ * @gpiofunc: mux value of gpio function
+ * @node: list node
+ */
+struct pcs_gpiofunc_range {
+ unsigned offset;
+ unsigned npins;
+ unsigned gpiofunc;
struct list_head node;
};
@@ -117,12 +162,14 @@
* @fshift: function register shift
* @foff: value to turn mux off
* @fmax: max number of functions in fmask
+ * @is_pinconf: whether supports pinconf
* @names: array of register names for pins
* @pins: physical pins on the SoC
* @pgtree: pingroup index radix tree
* @ftree: function index radix tree
* @pingroups: list of pingroups
* @functions: list of functions
+ * @gpiofuncs: list of gpio functions
* @ngroups: number of pingroups
* @nfuncs: number of functions
* @desc: pin controller descriptor
@@ -142,12 +189,14 @@
unsigned foff;
unsigned fmax;
bool bits_per_mux;
+ bool is_pinconf;
struct pcs_name *names;
struct pcs_data pins;
struct radix_tree_root pgtree;
struct radix_tree_root ftree;
struct list_head pingroups;
struct list_head functions;
+ struct list_head gpiofuncs;
unsigned ngroups;
unsigned nfuncs;
struct pinctrl_desc desc;
@@ -155,6 +204,16 @@
void (*write)(unsigned val, void __iomem *reg);
};
+static int pcs_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config);
+static int pcs_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long config);
+
+static enum pin_config_param pcs_bias[] = {
+ PIN_CONFIG_BIAS_PULL_DOWN,
+ PIN_CONFIG_BIAS_PULL_UP,
+};
+
/*
* REVISIT: Reads and writes could eventually use regmap or something
* generic. But at least on omaps, some mux registers are performance
@@ -270,7 +329,7 @@
struct device_node *np_config,
struct pinctrl_map **map, unsigned *num_maps);
-static struct pinctrl_ops pcs_pinctrl_ops = {
+static const struct pinctrl_ops pcs_pinctrl_ops = {
.get_groups_count = pcs_get_groups_count,
.get_group_name = pcs_get_group_name,
.get_group_pins = pcs_get_group_pins,
@@ -326,6 +385,28 @@
return 0;
}
+static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
+ struct pcs_function **func)
+{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
+ const struct pinctrl_setting_mux *setting;
+ unsigned fselector;
+
+ /* If pin is not described in DTS & enabled, mux_setting is NULL. */
+ setting = pdesc->mux_setting;
+ if (!setting)
+ return -ENOTSUPP;
+ fselector = setting->func;
+ *func = radix_tree_lookup(&pcs->ftree, fselector);
+ if (!(*func)) {
+ dev_err(pcs->dev, "%s could not find function%i\n",
+ __func__, fselector);
+ return -ENOTSUPP;
+ }
+ return 0;
+}
+
static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
unsigned group)
{
@@ -334,6 +415,9 @@
int i;
pcs = pinctrl_dev_get_drvdata(pctldev);
+ /* If function mask is null, needn't enable it. */
+ if (!pcs->fmask)
+ return 0;
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func)
return -EINVAL;
@@ -368,6 +452,10 @@
int i;
pcs = pinctrl_dev_get_drvdata(pctldev);
+ /* If function mask is null, needn't disable it. */
+ if (!pcs->fmask)
+ return;
+
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func) {
dev_err(pcs->dev, "%s could not find function%i\n",
@@ -403,12 +491,33 @@
}
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range, unsigned offset)
+ struct pinctrl_gpio_range *range, unsigned pin)
{
- return -ENOTSUPP;
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_gpiofunc_range *frange = NULL;
+ struct list_head *pos, *tmp;
+ int mux_bytes = 0;
+ unsigned data;
+
+ /* If function mask is null, return directly. */
+ if (!pcs->fmask)
+ return -ENOTSUPP;
+
+ list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+ frange = list_entry(pos, struct pcs_gpiofunc_range, node);
+ if (pin >= frange->offset + frange->npins
+ || pin < frange->offset)
+ continue;
+ mux_bytes = pcs->width / BITS_PER_BYTE;
+ data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+ data |= frange->gpiofunc;
+ pcs->write(data, pcs->base + pin * mux_bytes);
+ break;
+ }
+ return 0;
}
-static struct pinmux_ops pcs_pinmux_ops = {
+static const struct pinmux_ops pcs_pinmux_ops = {
.get_functions_count = pcs_get_functions_count,
.get_function_name = pcs_get_function_name,
.get_function_groups = pcs_get_function_groups,
@@ -417,32 +526,190 @@
.gpio_request_enable = pcs_request_gpio,
};
+/* Clear BIAS value */
+static void pcs_pinconf_clear_bias(struct pinctrl_dev *pctldev, unsigned pin)
+{
+ unsigned long config;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
+ config = pinconf_to_config_packed(pcs_bias[i], 0);
+ pcs_pinconf_set(pctldev, pin, config);
+ }
+}
+
+/*
+ * Check whether PIN_CONFIG_BIAS_DISABLE is valid.
+ * It's depend on that PULL_DOWN & PULL_UP configs are all invalid.
+ */
+static bool pcs_pinconf_bias_disable(struct pinctrl_dev *pctldev, unsigned pin)
+{
+ unsigned long config;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pcs_bias); i++) {
+ config = pinconf_to_config_packed(pcs_bias[i], 0);
+ if (!pcs_pinconf_get(pctldev, pin, &config))
+ goto out;
+ }
+ return true;
+out:
+ return false;
+}
+
static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long *config)
{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_function *func;
+ enum pin_config_param param;
+ unsigned offset = 0, data = 0, i, j, ret;
+
+ ret = pcs_get_function(pctldev, pin, &func);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < func->nconfs; i++) {
+ param = pinconf_to_config_param(*config);
+ if (param == PIN_CONFIG_BIAS_DISABLE) {
+ if (pcs_pinconf_bias_disable(pctldev, pin)) {
+ *config = 0;
+ return 0;
+ } else {
+ return -ENOTSUPP;
+ }
+ } else if (param != func->conf[i].param) {
+ continue;
+ }
+
+ offset = pin * (pcs->width / BITS_PER_BYTE);
+ data = pcs->read(pcs->base + offset) & func->conf[i].mask;
+ switch (func->conf[i].param) {
+ /* 4 parameters */
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if ((data != func->conf[i].enable) ||
+ (data == func->conf[i].disable))
+ return -ENOTSUPP;
+ *config = 0;
+ break;
+ /* 2 parameters */
+ case PIN_CONFIG_INPUT_SCHMITT:
+ for (j = 0; j < func->nconfs; j++) {
+ switch (func->conf[j].param) {
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ if (data != func->conf[j].enable)
+ return -ENOTSUPP;
+ break;
+ default:
+ break;
+ }
+ }
+ *config = data;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ case PIN_CONFIG_SLEW_RATE:
+ default:
+ *config = data;
+ break;
+ }
+ return 0;
+ }
return -ENOTSUPP;
}
static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long config)
{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_function *func;
+ unsigned offset = 0, shift = 0, i, data, ret;
+ u16 arg;
+
+ ret = pcs_get_function(pctldev, pin, &func);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < func->nconfs; i++) {
+ if (pinconf_to_config_param(config) == func->conf[i].param) {
+ offset = pin * (pcs->width / BITS_PER_BYTE);
+ data = pcs->read(pcs->base + offset);
+ arg = pinconf_to_config_argument(config);
+ switch (func->conf[i].param) {
+ /* 2 parameters */
+ case PIN_CONFIG_INPUT_SCHMITT:
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ case PIN_CONFIG_SLEW_RATE:
+ shift = ffs(func->conf[i].mask) - 1;
+ data &= ~func->conf[i].mask;
+ data |= (arg << shift) & func->conf[i].mask;
+ break;
+ /* 4 parameters */
+ case PIN_CONFIG_BIAS_DISABLE:
+ pcs_pinconf_clear_bias(pctldev, pin);
+ break;
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ if (arg)
+ pcs_pinconf_clear_bias(pctldev, pin);
+ /* fall through */
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ data &= ~func->conf[i].mask;
+ if (arg)
+ data |= func->conf[i].enable;
+ else
+ data |= func->conf[i].disable;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ pcs->write(data, pcs->base + offset);
+ return 0;
+ }
+ }
return -ENOTSUPP;
}
static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
unsigned group, unsigned long *config)
{
- return -ENOTSUPP;
+ const unsigned *pins;
+ unsigned npins, old = 0;
+ int i, ret;
+
+ ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+ for (i = 0; i < npins; i++) {
+ if (pcs_pinconf_get(pctldev, pins[i], config))
+ return -ENOTSUPP;
+ /* configs do not match between two pins */
+ if (i && (old != *config))
+ return -ENOTSUPP;
+ old = *config;
+ }
+ return 0;
}
static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
unsigned group, unsigned long config)
{
- return -ENOTSUPP;
+ const unsigned *pins;
+ unsigned npins;
+ int i, ret;
+
+ ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+ for (i = 0; i < npins; i++) {
+ if (pcs_pinconf_set(pctldev, pins[i], config))
+ return -ENOTSUPP;
+ }
+ return 0;
}
static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
- struct seq_file *s, unsigned offset)
+ struct seq_file *s, unsigned pin)
{
}
@@ -451,13 +718,22 @@
{
}
-static struct pinconf_ops pcs_pinconf_ops = {
+static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config)
+{
+ pinconf_generic_dump_config(pctldev, s, config);
+}
+
+static const struct pinconf_ops pcs_pinconf_ops = {
.pin_config_get = pcs_pinconf_get,
.pin_config_set = pcs_pinconf_set,
.pin_config_group_get = pcs_pinconf_group_get,
.pin_config_group_set = pcs_pinconf_group_set,
.pin_config_dbg_show = pcs_pinconf_dbg_show,
.pin_config_group_dbg_show = pcs_pinconf_group_dbg_show,
+ .pin_config_config_dbg_show = pcs_pinconf_config_dbg_show,
+ .is_generic = true,
};
/**
@@ -648,11 +924,158 @@
return index;
}
+/*
+ * check whether data matches enable bits or disable bits
+ * Return value: 1 for matching enable bits, 0 for matching disable bits,
+ * and negative value for matching failure.
+ */
+static int pcs_config_match(unsigned data, unsigned enable, unsigned disable)
+{
+ int ret = -EINVAL;
+
+ if (data == enable)
+ ret = 1;
+ else if (data == disable)
+ ret = 0;
+ return ret;
+}
+
+static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
+ unsigned value, unsigned enable, unsigned disable,
+ unsigned mask)
+{
+ (*conf)->param = param;
+ (*conf)->val = value;
+ (*conf)->enable = enable;
+ (*conf)->disable = disable;
+ (*conf)->mask = mask;
+ (*conf)++;
+}
+
+static void add_setting(unsigned long **setting, enum pin_config_param param,
+ unsigned arg)
+{
+ **setting = pinconf_to_config_packed(param, arg);
+ (*setting)++;
+}
+
+/* add pinconf setting with 2 parameters */
+static void pcs_add_conf2(struct pcs_device *pcs, struct device_node *np,
+ const char *name, enum pin_config_param param,
+ struct pcs_conf_vals **conf, unsigned long **settings)
+{
+ unsigned value[2], shift;
+ int ret;
+
+ ret = of_property_read_u32_array(np, name, value, 2);
+ if (ret)
+ return;
+ /* set value & mask */
+ value[0] &= value[1];
+ shift = ffs(value[1]) - 1;
+ /* skip enable & disable */
+ add_config(conf, param, value[0], 0, 0, value[1]);
+ add_setting(settings, param, value[0] >> shift);
+}
+
+/* add pinconf setting with 4 parameters */
+static void pcs_add_conf4(struct pcs_device *pcs, struct device_node *np,
+ const char *name, enum pin_config_param param,
+ struct pcs_conf_vals **conf, unsigned long **settings)
+{
+ unsigned value[4];
+ int ret;
+
+ /* value to set, enable, disable, mask */
+ ret = of_property_read_u32_array(np, name, value, 4);
+ if (ret)
+ return;
+ if (!value[3]) {
+ dev_err(pcs->dev, "mask field of the property can't be 0\n");
+ return;
+ }
+ value[0] &= value[3];
+ value[1] &= value[3];
+ value[2] &= value[3];
+ ret = pcs_config_match(value[0], value[1], value[2]);
+ if (ret < 0)
+ dev_dbg(pcs->dev, "failed to match enable or disable bits\n");
+ add_config(conf, param, value[0], value[1], value[2], value[3]);
+ add_setting(settings, param, ret);
+}
+
+static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
+ struct pcs_function *func,
+ struct pinctrl_map **map)
+
+{
+ struct pinctrl_map *m = *map;
+ int i = 0, nconfs = 0;
+ unsigned long *settings = NULL, *s = NULL;
+ struct pcs_conf_vals *conf = NULL;
+ struct pcs_conf_type prop2[] = {
+ { "pinctrl-single,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, },
+ { "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
+ { "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
+ };
+ struct pcs_conf_type prop4[] = {
+ { "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
+ { "pinctrl-single,bias-pulldown", PIN_CONFIG_BIAS_PULL_DOWN, },
+ { "pinctrl-single,input-schmitt-enable",
+ PIN_CONFIG_INPUT_SCHMITT_ENABLE, },
+ };
+
+ /* If pinconf isn't supported, don't parse properties in below. */
+ if (!pcs->is_pinconf)
+ return 0;
+
+ /* cacluate how much properties are supported in current node */
+ for (i = 0; i < ARRAY_SIZE(prop2); i++) {
+ if (of_find_property(np, prop2[i].name, NULL))
+ nconfs++;
+ }
+ for (i = 0; i < ARRAY_SIZE(prop4); i++) {
+ if (of_find_property(np, prop4[i].name, NULL))
+ nconfs++;
+ }
+ if (!nconfs)
+ return 0;
+
+ func->conf = devm_kzalloc(pcs->dev,
+ sizeof(struct pcs_conf_vals) * nconfs,
+ GFP_KERNEL);
+ if (!func->conf)
+ return -ENOMEM;
+ func->nconfs = nconfs;
+ conf = &(func->conf[0]);
+ m++;
+ settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs,
+ GFP_KERNEL);
+ if (!settings)
+ return -ENOMEM;
+ s = &settings[0];
+
+ for (i = 0; i < ARRAY_SIZE(prop2); i++)
+ pcs_add_conf2(pcs, np, prop2[i].name, prop2[i].param,
+ &conf, &s);
+ for (i = 0; i < ARRAY_SIZE(prop4); i++)
+ pcs_add_conf4(pcs, np, prop4[i].name, prop4[i].param,
+ &conf, &s);
+ m->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ m->data.configs.group_or_pin = np->name;
+ m->data.configs.configs = settings;
+ m->data.configs.num_configs = nconfs;
+ return 0;
+}
+
+static void pcs_free_pingroups(struct pcs_device *pcs);
+
/**
* smux_parse_one_pinctrl_entry() - parses a device tree mux entry
* @pcs: pinctrl driver instance
* @np: device node of the mux entry
* @map: map entry
+ * @num_maps: number of map
* @pgnames: pingroup names
*
* Note that this binding currently supports only sets of one register + value.
@@ -669,6 +1092,7 @@
static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
struct device_node *np,
struct pinctrl_map **map,
+ unsigned *num_maps,
const char **pgnames)
{
struct pcs_func_vals *vals;
@@ -741,8 +1165,18 @@
(*map)->data.mux.group = np->name;
(*map)->data.mux.function = np->name;
+ if (pcs->is_pinconf) {
+ if (pcs_parse_pinconf(pcs, np, function, map))
+ goto free_pingroups;
+ *num_maps = 2;
+ } else {
+ *num_maps = 1;
+ }
return 0;
+free_pingroups:
+ pcs_free_pingroups(pcs);
+ *num_maps = 1;
free_function:
pcs_remove_function(pcs, function);
@@ -771,7 +1205,8 @@
pcs = pinctrl_dev_get_drvdata(pctldev);
- *map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
+ /* create 2 maps. One is for pinmux, and the other is for pinconf. */
+ *map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL);
if (!*map)
return -ENOMEM;
@@ -783,13 +1218,13 @@
goto free_map;
}
- ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, pgnames);
+ ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps,
+ pgnames);
if (ret < 0) {
dev_err(pcs->dev, "no pins entries for %s\n",
np_config->name);
goto free_pgnames;
}
- *num_maps = 1;
return 0;
@@ -879,6 +1314,37 @@
static struct of_device_id pcs_of_match[];
+static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
+{
+ const char *propname = "pinctrl-single,gpio-range";
+ const char *cellname = "#pinctrl-single,gpio-range-cells";
+ struct of_phandle_args gpiospec;
+ struct pcs_gpiofunc_range *range;
+ int ret, i;
+
+ for (i = 0; ; i++) {
+ ret = of_parse_phandle_with_args(node, propname, cellname,
+ i, &gpiospec);
+ /* Do not treat it as error. Only treat it as end condition. */
+ if (ret) {
+ ret = 0;
+ break;
+ }
+ range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
+ if (!range) {
+ ret = -ENOMEM;
+ break;
+ }
+ range->offset = gpiospec.args[0];
+ range->npins = gpiospec.args[1];
+ range->gpiofunc = gpiospec.args[2];
+ mutex_lock(&pcs->mutex);
+ list_add_tail(&range->node, &pcs->gpiofuncs);
+ mutex_unlock(&pcs->mutex);
+ }
+ return ret;
+}
+
static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -900,14 +1366,23 @@
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
INIT_LIST_HEAD(&pcs->functions);
+ INIT_LIST_HEAD(&pcs->gpiofuncs);
+ pcs->is_pinconf = match->data;
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
"register width not specified\n");
- PCS_GET_PROP_U32("pinctrl-single,function-mask", &pcs->fmask,
- "function register mask not specified\n");
- pcs->fshift = ffs(pcs->fmask) - 1;
- pcs->fmax = pcs->fmask >> pcs->fshift;
+ ret = of_property_read_u32(np, "pinctrl-single,function-mask",
+ &pcs->fmask);
+ if (!ret) {
+ pcs->fshift = ffs(pcs->fmask) - 1;
+ pcs->fmax = pcs->fmask >> pcs->fshift;
+ } else {
+ /* If mask property doesn't exist, function mux is invalid. */
+ pcs->fmask = 0;
+ pcs->fshift = 0;
+ pcs->fmax = 0;
+ }
ret = of_property_read_u32(np, "pinctrl-single,function-off",
&pcs->foff);
@@ -961,7 +1436,8 @@
pcs->desc.name = DRIVER_NAME;
pcs->desc.pctlops = &pcs_pinctrl_ops;
pcs->desc.pmxops = &pcs_pinmux_ops;
- pcs->desc.confops = &pcs_pinconf_ops;
+ if (pcs->is_pinconf)
+ pcs->desc.confops = &pcs_pinconf_ops;
pcs->desc.owner = THIS_MODULE;
ret = pcs_allocate_pin_table(pcs);
@@ -975,6 +1451,10 @@
goto free;
}
+ ret = pcs_add_gpio_func(np, pcs);
+ if (ret < 0)
+ goto free;
+
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
pcs->desc.npins, pcs->base, pcs->size);
@@ -999,7 +1479,8 @@
}
static struct of_device_id pcs_of_match[] = {
- { .compatible = DRIVER_NAME, },
+ { .compatible = "pinctrl-single", .data = (void *)false },
+ { .compatible = "pinconf-single", .data = (void *)true },
{ },
};
MODULE_DEVICE_TABLE(of, pcs_of_match);
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c
index d02498b..fb90625 100644
--- a/drivers/pinctrl/pinctrl-sirf.c
+++ b/drivers/pinctrl/pinctrl-sirf.c
@@ -979,7 +979,7 @@
kfree(map);
}
-static struct pinctrl_ops sirfsoc_pctrl_ops = {
+static const struct pinctrl_ops sirfsoc_pctrl_ops = {
.get_groups_count = sirfsoc_get_groups_count,
.get_group_name = sirfsoc_get_group_name,
.get_group_pins = sirfsoc_get_group_pins,
@@ -1181,7 +1181,7 @@
return 0;
}
-static struct pinmux_ops sirfsoc_pinmux_ops = {
+static const struct pinmux_ops sirfsoc_pinmux_ops = {
.enable = sirfsoc_pinmux_enable,
.disable = sirfsoc_pinmux_disable,
.get_functions_count = sirfsoc_pinmux_get_funcs_count,
@@ -1685,15 +1685,12 @@
const unsigned long *p = (const unsigned long *)pullups;
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
- n = find_first_bit(p + i, BITS_PER_LONG);
- while (n < BITS_PER_LONG) {
+ for_each_set_bit(n, p + i, BITS_PER_LONG) {
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
u32 val = readl(sgpio_bank[i].chip.regs + offset);
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
writel(val, sgpio_bank[i].chip.regs + offset);
-
- n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
}
}
}
@@ -1704,15 +1701,12 @@
const unsigned long *p = (const unsigned long *)pulldowns;
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
- n = find_first_bit(p + i, BITS_PER_LONG);
- while (n < BITS_PER_LONG) {
+ for_each_set_bit(n, p + i, BITS_PER_LONG) {
u32 offset = SIRFSOC_GPIO_CTRL(i, n);
u32 val = readl(sgpio_bank[i].chip.regs + offset);
val |= SIRFSOC_GPIO_CTL_PULL_MASK;
val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
writel(val, sgpio_bank[i].chip.regs + offset);
-
- n = find_next_bit(p + i, BITS_PER_LONG, n + 1);
}
}
}
diff --git a/drivers/pinctrl/pinctrl-sunxi.c b/drivers/pinctrl/pinctrl-sunxi.c
index 80b11e3..c52fc2c0 100644
--- a/drivers/pinctrl/pinctrl-sunxi.c
+++ b/drivers/pinctrl/pinctrl-sunxi.c
@@ -11,6 +11,7 @@
*/
#include <linux/io.h>
+#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -30,482 +31,856 @@
static const struct sunxi_desc_pin sun4i_a10_pins[] = {
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXD3 */
+ SUNXI_FUNCTION(0x3, "spi1"), /* CS0 */
+ SUNXI_FUNCTION(0x4, "uart2")), /* RTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXD2 */
+ SUNXI_FUNCTION(0x3, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x4, "uart2")), /* CTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXD1 */
+ SUNXI_FUNCTION(0x3, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x4, "uart2")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXD0 */
+ SUNXI_FUNCTION(0x3, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x4, "uart2")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXD3 */
+ SUNXI_FUNCTION(0x3, "spi1")), /* CS1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXD2 */
+ SUNXI_FUNCTION(0x3, "spi3")), /* CS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXD1 */
+ SUNXI_FUNCTION(0x3, "spi3")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXD0 */
+ SUNXI_FUNCTION(0x3, "spi3")), /* MOSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXCK */
+ SUNXI_FUNCTION(0x3, "spi3")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXERR */
+ SUNXI_FUNCTION(0x3, "spi3")), /* CS1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA10,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ERXDV */
SUNXI_FUNCTION(0x4, "uart1")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA11,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* EMDC */
SUNXI_FUNCTION(0x4, "uart1")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA12,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* EMDIO */
+ SUNXI_FUNCTION(0x3, "uart6"), /* TX */
SUNXI_FUNCTION(0x4, "uart1")), /* RTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA13,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXEN */
+ SUNXI_FUNCTION(0x3, "uart6"), /* RX */
SUNXI_FUNCTION(0x4, "uart1")), /* CTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA14,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXCK */
+ SUNXI_FUNCTION(0x3, "uart7"), /* TX */
SUNXI_FUNCTION(0x4, "uart1")), /* DTR */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA15,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ECRS */
+ SUNXI_FUNCTION(0x3, "uart7"), /* RX */
SUNXI_FUNCTION(0x4, "uart1")), /* DSR */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA16,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ECOL */
+ SUNXI_FUNCTION(0x3, "can"), /* TX */
SUNXI_FUNCTION(0x4, "uart1")), /* DCD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PA17,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac"), /* ETXERR */
+ SUNXI_FUNCTION(0x3, "can"), /* RX */
SUNXI_FUNCTION(0x4, "uart1")), /* RING */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm")), /* PWM0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ir0")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ir0")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "ac97")), /* MCLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s"), /* BCLK */
+ SUNXI_FUNCTION(0x3, "ac97")), /* BCLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s"), /* LRCK */
+ SUNXI_FUNCTION(0x3, "ac97")), /* SYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s"), /* DO0 */
+ SUNXI_FUNCTION(0x3, "ac97")), /* DO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s")), /* DO1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s")), /* DO2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s")), /* DO3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s"), /* DI */
+ SUNXI_FUNCTION(0x3, "ac97")), /* DI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2")), /* CS1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2"), /* CS0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2"), /* CLK */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2"), /* MISO */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB22,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart0")), /* TX */
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION(0x3, "ir1")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB23,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
- SUNXI_FUNCTION(0x2, "uart0")), /* RX */
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x3, "ir1")), /* RX */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NWE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NCE1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NCE0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NRE# */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NRB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NRB1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NDQ4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NDQ5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NDQ6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NDQ7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NWP */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NCE2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NCE3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCE4 */
+ SUNXI_FUNCTION(0x3, "spi2")), /* CS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCE5 */
+ SUNXI_FUNCTION(0x3, "spi2")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCE6 */
+ SUNXI_FUNCTION(0x3, "spi2")), /* MOSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC22,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCE7 */
+ SUNXI_FUNCTION(0x3, "spi2")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC23,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC24,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NDQS */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VN2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VPC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D8 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VP3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D9 */
+ SUNXI_FUNCTION(0x3, "lvds0")), /* VM3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D10 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VP0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D11 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VN0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D12 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VP1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D13 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VN1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D14 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VP2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D15 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VN2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D16 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VPC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D17 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D18 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VP3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D19 */
+ SUNXI_FUNCTION(0x3, "lvds1")), /* VN3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D20 */
+ SUNXI_FUNCTION(0x3, "csi1")), /* MCLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D21 */
+ SUNXI_FUNCTION(0x3, "sim")), /* VPPEN */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD22,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D22 */
+ SUNXI_FUNCTION(0x3, "sim")), /* VPPPP */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD23,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* D23 */
+ SUNXI_FUNCTION(0x3, "sim")), /* DET */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD24,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "sim")), /* VCCEN */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD25,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* DE */
+ SUNXI_FUNCTION(0x3, "sim")), /* RST */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD26,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "sim")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD27,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "sim")), /* SDA */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "csi0")), /* PCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* ERR */
+ SUNXI_FUNCTION(0x3, "csi0")), /* CK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* SYNC */
+ SUNXI_FUNCTION(0x3, "csi0")), /* HSYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* DVLD */
+ SUNXI_FUNCTION(0x3, "csi0")), /* VSYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "csi0"), /* D1 */
+ SUNXI_FUNCTION(0x4, "sim")), /* VPPEN */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D4 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D5 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D6 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts0"), /* D7 */
+ SUNXI_FUNCTION(0x3, "csi0")), /* D7 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x4, "jtag")), /* MSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x4, "jtag")), /* DI1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
SUNXI_FUNCTION(0x4, "uart0")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x4, "jtag")), /* DO1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
SUNXI_FUNCTION(0x4, "uart0")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x4, "jtag")), /* CK1 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "csi1"), /* PCK */
+ SUNXI_FUNCTION(0x4, "mmc1")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* ERR */
+ SUNXI_FUNCTION(0x3, "csi1"), /* CK */
+ SUNXI_FUNCTION(0x4, "mmc1")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* SYNC */
+ SUNXI_FUNCTION(0x3, "csi1"), /* HSYNC */
+ SUNXI_FUNCTION(0x4, "mmc1")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* DVLD */
+ SUNXI_FUNCTION(0x3, "csi1"), /* VSYNC */
+ SUNXI_FUNCTION(0x4, "mmc1")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D0 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D0 */
+ SUNXI_FUNCTION(0x4, "mmc1"), /* D2 */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D1 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D1 */
+ SUNXI_FUNCTION(0x4, "mmc1"), /* D3 */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D2 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D2 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* TX */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D3 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D3 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RX */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D4 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D4 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RTS */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D5 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D5 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* CTS */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D6 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D6 */
+ SUNXI_FUNCTION(0x4, "uart4"), /* TX */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ts1"), /* D7 */
+ SUNXI_FUNCTION(0x3, "csi1"), /* D7 */
+ SUNXI_FUNCTION(0x4, "uart4"), /* RX */
+ SUNXI_FUNCTION(0x5, "csi0")), /* D15 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D0 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAA0 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* TX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D1 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAA1 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D2 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAA2 */
+ SUNXI_FUNCTION(0x4, "uart3"), /* RTS */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D3 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAIRQ */
+ SUNXI_FUNCTION(0x4, "uart3"), /* CTS */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D4 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD0 */
+ SUNXI_FUNCTION(0x4, "uart4"), /* TX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D5 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD1 */
+ SUNXI_FUNCTION(0x4, "uart4"), /* RX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D6 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD2 */
+ SUNXI_FUNCTION(0x4, "uart5"), /* TX */
+ SUNXI_FUNCTION(0x5, "ms"), /* BS */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D7 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD3 */
+ SUNXI_FUNCTION(0x4, "uart5"), /* RX */
+ SUNXI_FUNCTION(0x5, "ms"), /* CLK */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D7 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D8 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD4 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN0 */
+ SUNXI_FUNCTION(0x5, "ms"), /* D0 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D8 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D9 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD5 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN1 */
+ SUNXI_FUNCTION(0x5, "ms"), /* D1 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D9 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D10 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD6 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN2 */
+ SUNXI_FUNCTION(0x5, "ms"), /* D2 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D11 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD7 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN3 */
+ SUNXI_FUNCTION(0x5, "ms"), /* D3 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D12 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD8 */
+ SUNXI_FUNCTION(0x4, "ps2"), /* SCK1 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D13 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD9 */
+ SUNXI_FUNCTION(0x4, "ps2"), /* SDA1 */
+ SUNXI_FUNCTION(0x5, "sim"), /* RST */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D14 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD10 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN4 */
+ SUNXI_FUNCTION(0x5, "sim"), /* VPPEN */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D15 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD11 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN5 */
+ SUNXI_FUNCTION(0x5, "sim"), /* VPPPP */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D15 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D16 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD12 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN6 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D16 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D17 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD13 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* IN7 */
+ SUNXI_FUNCTION(0x5, "sim"), /* VCCEN */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D17 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D18 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD14 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT0 */
+ SUNXI_FUNCTION(0x5, "sim"), /* SCK */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D19 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAD15 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT1 */
+ SUNXI_FUNCTION(0x5, "sim"), /* SDA */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D19 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D20 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAOE */
+ SUNXI_FUNCTION(0x4, "can"), /* TX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D20 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D21 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATADREQ */
+ SUNXI_FUNCTION(0x4, "can"), /* RX */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D21 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH22,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D22 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATADACK */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT2 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* CMD */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D22 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH23,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* D23 */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATACS0 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT3 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* CLK */
+ SUNXI_FUNCTION(0x7, "csi1")), /* D23 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH24,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATACS1 */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT4 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* D0 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* PCLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH25,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* DE */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAIORDY */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT5 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* D1 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* FIELD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH26,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAIOR */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT6 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* D2 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* HSYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PH27,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd1"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "pata"), /* ATAIOW */
+ SUNXI_FUNCTION(0x4, "keypad"), /* OUT7 */
+ SUNXI_FUNCTION(0x5, "mmc1"), /* D3 */
+ SUNXI_FUNCTION(0x7, "csi1")), /* VSYNC */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI0,
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -518,277 +893,401 @@
SUNXI_FUNCTION(0x1, "gpio_out")),
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm")), /* PWM1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc3")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* CS0 */
+ SUNXI_FUNCTION(0x3, "uart5")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart5")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart6")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart6")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi0"), /* CS1 */
+ SUNXI_FUNCTION(0x3, "ps2"), /* SCK1 */
+ SUNXI_FUNCTION(0x4, "timer4")), /* TCLKIN0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS1 */
+ SUNXI_FUNCTION(0x3, "ps2"), /* SDA1 */
+ SUNXI_FUNCTION(0x4, "timer5")), /* TCLKIN1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS0 */
+ SUNXI_FUNCTION(0x3, "uart2")), /* RTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart2")), /* CTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart2")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart2")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ps2"), /* SCK0 */
+ SUNXI_FUNCTION(0x3, "uart7"), /* TX */
+ SUNXI_FUNCTION(0x4, "hdmi")), /* HSCL */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PI21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ps2"), /* SDA0 */
+ SUNXI_FUNCTION(0x3, "uart7"), /* RX */
+ SUNXI_FUNCTION(0x4, "hdmi")), /* HSDA */
};
static const struct sunxi_desc_pin sun5i_a13_pins[] = {
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "pwm")),
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ir0")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "ir0")), /* RX */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi2")), /* CS1 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB16,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c1")), /* SDA */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB17,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2")), /* SCK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PB18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c2")), /* SDA */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NWE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NCE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NCE0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* NRE */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NRB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NRB1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PC19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* NDQS */
+ SUNXI_FUNCTION(0x4, "uart3")), /* RTS */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D4 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D5 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D6 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D7 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D10 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D11 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D12 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD13,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D13 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD14,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D14 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD15,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D15 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD18,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D18 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD19,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D19 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD20,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D20 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD21,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D21 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD22,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D22 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD23,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* D23 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD24,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD25,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* DE */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD26,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* HSYNC */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PD27,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "lcd0")), /* VSYNC */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x3, "csi0"), /* PCLK */
+ SUNXI_FUNCTION(0x4, "spi2")), /* CS0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x3, "csi0"), /* MCLK */
+ SUNXI_FUNCTION(0x4, "spi2")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x3, "csi0"), /* HSYNC */
+ SUNXI_FUNCTION(0x4, "spi2")), /* MOSI */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* VSYNC */
+ SUNXI_FUNCTION(0x4, "spi2")), /* MISO */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D0 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D1 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE6,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D2 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* D2 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE7,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D3 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE8,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D4 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D5 */
+ SUNXI_FUNCTION(0x4, "mmc2")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE10,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D6 */
SUNXI_FUNCTION(0x4, "uart1")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PE11,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "csi0"), /* D7 */
SUNXI_FUNCTION(0x4, "uart1")), /* RX */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF0,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* D1 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF1,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* D0 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF2,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* CLK */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF3,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* CMD */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF4,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* D3 */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PF5,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x4, "mmc0")), /* D2 */
/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG0,
SUNXI_FUNCTION(0x0, "gpio_in"),
@@ -802,24 +1301,34 @@
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG3,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
SUNXI_FUNCTION(0x4, "uart1")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG4,
SUNXI_FUNCTION(0x0, "gpio_in"),
SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
SUNXI_FUNCTION(0x4, "uart1")), /* RX */
- /* Hole */
+/* Hole */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG9,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS0 */
+ SUNXI_FUNCTION(0x3, "uart3")), /* TX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG10,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart3")), /* RX */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG11,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart3")), /* CTS */
SUNXI_PIN(SUNXI_PINCTRL_PIN_PG12,
SUNXI_FUNCTION(0x0, "gpio_in"),
- SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart3")), /* RTS */
};
static const struct sunxi_pinctrl_desc sun4i_a10_pinctrl_data = {
@@ -1029,7 +1538,7 @@
kfree(map);
}
-static struct pinctrl_ops sunxi_pctrl_ops = {
+static const struct pinctrl_ops sunxi_pctrl_ops = {
.dt_node_to_map = sunxi_pctrl_dt_node_to_map,
.dt_free_map = sunxi_pctrl_dt_free_map,
.get_groups_count = sunxi_pctrl_get_groups_count,
@@ -1098,7 +1607,7 @@
return 0;
}
-static struct pinconf_ops sunxi_pconf_ops = {
+static const struct pinconf_ops sunxi_pconf_ops = {
.pin_config_group_get = sunxi_pconf_group_get,
.pin_config_group_set = sunxi_pconf_group_set,
};
@@ -1204,7 +1713,7 @@
return ret;
}
-static struct pinmux_ops sunxi_pmx_ops = {
+static const struct pinmux_ops sunxi_pmx_ops = {
.get_functions_count = sunxi_pmx_get_funcs_cnt,
.get_function_name = sunxi_pmx_get_func_name,
.get_function_groups = sunxi_pmx_get_func_groups,
@@ -1409,6 +1918,7 @@
struct pinctrl_pin_desc *pins;
struct sunxi_pinctrl *pctl;
int i, ret, last_pin;
+ struct clk *clk;
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
@@ -1479,6 +1989,12 @@
goto gpiochip_error;
}
+ clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ goto gpiochip_error;
+
+ clk_prepare_enable(clk);
+
dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
return 0;
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index f195d77..2fa9bc6 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -316,7 +316,7 @@
return 0;
}
-static struct pinctrl_ops tegra_pinctrl_ops = {
+static const struct pinctrl_ops tegra_pinctrl_ops = {
.get_groups_count = tegra_pinctrl_get_groups_count,
.get_group_name = tegra_pinctrl_get_group_name,
.get_group_pins = tegra_pinctrl_get_group_pins,
@@ -401,7 +401,7 @@
pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
}
-static struct pinmux_ops tegra_pinmux_ops = {
+static const struct pinmux_ops tegra_pinmux_ops = {
.get_functions_count = tegra_pinctrl_get_funcs_count,
.get_function_name = tegra_pinctrl_get_func_name,
.get_function_groups = tegra_pinctrl_get_func_groups,
@@ -676,7 +676,7 @@
}
#endif
-static struct pinconf_ops tegra_pinconf_ops = {
+static const struct pinconf_ops tegra_pinconf_ops = {
.pin_config_get = tegra_pinconf_get,
.pin_config_set = tegra_pinconf_set,
.pin_config_group_get = tegra_pinconf_group_get,
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c
index 2b57725..6a3a750 100644
--- a/drivers/pinctrl/pinctrl-u300.c
+++ b/drivers/pinctrl/pinctrl-u300.c
@@ -860,7 +860,7 @@
seq_printf(s, " " DRIVER_NAME);
}
-static struct pinctrl_ops u300_pctrl_ops = {
+static const struct pinctrl_ops u300_pctrl_ops = {
.get_groups_count = u300_get_groups_count,
.get_group_name = u300_get_group_name,
.get_group_pins = u300_get_group_pins,
@@ -1003,7 +1003,7 @@
return 0;
}
-static struct pinmux_ops u300_pmx_ops = {
+static const struct pinmux_ops u300_pmx_ops = {
.get_functions_count = u300_pmx_get_funcs_count,
.get_function_name = u300_pmx_get_func_name,
.get_function_groups = u300_pmx_get_groups,
@@ -1046,7 +1046,7 @@
return 0;
}
-static struct pinconf_ops u300_pconf_ops = {
+static const struct pinconf_ops u300_pconf_ops = {
.is_generic = true,
.pin_config_get = u300_pin_config_get,
.pin_config_set = u300_pin_config_set,
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index 068224e..f2977cf 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -553,7 +553,7 @@
return ret;
}
-static struct pinconf_ops xway_pinconf_ops = {
+static const struct pinconf_ops xway_pinconf_ops = {
.pin_config_get = xway_pinconf_get,
.pin_config_set = xway_pinconf_set,
.pin_config_group_set = xway_pinconf_group_set,
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c
index bd83c8b..88cc509 100644
--- a/drivers/pinctrl/pinmux.c
+++ b/drivers/pinctrl/pinmux.c
@@ -506,7 +506,7 @@
if (!pmxops)
return 0;
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
nfuncs = pmxops->get_functions_count(pctldev);
while (func_selector < nfuncs) {
const char *func = pmxops->get_function_name(pctldev,
@@ -530,7 +530,7 @@
func_selector++;
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
@@ -548,7 +548,7 @@
seq_puts(s, "Pinmux settings per pin\n");
seq_puts(s, "Format: pin (name): mux_owner gpio_owner hog?\n");
- mutex_lock(&pinctrl_mutex);
+ mutex_lock(&pctldev->mutex);
/* The pin number can be retrived from the pin controller descriptor */
for (i = 0; i < pctldev->desc->npins; i++) {
@@ -583,7 +583,7 @@
seq_printf(s, "\n");
}
- mutex_unlock(&pinctrl_mutex);
+ mutex_unlock(&pctldev->mutex);
return 0;
}
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index 6a7dae7..116da04 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -198,7 +198,7 @@
kfree(map);
}
-static struct pinctrl_ops spear_pinctrl_ops = {
+static const struct pinctrl_ops spear_pinctrl_ops = {
.get_groups_count = spear_pinctrl_get_groups_cnt,
.get_group_name = spear_pinctrl_get_group_name,
.get_group_pins = spear_pinctrl_get_group_pins,
@@ -340,7 +340,7 @@
gpio_request_endisable(pctldev, range, offset, false);
}
-static struct pinmux_ops spear_pinmux_ops = {
+static const struct pinmux_ops spear_pinmux_ops = {
.get_functions_count = spear_pinctrl_get_funcs_count,
.get_function_name = spear_pinctrl_get_func_name,
.get_function_groups = spear_pinctrl_get_func_groups,
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 45cacf7..1a779bb 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -134,7 +134,6 @@
{ KE_KEY, 0x2142, { KEY_MEDIA } },
{ KE_KEY, 0x213b, { KEY_INFO } },
{ KE_KEY, 0x2169, { KEY_DIRECTION } },
- { KE_KEY, 0x216a, { KEY_SETUP } },
{ KE_KEY, 0x231b, { KEY_HELP } },
{ KE_END, 0 }
};
@@ -925,9 +924,6 @@
err = hp_wmi_input_setup();
if (err)
return err;
-
- //Enable magic for hotkeys that run on the SMBus
- ec_write(0xe6,0x6e);
}
if (bios_capable) {
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 9a90756..edec135 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1964,9 +1964,6 @@
/* kthread for the hotkey poller */
static struct task_struct *tpacpi_hotkey_task;
-/* Acquired while the poller kthread is running, use to sync start/stop */
-static struct mutex hotkey_thread_mutex;
-
/*
* Acquire mutex to write poller control variables as an
* atomic block.
@@ -2462,8 +2459,6 @@
unsigned int poll_freq;
bool was_frozen;
- mutex_lock(&hotkey_thread_mutex);
-
if (tpacpi_lifecycle == TPACPI_LIFE_EXITING)
goto exit;
@@ -2523,7 +2518,6 @@
}
exit:
- mutex_unlock(&hotkey_thread_mutex);
return 0;
}
@@ -2533,9 +2527,6 @@
if (tpacpi_hotkey_task) {
kthread_stop(tpacpi_hotkey_task);
tpacpi_hotkey_task = NULL;
- mutex_lock(&hotkey_thread_mutex);
- /* at this point, the thread did exit */
- mutex_unlock(&hotkey_thread_mutex);
}
}
@@ -3234,7 +3225,6 @@
mutex_init(&hotkey_mutex);
#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL
- mutex_init(&hotkey_thread_mutex);
mutex_init(&hotkey_thread_data_mutex);
#endif
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index cc1f7bf..c6d77e2 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -4,7 +4,7 @@
config REMOTEPROC
tristate
depends on HAS_DMA
- select FW_CONFIG
+ select FW_LOADER
select VIRTIO
config OMAP_REMOTEPROC
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 29387df4..8edb4ae 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -217,7 +217,7 @@
* TODO: support predefined notifyids (via resource table)
*/
ret = idr_alloc(&rproc->notifyids, rvring, 0, 0, GFP_KERNEL);
- if (ret) {
+ if (ret < 0) {
dev_err(dev, "idr_alloc failed: %d\n", ret);
dma_free_coherent(dev->parent, size, va, dma);
return ret;
@@ -366,10 +366,12 @@
/* it is now safe to add the virtio device */
ret = rproc_add_virtio_dev(rvdev, rsc->id);
if (ret)
- goto free_rvdev;
+ goto remove_rvdev;
return 0;
+remove_rvdev:
+ list_del(&rvdev->node);
free_rvdev:
kfree(rvdev);
return ret;
diff --git a/drivers/remoteproc/ste_modem_rproc.c b/drivers/remoteproc/ste_modem_rproc.c
index a7743c0..fb95c42 100644
--- a/drivers/remoteproc/ste_modem_rproc.c
+++ b/drivers/remoteproc/ste_modem_rproc.c
@@ -240,6 +240,8 @@
/* Unregister as remoteproc device */
rproc_del(sproc->rproc);
+ dma_free_coherent(sproc->rproc->dev.parent, SPROC_FW_SIZE,
+ sproc->fw_addr, sproc->fw_dma_addr);
rproc_put(sproc->rproc);
mdev->drv_data = NULL;
@@ -297,10 +299,13 @@
/* Register as a remoteproc device */
err = rproc_add(rproc);
if (err)
- goto free_rproc;
+ goto free_mem;
return 0;
+free_mem:
+ dma_free_coherent(rproc->dev.parent, SPROC_FW_SIZE,
+ sproc->fw_addr, sproc->fw_dma_addr);
free_rproc:
/* Reset device data upon error */
mdev->drv_data = NULL;
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f1b7fdc..82758cb 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -246,7 +246,7 @@
static int dasd_state_known_to_basic(struct dasd_device *device)
{
struct dasd_block *block = device->block;
- int rc;
+ int rc = 0;
/* Allocate and register gendisk structure. */
if (block) {
@@ -273,7 +273,8 @@
DBF_DEV_EVENT(DBF_EMERG, device, "%s", "debug area created");
device->state = DASD_STATE_BASIC;
- return 0;
+
+ return rc;
}
/*
@@ -282,6 +283,7 @@
static int dasd_state_basic_to_known(struct dasd_device *device)
{
int rc;
+
if (device->block) {
dasd_profile_exit(&device->block->profile);
if (device->block->debugfs_dentry)
@@ -332,8 +334,10 @@
if (block->base->discipline->do_analysis != NULL)
rc = block->base->discipline->do_analysis(block);
if (rc) {
- if (rc != -EAGAIN)
+ if (rc != -EAGAIN) {
device->state = DASD_STATE_UNFMT;
+ goto out;
+ }
return rc;
}
dasd_setup_queue(block);
@@ -341,11 +345,16 @@
block->blocks << block->s2b_shift);
device->state = DASD_STATE_READY;
rc = dasd_scan_partitions(block);
- if (rc)
+ if (rc) {
device->state = DASD_STATE_BASIC;
+ return rc;
+ }
} else {
device->state = DASD_STATE_READY;
}
+out:
+ if (device->discipline->basic_to_ready)
+ rc = device->discipline->basic_to_ready(device);
return rc;
}
@@ -368,6 +377,11 @@
{
int rc;
+ if (device->discipline->ready_to_basic) {
+ rc = device->discipline->ready_to_basic(device);
+ if (rc)
+ return rc;
+ }
device->state = DASD_STATE_BASIC;
if (device->block) {
struct dasd_block *block = device->block;
@@ -402,16 +416,10 @@
static int
dasd_state_ready_to_online(struct dasd_device * device)
{
- int rc;
struct gendisk *disk;
struct disk_part_iter piter;
struct hd_struct *part;
- if (device->discipline->ready_to_online) {
- rc = device->discipline->ready_to_online(device);
- if (rc)
- return rc;
- }
device->state = DASD_STATE_ONLINE;
if (device->block) {
dasd_schedule_block_bh(device->block);
@@ -444,6 +452,7 @@
if (rc)
return rc;
}
+
device->state = DASD_STATE_READY;
if (device->block && !(device->features & DASD_FEATURE_USERAW)) {
disk = device->block->bdev->bd_disk;
@@ -2223,6 +2232,77 @@
return rc;
}
+static inline int _wait_for_wakeup_queue(struct list_head *ccw_queue)
+{
+ struct dasd_ccw_req *cqr;
+
+ list_for_each_entry(cqr, ccw_queue, blocklist) {
+ if (cqr->callback_data != DASD_SLEEPON_END_TAG)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
+{
+ struct dasd_device *device;
+ int rc;
+ struct dasd_ccw_req *cqr, *n;
+
+retry:
+ list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
+ device = cqr->startdev;
+ if (cqr->status != DASD_CQR_FILLED) /*could be failed*/
+ continue;
+
+ if (test_bit(DASD_FLAG_LOCK_STOLEN, &device->flags) &&
+ !test_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags)) {
+ cqr->status = DASD_CQR_FAILED;
+ cqr->intrc = -EPERM;
+ continue;
+ }
+ /*Non-temporary stop condition will trigger fail fast*/
+ if (device->stopped & ~DASD_STOPPED_PENDING &&
+ test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
+ !dasd_eer_enabled(device)) {
+ cqr->status = DASD_CQR_FAILED;
+ cqr->intrc = -EAGAIN;
+ continue;
+ }
+
+ /*Don't try to start requests if device is stopped*/
+ if (interruptible) {
+ rc = wait_event_interruptible(
+ generic_waitq, !device->stopped);
+ if (rc == -ERESTARTSYS) {
+ cqr->status = DASD_CQR_FAILED;
+ cqr->intrc = rc;
+ continue;
+ }
+ } else
+ wait_event(generic_waitq, !(device->stopped));
+
+ if (!cqr->callback)
+ cqr->callback = dasd_wakeup_cb;
+ cqr->callback_data = DASD_SLEEPON_START_TAG;
+ dasd_add_request_tail(cqr);
+ }
+
+ wait_event(generic_waitq, _wait_for_wakeup_queue(ccw_queue));
+
+ rc = 0;
+ list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
+ if (__dasd_sleep_on_erp(cqr))
+ rc = 1;
+ }
+ if (rc)
+ goto retry;
+
+
+ return 0;
+}
+
/*
* Queue a request to the tail of the device ccw_queue and wait for
* it's completion.
@@ -2233,6 +2313,15 @@
}
/*
+ * Start requests from a ccw_queue and wait for their completion.
+ */
+int dasd_sleep_on_queue(struct list_head *ccw_queue)
+{
+ return _dasd_sleep_on_queue(ccw_queue, 0);
+}
+EXPORT_SYMBOL(dasd_sleep_on_queue);
+
+/*
* Queue a request to the tail of the device ccw_queue and wait
* interruptible for it's completion.
*/
@@ -2663,6 +2752,26 @@
}
/*
+ * Requeue a request back to the block request queue
+ * only works for block requests
+ */
+static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
+{
+ struct dasd_block *block = cqr->block;
+ struct request *req;
+ unsigned long flags;
+
+ if (!block)
+ return -EINVAL;
+ spin_lock_irqsave(&block->queue_lock, flags);
+ req = (struct request *) cqr->callback_data;
+ blk_requeue_request(block->request_queue, req);
+ spin_unlock_irqrestore(&block->queue_lock, flags);
+
+ return 0;
+}
+
+/*
* Go through all request on the dasd_block request queue, cancel them
* on the respective dasd_device, and return them to the generic
* block layer.
@@ -3380,10 +3489,11 @@
int dasd_generic_pm_freeze(struct ccw_device *cdev)
{
- struct dasd_ccw_req *cqr, *n;
- int rc;
- struct list_head freeze_queue;
struct dasd_device *device = dasd_device_from_cdev(cdev);
+ struct list_head freeze_queue;
+ struct dasd_ccw_req *cqr, *n;
+ struct dasd_ccw_req *refers;
+ int rc;
if (IS_ERR(device))
return PTR_ERR(device);
@@ -3396,7 +3506,8 @@
/* disallow new I/O */
dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
- /* clear active requests */
+
+ /* clear active requests and requeue them to block layer if possible */
INIT_LIST_HEAD(&freeze_queue);
spin_lock_irq(get_ccwdev_lock(cdev));
rc = 0;
@@ -3416,7 +3527,6 @@
}
list_move_tail(&cqr->devlist, &freeze_queue);
}
-
spin_unlock_irq(get_ccwdev_lock(cdev));
list_for_each_entry_safe(cqr, n, &freeze_queue, devlist) {
@@ -3424,12 +3534,38 @@
(cqr->status != DASD_CQR_CLEAR_PENDING));
if (cqr->status == DASD_CQR_CLEARED)
cqr->status = DASD_CQR_QUEUED;
- }
- /* move freeze_queue to start of the ccw_queue */
- spin_lock_irq(get_ccwdev_lock(cdev));
- list_splice_tail(&freeze_queue, &device->ccw_queue);
- spin_unlock_irq(get_ccwdev_lock(cdev));
+ /* requeue requests to blocklayer will only work for
+ block device requests */
+ if (_dasd_requeue_request(cqr))
+ continue;
+
+ /* remove requests from device and block queue */
+ list_del_init(&cqr->devlist);
+ while (cqr->refers != NULL) {
+ refers = cqr->refers;
+ /* remove the request from the block queue */
+ list_del(&cqr->blocklist);
+ /* free the finished erp request */
+ dasd_free_erp_request(cqr, cqr->memdev);
+ cqr = refers;
+ }
+ if (cqr->block)
+ list_del_init(&cqr->blocklist);
+ cqr->block->base->discipline->free_cp(
+ cqr, (struct request *) cqr->callback_data);
+ }
+
+ /*
+ * if requests remain then they are internal request
+ * and go back to the device queue
+ */
+ if (!list_empty(&freeze_queue)) {
+ /* move freeze_queue to start of the ccw_queue */
+ spin_lock_irq(get_ccwdev_lock(cdev));
+ list_splice_tail(&freeze_queue, &device->ccw_queue);
+ spin_unlock_irq(get_ccwdev_lock(cdev));
+ }
dasd_put_device(device);
return rc;
}
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index c196827..a71bb8a 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -410,8 +410,7 @@
struct dasd_devmap *devmap, *new, *tmp;
int hash;
- new = (struct dasd_devmap *)
- kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
+ new = kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL);
if (!new)
return ERR_PTR(-ENOMEM);
spin_lock(&dasd_devmap_lock);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 6999fd9..6a44b27 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2022,7 +2022,7 @@
return dasd_eckd_end_analysis(block);
}
-static int dasd_eckd_ready_to_online(struct dasd_device *device)
+static int dasd_eckd_basic_to_ready(struct dasd_device *device)
{
return dasd_alias_add_device(device);
};
@@ -2031,6 +2031,11 @@
{
cancel_work_sync(&device->reload_device);
cancel_work_sync(&device->kick_validate);
+ return 0;
+};
+
+static int dasd_eckd_ready_to_basic(struct dasd_device *device)
+{
return dasd_alias_remove_device(device);
};
@@ -2050,45 +2055,34 @@
}
static struct dasd_ccw_req *
-dasd_eckd_format_device(struct dasd_device * device,
- struct format_data_t * fdata)
+dasd_eckd_build_format(struct dasd_device *base,
+ struct format_data_t *fdata)
{
- struct dasd_eckd_private *private;
+ struct dasd_eckd_private *base_priv;
+ struct dasd_eckd_private *start_priv;
+ struct dasd_device *startdev;
struct dasd_ccw_req *fcp;
struct eckd_count *ect;
+ struct ch_t address;
struct ccw1 *ccw;
void *data;
int rpt;
- struct ch_t address;
int cplength, datasize;
- int i;
+ int i, j;
int intensity = 0;
int r0_perm;
+ int nr_tracks;
- private = (struct dasd_eckd_private *) device->private;
- rpt = recs_per_track(&private->rdc_data, 0, fdata->blksize);
- set_ch_t(&address,
- fdata->start_unit / private->rdc_data.trk_per_cyl,
- fdata->start_unit % private->rdc_data.trk_per_cyl);
+ startdev = dasd_alias_get_start_dev(base);
+ if (!startdev)
+ startdev = base;
- /* Sanity checks. */
- if (fdata->start_unit >=
- (private->real_cyl * private->rdc_data.trk_per_cyl)) {
- dev_warn(&device->cdev->dev, "Start track number %d used in "
- "formatting is too big\n", fdata->start_unit);
- return ERR_PTR(-EINVAL);
- }
- if (fdata->start_unit > fdata->stop_unit) {
- dev_warn(&device->cdev->dev, "Start track %d used in "
- "formatting exceeds end track\n", fdata->start_unit);
- return ERR_PTR(-EINVAL);
- }
- if (dasd_check_blocksize(fdata->blksize) != 0) {
- dev_warn(&device->cdev->dev,
- "The DASD cannot be formatted with block size %d\n",
- fdata->blksize);
- return ERR_PTR(-EINVAL);
- }
+ start_priv = (struct dasd_eckd_private *) startdev->private;
+ base_priv = (struct dasd_eckd_private *) base->private;
+
+ rpt = recs_per_track(&base_priv->rdc_data, 0, fdata->blksize);
+
+ nr_tracks = fdata->stop_unit - fdata->start_unit + 1;
/*
* fdata->intensity is a bit string that tells us what to do:
@@ -2106,149 +2100,282 @@
r0_perm = 1;
intensity = fdata->intensity;
}
+
switch (intensity) {
case 0x00: /* Normal format */
case 0x08: /* Normal format, use cdl. */
- cplength = 2 + rpt;
- datasize = sizeof(struct DE_eckd_data) +
+ cplength = 2 + (rpt*nr_tracks);
+ datasize = sizeof(struct PFX_eckd_data) +
sizeof(struct LO_eckd_data) +
- rpt * sizeof(struct eckd_count);
+ rpt * nr_tracks * sizeof(struct eckd_count);
break;
case 0x01: /* Write record zero and format track. */
case 0x09: /* Write record zero and format track, use cdl. */
- cplength = 3 + rpt;
- datasize = sizeof(struct DE_eckd_data) +
+ cplength = 2 + rpt * nr_tracks;
+ datasize = sizeof(struct PFX_eckd_data) +
sizeof(struct LO_eckd_data) +
sizeof(struct eckd_count) +
- rpt * sizeof(struct eckd_count);
+ rpt * nr_tracks * sizeof(struct eckd_count);
break;
case 0x04: /* Invalidate track. */
case 0x0c: /* Invalidate track, use cdl. */
cplength = 3;
- datasize = sizeof(struct DE_eckd_data) +
+ datasize = sizeof(struct PFX_eckd_data) +
sizeof(struct LO_eckd_data) +
sizeof(struct eckd_count);
break;
default:
- dev_warn(&device->cdev->dev, "An I/O control call used "
- "incorrect flags 0x%x\n", fdata->intensity);
+ dev_warn(&startdev->cdev->dev,
+ "An I/O control call used incorrect flags 0x%x\n",
+ fdata->intensity);
return ERR_PTR(-EINVAL);
}
/* Allocate the format ccw request. */
- fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
+ fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
+ datasize, startdev);
if (IS_ERR(fcp))
return fcp;
+ start_priv->count++;
data = fcp->data;
ccw = fcp->cpaddr;
switch (intensity & ~0x08) {
case 0x00: /* Normal format. */
- define_extent(ccw++, (struct DE_eckd_data *) data,
- fdata->start_unit, fdata->start_unit,
- DASD_ECKD_CCW_WRITE_CKD, device);
+ prefix(ccw++, (struct PFX_eckd_data *) data,
+ fdata->start_unit, fdata->stop_unit,
+ DASD_ECKD_CCW_WRITE_CKD, base, startdev);
/* grant subsystem permission to format R0 */
if (r0_perm)
- ((struct DE_eckd_data *)data)->ga_extended |= 0x04;
- data += sizeof(struct DE_eckd_data);
+ ((struct PFX_eckd_data *)data)
+ ->define_extent.ga_extended |= 0x04;
+ data += sizeof(struct PFX_eckd_data);
ccw[-1].flags |= CCW_FLAG_CC;
locate_record(ccw++, (struct LO_eckd_data *) data,
- fdata->start_unit, 0, rpt,
- DASD_ECKD_CCW_WRITE_CKD, device,
+ fdata->start_unit, 0, rpt*nr_tracks,
+ DASD_ECKD_CCW_WRITE_CKD, base,
fdata->blksize);
data += sizeof(struct LO_eckd_data);
break;
case 0x01: /* Write record zero + format track. */
- define_extent(ccw++, (struct DE_eckd_data *) data,
- fdata->start_unit, fdata->start_unit,
- DASD_ECKD_CCW_WRITE_RECORD_ZERO,
- device);
- data += sizeof(struct DE_eckd_data);
+ prefix(ccw++, (struct PFX_eckd_data *) data,
+ fdata->start_unit, fdata->stop_unit,
+ DASD_ECKD_CCW_WRITE_RECORD_ZERO,
+ base, startdev);
+ data += sizeof(struct PFX_eckd_data);
ccw[-1].flags |= CCW_FLAG_CC;
locate_record(ccw++, (struct LO_eckd_data *) data,
- fdata->start_unit, 0, rpt + 1,
- DASD_ECKD_CCW_WRITE_RECORD_ZERO, device,
- device->block->bp_block);
+ fdata->start_unit, 0, rpt * nr_tracks + 1,
+ DASD_ECKD_CCW_WRITE_RECORD_ZERO, base,
+ base->block->bp_block);
data += sizeof(struct LO_eckd_data);
break;
case 0x04: /* Invalidate track. */
- define_extent(ccw++, (struct DE_eckd_data *) data,
- fdata->start_unit, fdata->start_unit,
- DASD_ECKD_CCW_WRITE_CKD, device);
- data += sizeof(struct DE_eckd_data);
+ prefix(ccw++, (struct PFX_eckd_data *) data,
+ fdata->start_unit, fdata->stop_unit,
+ DASD_ECKD_CCW_WRITE_CKD, base, startdev);
+ data += sizeof(struct PFX_eckd_data);
ccw[-1].flags |= CCW_FLAG_CC;
locate_record(ccw++, (struct LO_eckd_data *) data,
fdata->start_unit, 0, 1,
- DASD_ECKD_CCW_WRITE_CKD, device, 8);
+ DASD_ECKD_CCW_WRITE_CKD, base, 8);
data += sizeof(struct LO_eckd_data);
break;
}
- if (intensity & 0x01) { /* write record zero */
- ect = (struct eckd_count *) data;
- data += sizeof(struct eckd_count);
- ect->cyl = address.cyl;
- ect->head = address.head;
- ect->record = 0;
- ect->kl = 0;
- ect->dl = 8;
- ccw[-1].flags |= CCW_FLAG_CC;
- ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
- ccw->flags = CCW_FLAG_SLI;
- ccw->count = 8;
- ccw->cda = (__u32)(addr_t) ect;
- ccw++;
- }
- if ((intensity & ~0x08) & 0x04) { /* erase track */
- ect = (struct eckd_count *) data;
- data += sizeof(struct eckd_count);
- ect->cyl = address.cyl;
- ect->head = address.head;
- ect->record = 1;
- ect->kl = 0;
- ect->dl = 0;
- ccw[-1].flags |= CCW_FLAG_CC;
- ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
- ccw->flags = CCW_FLAG_SLI;
- ccw->count = 8;
- ccw->cda = (__u32)(addr_t) ect;
- } else { /* write remaining records */
- for (i = 0; i < rpt; i++) {
+
+ for (j = 0; j < nr_tracks; j++) {
+ /* calculate cylinder and head for the current track */
+ set_ch_t(&address,
+ (fdata->start_unit + j) /
+ base_priv->rdc_data.trk_per_cyl,
+ (fdata->start_unit + j) %
+ base_priv->rdc_data.trk_per_cyl);
+ if (intensity & 0x01) { /* write record zero */
ect = (struct eckd_count *) data;
data += sizeof(struct eckd_count);
ect->cyl = address.cyl;
ect->head = address.head;
- ect->record = i + 1;
+ ect->record = 0;
ect->kl = 0;
- ect->dl = fdata->blksize;
- /* Check for special tracks 0-1 when formatting CDL */
- if ((intensity & 0x08) &&
- fdata->start_unit == 0) {
- if (i < 3) {
- ect->kl = 4;
- ect->dl = sizes_trk0[i] - 4;
- }
- }
- if ((intensity & 0x08) &&
- fdata->start_unit == 1) {
- ect->kl = 44;
- ect->dl = LABEL_SIZE - 44;
- }
+ ect->dl = 8;
ccw[-1].flags |= CCW_FLAG_CC;
- ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+ ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
ccw->flags = CCW_FLAG_SLI;
ccw->count = 8;
ccw->cda = (__u32)(addr_t) ect;
ccw++;
}
+ if ((intensity & ~0x08) & 0x04) { /* erase track */
+ ect = (struct eckd_count *) data;
+ data += sizeof(struct eckd_count);
+ ect->cyl = address.cyl;
+ ect->head = address.head;
+ ect->record = 1;
+ ect->kl = 0;
+ ect->dl = 0;
+ ccw[-1].flags |= CCW_FLAG_CC;
+ ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+ ccw->flags = CCW_FLAG_SLI;
+ ccw->count = 8;
+ ccw->cda = (__u32)(addr_t) ect;
+ } else { /* write remaining records */
+ for (i = 0; i < rpt; i++) {
+ ect = (struct eckd_count *) data;
+ data += sizeof(struct eckd_count);
+ ect->cyl = address.cyl;
+ ect->head = address.head;
+ ect->record = i + 1;
+ ect->kl = 0;
+ ect->dl = fdata->blksize;
+ /*
+ * Check for special tracks 0-1
+ * when formatting CDL
+ */
+ if ((intensity & 0x08) &&
+ fdata->start_unit == 0) {
+ if (i < 3) {
+ ect->kl = 4;
+ ect->dl = sizes_trk0[i] - 4;
+ }
+ }
+ if ((intensity & 0x08) &&
+ fdata->start_unit == 1) {
+ ect->kl = 44;
+ ect->dl = LABEL_SIZE - 44;
+ }
+ ccw[-1].flags |= CCW_FLAG_CC;
+ if (i != 0 || j == 0)
+ ccw->cmd_code =
+ DASD_ECKD_CCW_WRITE_CKD;
+ else
+ ccw->cmd_code =
+ DASD_ECKD_CCW_WRITE_CKD_MT;
+ ccw->flags = CCW_FLAG_SLI;
+ ccw->count = 8;
+ ccw->cda = (__u32)(addr_t) ect;
+ ccw++;
+ }
+ }
}
- fcp->startdev = device;
- fcp->memdev = device;
+
+ fcp->startdev = startdev;
+ fcp->memdev = startdev;
fcp->retries = 256;
+ fcp->expires = startdev->default_expires * HZ;
fcp->buildclk = get_tod_clock();
fcp->status = DASD_CQR_FILLED;
+
return fcp;
}
+static int
+dasd_eckd_format_device(struct dasd_device *base,
+ struct format_data_t *fdata)
+{
+ struct dasd_ccw_req *cqr, *n;
+ struct dasd_block *block;
+ struct dasd_eckd_private *private;
+ struct list_head format_queue;
+ struct dasd_device *device;
+ int old_stop, format_step;
+ int step, rc = 0;
+
+ block = base->block;
+ private = (struct dasd_eckd_private *) base->private;
+
+ /* Sanity checks. */
+ if (fdata->start_unit >=
+ (private->real_cyl * private->rdc_data.trk_per_cyl)) {
+ dev_warn(&base->cdev->dev,
+ "Start track number %u used in formatting is too big\n",
+ fdata->start_unit);
+ return -EINVAL;
+ }
+ if (fdata->stop_unit >=
+ (private->real_cyl * private->rdc_data.trk_per_cyl)) {
+ dev_warn(&base->cdev->dev,
+ "Stop track number %u used in formatting is too big\n",
+ fdata->stop_unit);
+ return -EINVAL;
+ }
+ if (fdata->start_unit > fdata->stop_unit) {
+ dev_warn(&base->cdev->dev,
+ "Start track %u used in formatting exceeds end track\n",
+ fdata->start_unit);
+ return -EINVAL;
+ }
+ if (dasd_check_blocksize(fdata->blksize) != 0) {
+ dev_warn(&base->cdev->dev,
+ "The DASD cannot be formatted with block size %u\n",
+ fdata->blksize);
+ return -EINVAL;
+ }
+
+ INIT_LIST_HEAD(&format_queue);
+ old_stop = fdata->stop_unit;
+
+ while (fdata->start_unit <= 1) {
+ fdata->stop_unit = fdata->start_unit;
+ cqr = dasd_eckd_build_format(base, fdata);
+ list_add(&cqr->blocklist, &format_queue);
+
+ fdata->stop_unit = old_stop;
+ fdata->start_unit++;
+
+ if (fdata->start_unit > fdata->stop_unit)
+ goto sleep;
+ }
+
+retry:
+ format_step = 255 / recs_per_track(&private->rdc_data, 0,
+ fdata->blksize);
+ while (fdata->start_unit <= old_stop) {
+ step = fdata->stop_unit - fdata->start_unit + 1;
+ if (step > format_step)
+ fdata->stop_unit = fdata->start_unit + format_step - 1;
+
+ cqr = dasd_eckd_build_format(base, fdata);
+ if (IS_ERR(cqr)) {
+ if (PTR_ERR(cqr) == -ENOMEM) {
+ /*
+ * not enough memory available
+ * go to out and start requests
+ * retry after first requests were finished
+ */
+ fdata->stop_unit = old_stop;
+ goto sleep;
+ } else
+ return PTR_ERR(cqr);
+ }
+ list_add(&cqr->blocklist, &format_queue);
+
+ fdata->start_unit = fdata->stop_unit + 1;
+ fdata->stop_unit = old_stop;
+ }
+
+sleep:
+ dasd_sleep_on_queue(&format_queue);
+
+ list_for_each_entry_safe(cqr, n, &format_queue, blocklist) {
+ device = cqr->startdev;
+ private = (struct dasd_eckd_private *) device->private;
+ if (cqr->status == DASD_CQR_FAILED)
+ rc = -EIO;
+ list_del_init(&cqr->blocklist);
+ dasd_sfree_request(cqr, device);
+ private->count--;
+ }
+
+ /*
+ * in case of ENOMEM we need to retry after
+ * first requests are finished
+ */
+ if (fdata->start_unit <= fdata->stop_unit)
+ goto retry;
+
+ return rc;
+}
+
static void dasd_eckd_handle_terminated_request(struct dasd_ccw_req *cqr)
{
cqr->status = DASD_CQR_FILLED;
@@ -4305,8 +4432,9 @@
.uncheck_device = dasd_eckd_uncheck_device,
.do_analysis = dasd_eckd_do_analysis,
.verify_path = dasd_eckd_verify_path,
- .ready_to_online = dasd_eckd_ready_to_online,
+ .basic_to_ready = dasd_eckd_basic_to_ready,
.online_to_ready = dasd_eckd_online_to_ready,
+ .ready_to_basic = dasd_eckd_ready_to_basic,
.fill_geometry = dasd_eckd_fill_geometry,
.start_IO = dasd_start_IO,
.term_IO = dasd_term_IO,
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 899e3f5..0785bd9 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -300,10 +300,11 @@
* Last things to do when a device is set online, and first things
* when it is set offline.
*/
- int (*ready_to_online) (struct dasd_device *);
+ int (*basic_to_ready) (struct dasd_device *);
int (*online_to_ready) (struct dasd_device *);
+ int (*ready_to_basic) (struct dasd_device *);
- /*
+ /* (struct dasd_device *);
* Device operation functions. build_cp creates a ccw chain for
* a block device request, start_io starts the request and
* term_IO cancels it (e.g. in case of a timeout). format_device
@@ -317,8 +318,8 @@
int (*start_IO) (struct dasd_ccw_req *);
int (*term_IO) (struct dasd_ccw_req *);
void (*handle_terminated_request) (struct dasd_ccw_req *);
- struct dasd_ccw_req *(*format_device) (struct dasd_device *,
- struct format_data_t *);
+ int (*format_device) (struct dasd_device *,
+ struct format_data_t *);
int (*free_cp) (struct dasd_ccw_req *, struct request *);
/*
@@ -672,6 +673,7 @@
void dasd_schedule_device_bh(struct dasd_device *);
void dasd_schedule_block_bh(struct dasd_block *);
int dasd_sleep_on(struct dasd_ccw_req *);
+int dasd_sleep_on_queue(struct list_head *);
int dasd_sleep_on_immediatly(struct dasd_ccw_req *);
int dasd_sleep_on_interruptible(struct dasd_ccw_req *);
void dasd_device_set_timer(struct dasd_device *, int);
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 03c0e04..8be1b51 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -143,12 +143,12 @@
/*
* performs formatting of _device_ according to _fdata_
* Note: The discipline's format_function is assumed to deliver formatting
- * commands to format a single unit of the device. In terms of the ECKD
- * devices this means CCWs are generated to format a single track.
+ * commands to format multiple units of the device. In terms of the ECKD
+ * devices this means CCWs are generated to format multiple tracks.
*/
-static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
+static int
+dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
- struct dasd_ccw_req *cqr;
struct dasd_device *base;
int rc;
@@ -157,8 +157,8 @@
return -EPERM;
if (base->state != DASD_STATE_BASIC) {
- pr_warning("%s: The DASD cannot be formatted while it is "
- "enabled\n", dev_name(&base->cdev->dev));
+ pr_warn("%s: The DASD cannot be formatted while it is enabled\n",
+ dev_name(&base->cdev->dev));
return -EBUSY;
}
@@ -178,21 +178,10 @@
bdput(bdev);
}
- while (fdata->start_unit <= fdata->stop_unit) {
- cqr = base->discipline->format_device(base, fdata);
- if (IS_ERR(cqr))
- return PTR_ERR(cqr);
- rc = dasd_sleep_on_interruptible(cqr);
- dasd_sfree_request(cqr, cqr->memdev);
- if (rc) {
- if (rc != -ERESTARTSYS)
- pr_err("%s: Formatting unit %d failed with "
- "rc=%d\n", dev_name(&base->cdev->dev),
- fdata->start_unit, rc);
- return rc;
- }
- fdata->start_unit++;
- }
+ rc = base->discipline->format_device(base, fdata);
+ if (rc)
+ return rc;
+
return 0;
}
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c
index e9b9c83..b303cab 100644
--- a/drivers/s390/block/scm_blk.c
+++ b/drivers/s390/block/scm_blk.c
@@ -465,7 +465,7 @@
scm_major = ret;
ret = scm_alloc_rqs(nr_requests);
if (ret)
- goto out_unreg;
+ goto out_free;
scm_debug = debug_register("scm_log", 16, 1, 16);
if (!scm_debug) {
@@ -486,7 +486,6 @@
debug_unregister(scm_debug);
out_free:
scm_free_rqs();
-out_unreg:
unregister_blkdev(scm_major, "scm");
out:
return ret;
diff --git a/drivers/s390/block/scm_blk_cluster.c b/drivers/s390/block/scm_blk_cluster.c
index f4bb61b..c0d102e 100644
--- a/drivers/s390/block/scm_blk_cluster.c
+++ b/drivers/s390/block/scm_blk_cluster.c
@@ -223,6 +223,8 @@
bool scm_cluster_size_valid(void)
{
- return write_cluster_size == 0 || write_cluster_size == 32 ||
- write_cluster_size == 64 || write_cluster_size == 128;
+ if (write_cluster_size == 1 || write_cluster_size > 128)
+ return false;
+
+ return !(write_cluster_size & (write_cluster_size - 1));
}
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 7b00fa6..eb5d227 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -502,7 +502,7 @@
raw3215_try_io(raw);
raw->flags &= ~RAW3215_FLUSHING;
#ifdef CONFIG_TN3215_CONSOLE
- wait_cons_dev();
+ ccw_device_wait_idle(raw->cdev);
#endif
/* Enough room freed up ? */
if (RAW3215_BUFFER_SIZE - raw->count >= length)
@@ -858,7 +858,7 @@
raw = raw3215[0]; /* console 3215 is the first one */
if (raw->port.flags & ASYNC_SUSPENDED)
/* The console is still frozen for suspend. */
- if (ccw_device_force_console())
+ if (ccw_device_force_console(raw->cdev))
/* Forcing didn't work, no panic message .. */
return;
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index f4ff515..0da3ae3 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -174,8 +174,7 @@
int i;
for (i = 0; i < MON_MSGLIM; i++)
- if (monpriv->msg_array[i])
- kfree(monpriv->msg_array[i]);
+ kfree(monpriv->msg_array[i]);
kfree(monpriv);
}
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 4c9030a..24a08e8 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -796,7 +796,7 @@
do {
__raw3270_reset_device(rp);
while (!raw3270_state_final(rp)) {
- wait_cons_dev();
+ ccw_device_wait_idle(rp->cdev);
barrier();
}
} while (rp->state != RAW3270_STATE_READY);
@@ -810,7 +810,7 @@
unsigned long flags;
spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
- wait_cons_dev();
+ ccw_device_wait_idle(rp->cdev);
spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
}
@@ -1274,7 +1274,7 @@
rp = view->dev;
if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
- ccw_device_force_console();
+ ccw_device_force_console(rp->cdev);
#endif
}
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index cd79838..178836e 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -561,6 +561,8 @@
add_memory_merged(0);
}
+#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS)
+
static void __init insert_increment(u16 rn, int standby, int assigned)
{
struct memory_increment *incr, *new_incr;
@@ -573,7 +575,7 @@
new_incr->rn = rn;
new_incr->standby = standby;
if (!standby)
- new_incr->usecount = 1;
+ new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1;
last_rn = 0;
prev = &sclp_mem_list;
list_for_each_entry(incr, &sclp_mem_list, list) {
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 1d61a01..2282061 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -127,7 +127,7 @@
}
if (mode == TO_USER) {
if (copy_to_user((__force __user void*) dest + offs, buf,
- PAGE_SIZE))
+ count - offs))
return -EFAULT;
} else
memcpy(dest + offs, buf, count - offs);
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 50ad5fd..21fabc6 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -377,6 +377,26 @@
}
/**
+ * chp_update_desc - update channel-path description
+ * @chp - channel-path
+ *
+ * Update the channel-path description of the specified channel-path.
+ * Return zero on success, non-zero otherwise.
+ */
+int chp_update_desc(struct channel_path *chp)
+{
+ int rc;
+
+ rc = chsc_determine_base_channel_path_desc(chp->chpid, &chp->desc);
+ if (rc)
+ return rc;
+
+ rc = chsc_determine_fmt1_channel_path_desc(chp->chpid, &chp->desc_fmt1);
+
+ return rc;
+}
+
+/**
* chp_new - register a new channel-path
* @chpid - channel-path ID
*
@@ -403,7 +423,7 @@
mutex_init(&chp->lock);
/* Obtain channel path description and fill it in. */
- ret = chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+ ret = chp_update_desc(chp);
if (ret)
goto out_free;
if ((chp->desc.flags & 0x80) == 0) {
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index e1399db..9284b78 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -44,6 +44,7 @@
struct mutex lock; /* Serialize access to below members. */
int state;
struct channel_path_desc desc;
+ struct channel_path_desc_fmt1 desc_fmt1;
/* Channel-measurement related stuff: */
int cmg;
int shared;
@@ -62,6 +63,7 @@
void *chp_get_chp_desc(struct chp_id chpid);
void chp_remove_cmg_attr(struct channel_path *chp);
int chp_add_cmg_attr(struct channel_path *chp);
+int chp_update_desc(struct channel_path *chp);
int chp_new(struct chp_id chpid);
void chp_cfg_schedule(struct chp_id chpid, int configure);
void chp_cfg_cancel_deconfigure(struct chp_id chpid);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index e16c553..8ea7d9b 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -376,7 +376,7 @@
continue;
}
mutex_lock(&chp->lock);
- chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+ chp_update_desc(chp);
mutex_unlock(&chp->lock);
}
}
@@ -631,8 +631,8 @@
* Redo PathVerification on the devices the chpid connects to
*/
if (on) {
- /* Try to update the channel path descritor. */
- chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+ /* Try to update the channel path description. */
+ chp_update_desc(chp);
for_each_subchannel_staged(s390_subchannel_vary_chpid_on,
__s390_vary_chpid_on, &chpid);
} else
@@ -825,9 +825,10 @@
{
struct chsc_response_struct *chsc_resp;
struct chsc_scpd *scpd_area;
+ unsigned long flags;
int ret;
- spin_lock_irq(&chsc_page_lock);
+ spin_lock_irqsave(&chsc_page_lock, flags);
scpd_area = chsc_page;
ret = chsc_determine_channel_path_desc(chpid, 0, 0, 1, 0, scpd_area);
if (ret)
@@ -835,7 +836,7 @@
chsc_resp = (void *)&scpd_area->response;
memcpy(desc, &chsc_resp->data, sizeof(*desc));
out:
- spin_unlock_irq(&chsc_page_lock);
+ spin_unlock_irqrestore(&chsc_page_lock, flags);
return ret;
}
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 986ef6a..935d80b 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -471,15 +471,6 @@
}
EXPORT_SYMBOL_GPL(cio_disable_subchannel);
-int cio_create_sch_lock(struct subchannel *sch)
-{
- sch->lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
- if (!sch->lock)
- return -ENOMEM;
- spin_lock_init(sch->lock);
- return 0;
-}
-
static int cio_check_devno_blacklisted(struct subchannel *sch)
{
if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) {
@@ -536,32 +527,19 @@
sprintf(dbf_txt, "valsch%x", schid.sch_no);
CIO_TRACE_EVENT(4, dbf_txt);
- /* Nuke all fields. */
- memset(sch, 0, sizeof(struct subchannel));
-
- sch->schid = schid;
- if (cio_is_console(schid)) {
- sch->lock = cio_get_console_lock();
- } else {
- err = cio_create_sch_lock(sch);
- if (err)
- goto out;
- }
- mutex_init(&sch->reg_mutex);
-
/*
* The first subchannel that is not-operational (ccode==3)
- * indicates that there aren't any more devices available.
+ * indicates that there aren't any more devices available.
* If stsch gets an exception, it means the current subchannel set
- * is not valid.
+ * is not valid.
*/
- ccode = stsch_err (schid, &sch->schib);
+ ccode = stsch_err(schid, &sch->schib);
if (ccode) {
err = (ccode == 3) ? -ENXIO : ccode;
goto out;
}
- /* Copy subchannel type from path management control word. */
sch->st = sch->schib.pmcw.st;
+ sch->schid = schid;
switch (sch->st) {
case SUBCHANNEL_TYPE_IO:
@@ -578,11 +556,7 @@
CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n",
sch->schid.ssid, sch->schid.sch_no, sch->st);
- return 0;
out:
- if (!cio_is_console(schid))
- kfree(sch->lock);
- sch->lock = NULL;
return err;
}
@@ -650,15 +624,13 @@
}
#ifdef CONFIG_CCW_CONSOLE
-static struct subchannel console_subchannel;
-static struct io_subchannel_private console_priv;
-static int console_subchannel_in_use;
+static struct subchannel *console_sch;
/*
* Use cio_tsch to update the subchannel status and call the interrupt handler
- * if status had been pending. Called with the console_subchannel lock.
+ * if status had been pending. Called with the subchannel's lock held.
*/
-static void cio_tsch(struct subchannel *sch)
+void cio_tsch(struct subchannel *sch)
{
struct irb *irb;
int irq_context;
@@ -675,6 +647,7 @@
local_bh_disable();
irq_enter();
}
+ kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
if (sch->driver && sch->driver->irq)
sch->driver->irq(sch);
else
@@ -685,135 +658,90 @@
}
}
-void *cio_get_console_priv(void)
+static int cio_test_for_console(struct subchannel_id schid, void *data)
{
- return &console_priv;
-}
+ struct schib schib;
-/*
- * busy wait for the next interrupt on the console
- */
-void wait_cons_dev(void)
-{
- if (!console_subchannel_in_use)
- return;
-
- while (1) {
- cio_tsch(&console_subchannel);
- if (console_subchannel.schib.scsw.cmd.actl == 0)
- break;
- udelay_simple(100);
- }
-}
-
-static int
-cio_test_for_console(struct subchannel_id schid, void *data)
-{
- if (stsch_err(schid, &console_subchannel.schib) != 0)
+ if (stsch_err(schid, &schib) != 0)
return -ENXIO;
- if ((console_subchannel.schib.pmcw.st == SUBCHANNEL_TYPE_IO) &&
- console_subchannel.schib.pmcw.dnv &&
- (console_subchannel.schib.pmcw.dev == console_devno)) {
+ if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv &&
+ (schib.pmcw.dev == console_devno)) {
console_irq = schid.sch_no;
return 1; /* found */
}
return 0;
}
-
-static int
-cio_get_console_sch_no(void)
+static int cio_get_console_sch_no(void)
{
struct subchannel_id schid;
-
+ struct schib schib;
+
init_subchannel_id(&schid);
if (console_irq != -1) {
/* VM provided us with the irq number of the console. */
schid.sch_no = console_irq;
- if (stsch_err(schid, &console_subchannel.schib) != 0 ||
- (console_subchannel.schib.pmcw.st != SUBCHANNEL_TYPE_IO) ||
- !console_subchannel.schib.pmcw.dnv)
+ if (stsch_err(schid, &schib) != 0 ||
+ (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv)
return -1;
- console_devno = console_subchannel.schib.pmcw.dev;
+ console_devno = schib.pmcw.dev;
} else if (console_devno != -1) {
/* At least the console device number is known. */
for_each_subchannel(cio_test_for_console, NULL);
- if (console_irq == -1)
- return -1;
- } else {
- /* unlike in 2.4, we cannot autoprobe here, since
- * the channel subsystem is not fully initialized.
- * With some luck, the HWC console can take over */
- return -1;
}
return console_irq;
}
-struct subchannel *
-cio_probe_console(void)
+struct subchannel *cio_probe_console(void)
{
- int sch_no, ret;
struct subchannel_id schid;
+ struct subchannel *sch;
+ int sch_no, ret;
- if (xchg(&console_subchannel_in_use, 1) != 0)
- return ERR_PTR(-EBUSY);
sch_no = cio_get_console_sch_no();
if (sch_no == -1) {
- console_subchannel_in_use = 0;
pr_warning("No CCW console was found\n");
return ERR_PTR(-ENODEV);
}
- memset(&console_subchannel, 0, sizeof(struct subchannel));
init_subchannel_id(&schid);
schid.sch_no = sch_no;
- ret = cio_validate_subchannel(&console_subchannel, schid);
- if (ret) {
- console_subchannel_in_use = 0;
- return ERR_PTR(-ENODEV);
- }
+ sch = css_alloc_subchannel(schid);
+ if (IS_ERR(sch))
+ return sch;
- /*
- * enable console I/O-interrupt subclass
- */
isc_register(CONSOLE_ISC);
- console_subchannel.config.isc = CONSOLE_ISC;
- console_subchannel.config.intparm = (u32)(addr_t)&console_subchannel;
- ret = cio_commit_config(&console_subchannel);
+ sch->config.isc = CONSOLE_ISC;
+ sch->config.intparm = (u32)(addr_t)sch;
+ ret = cio_commit_config(sch);
if (ret) {
isc_unregister(CONSOLE_ISC);
- console_subchannel_in_use = 0;
+ put_device(&sch->dev);
return ERR_PTR(ret);
}
- return &console_subchannel;
+ console_sch = sch;
+ return sch;
}
-void
-cio_release_console(void)
+int cio_is_console(struct subchannel_id schid)
{
- console_subchannel.config.intparm = 0;
- cio_commit_config(&console_subchannel);
- isc_unregister(CONSOLE_ISC);
- console_subchannel_in_use = 0;
-}
-
-/* Bah... hack to catch console special sausages. */
-int
-cio_is_console(struct subchannel_id schid)
-{
- if (!console_subchannel_in_use)
+ if (!console_sch)
return 0;
- return schid_equal(&schid, &console_subchannel.schid);
+ return schid_equal(&schid, &console_sch->schid);
}
-struct subchannel *
-cio_get_console_subchannel(void)
+void cio_register_early_subchannels(void)
{
- if (!console_subchannel_in_use)
- return NULL;
- return &console_subchannel;
-}
+ int ret;
-#endif
+ if (!console_sch)
+ return;
+
+ ret = css_register_subchannel(console_sch);
+ if (ret)
+ put_device(&console_sch->dev);
+}
+#endif /* CONFIG_CCW_CONSOLE */
+
static int
__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib)
{
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 4a1ff5c..d62f5e7 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -121,23 +121,18 @@
int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key);
int cio_tm_intrg(struct subchannel *sch);
-int cio_create_sch_lock(struct subchannel *);
void do_adapter_IO(u8 isc);
void do_IRQ(struct pt_regs *);
/* Use with care. */
#ifdef CONFIG_CCW_CONSOLE
extern struct subchannel *cio_probe_console(void);
-extern void cio_release_console(void);
extern int cio_is_console(struct subchannel_id);
-extern struct subchannel *cio_get_console_subchannel(void);
-extern spinlock_t * cio_get_console_lock(void);
-extern void *cio_get_console_priv(void);
+extern void cio_register_early_subchannels(void);
+extern void cio_tsch(struct subchannel *sch);
#else
#define cio_is_console(schid) 0
-#define cio_get_console_subchannel() NULL
-#define cio_get_console_lock() NULL
-#define cio_get_console_priv() NULL
+static inline void cio_register_early_subchannels(void) {}
#endif
#endif
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index a239237..1ebe5d3 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -137,37 +137,53 @@
static void css_sch_todo(struct work_struct *work);
-static struct subchannel *
-css_alloc_subchannel(struct subchannel_id schid)
+static int css_sch_create_locks(struct subchannel *sch)
+{
+ sch->lock = kmalloc(sizeof(*sch->lock), GFP_KERNEL);
+ if (!sch->lock)
+ return -ENOMEM;
+
+ spin_lock_init(sch->lock);
+ mutex_init(&sch->reg_mutex);
+
+ return 0;
+}
+
+static void css_subchannel_release(struct device *dev)
+{
+ struct subchannel *sch = to_subchannel(dev);
+
+ sch->config.intparm = 0;
+ cio_commit_config(sch);
+ kfree(sch->lock);
+ kfree(sch);
+}
+
+struct subchannel *css_alloc_subchannel(struct subchannel_id schid)
{
struct subchannel *sch;
int ret;
- sch = kmalloc (sizeof (*sch), GFP_KERNEL | GFP_DMA);
- if (sch == NULL)
+ sch = kzalloc(sizeof(*sch), GFP_KERNEL | GFP_DMA);
+ if (!sch)
return ERR_PTR(-ENOMEM);
- ret = cio_validate_subchannel (sch, schid);
- if (ret < 0) {
- kfree(sch);
- return ERR_PTR(ret);
- }
+
+ ret = cio_validate_subchannel(sch, schid);
+ if (ret < 0)
+ goto err;
+
+ ret = css_sch_create_locks(sch);
+ if (ret)
+ goto err;
+
INIT_WORK(&sch->todo_work, css_sch_todo);
+ sch->dev.release = &css_subchannel_release;
+ device_initialize(&sch->dev);
return sch;
-}
-static void
-css_subchannel_release(struct device *dev)
-{
- struct subchannel *sch;
-
- sch = to_subchannel(dev);
- if (!cio_is_console(sch->schid)) {
- /* Reset intparm to zeroes. */
- sch->config.intparm = 0;
- cio_commit_config(sch);
- kfree(sch->lock);
- kfree(sch);
- }
+err:
+ kfree(sch);
+ return ERR_PTR(ret);
}
static int css_sch_device_register(struct subchannel *sch)
@@ -177,7 +193,7 @@
mutex_lock(&sch->reg_mutex);
dev_set_name(&sch->dev, "0.%x.%04x", sch->schid.ssid,
sch->schid.sch_no);
- ret = device_register(&sch->dev);
+ ret = device_add(&sch->dev);
mutex_unlock(&sch->reg_mutex);
return ret;
}
@@ -228,16 +244,11 @@
{
int ret;
- if (cio_is_console(sch->schid)) {
- /* Console is initialized too early for functions requiring
- * memory allocation. */
+ ret = chsc_get_ssd_info(sch->schid, &sch->ssd_info);
+ if (ret)
ssd_from_pmcw(&sch->ssd_info, &sch->schib.pmcw);
- } else {
- ret = chsc_get_ssd_info(sch->schid, &sch->ssd_info);
- if (ret)
- ssd_from_pmcw(&sch->ssd_info, &sch->schib.pmcw);
- ssd_register_chpids(&sch->ssd_info);
- }
+
+ ssd_register_chpids(&sch->ssd_info);
}
static ssize_t type_show(struct device *dev, struct device_attribute *attr,
@@ -275,14 +286,13 @@
NULL,
};
-static int css_register_subchannel(struct subchannel *sch)
+int css_register_subchannel(struct subchannel *sch)
{
int ret;
/* Initialize the subchannel structure */
sch->dev.parent = &channel_subsystems[0]->device;
sch->dev.bus = &css_bus_type;
- sch->dev.release = &css_subchannel_release;
sch->dev.groups = default_subch_attr_groups;
/*
* We don't want to generate uevents for I/O subchannels that don't
@@ -314,23 +324,19 @@
return ret;
}
-int css_probe_device(struct subchannel_id schid)
+static int css_probe_device(struct subchannel_id schid)
{
- int ret;
struct subchannel *sch;
+ int ret;
- if (cio_is_console(schid))
- sch = cio_get_console_subchannel();
- else {
- sch = css_alloc_subchannel(schid);
- if (IS_ERR(sch))
- return PTR_ERR(sch);
- }
+ sch = css_alloc_subchannel(schid);
+ if (IS_ERR(sch))
+ return PTR_ERR(sch);
+
ret = css_register_subchannel(sch);
- if (ret) {
- if (!cio_is_console(schid))
- put_device(&sch->dev);
- }
+ if (ret)
+ put_device(&sch->dev);
+
return ret;
}
@@ -770,7 +776,7 @@
css->pseudo_subchannel->dev.release = css_subchannel_release;
dev_set_name(&css->pseudo_subchannel->dev, "defunct");
mutex_init(&css->pseudo_subchannel->reg_mutex);
- ret = cio_create_sch_lock(css->pseudo_subchannel);
+ ret = css_sch_create_locks(css->pseudo_subchannel);
if (ret) {
kfree(css->pseudo_subchannel);
return ret;
@@ -870,8 +876,7 @@
/*
* Now that the driver core is running, we can setup our channel subsystem.
- * The struct subchannel's are created during probing (except for the
- * static console subchannel).
+ * The struct subchannel's are created during probing.
*/
static int __init css_bus_init(void)
{
@@ -1050,6 +1055,8 @@
*/
static int __init channel_subsystem_init_sync(void)
{
+ /* Register subchannels which are already in use. */
+ cio_register_early_subchannels();
/* Start initial subchannel evaluation. */
css_schedule_eval_all();
css_complete_work();
@@ -1065,9 +1072,8 @@
chsc_enable_facility(CHSC_SDA_OC_MSS);
chp_id_for_each(&chpid) {
chp = chpid_to_chp(chpid);
- if (!chp)
- continue;
- chsc_determine_base_channel_path_desc(chpid, &chp->desc);
+ if (chp)
+ chp_update_desc(chp);
}
}
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 4af3dfe..b1de603 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -101,7 +101,8 @@
extern void css_driver_unregister(struct css_driver *);
extern void css_sch_device_unregister(struct subchannel *);
-extern int css_probe_device(struct subchannel_id);
+extern int css_register_subchannel(struct subchannel *);
+extern struct subchannel *css_alloc_subchannel(struct subchannel_id);
extern struct subchannel *get_subchannel_by_schid(struct subchannel_id);
extern int css_init_done;
extern int max_ssid;
@@ -109,7 +110,6 @@
int (*fn_unknown)(struct subchannel_id,
void *), void *data);
extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
-extern void css_reiterate_subchannels(void);
void css_update_ssd_info(struct subchannel *sch);
struct channel_subsystem {
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index c6767f5..1ab5f6c 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -19,6 +19,7 @@
#include <linux/list.h>
#include <linux/device.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/kernel_stat.h>
@@ -43,6 +44,10 @@
static int recovery_phase;
static const unsigned long recovery_delay[] = { 3, 30, 300 };
+static atomic_t ccw_device_init_count = ATOMIC_INIT(0);
+static DECLARE_WAIT_QUEUE_HEAD(ccw_device_init_wq);
+static struct bus_type ccw_bus_type;
+
/******************* bus type handling ***********************/
/* The Linux driver model distinguishes between a bus type and
@@ -127,8 +132,6 @@
return ret;
}
-static struct bus_type ccw_bus_type;
-
static void io_subchannel_irq(struct subchannel *);
static int io_subchannel_probe(struct subchannel *);
static int io_subchannel_remove(struct subchannel *);
@@ -137,8 +140,6 @@
static int io_subchannel_chp_event(struct subchannel *, struct chp_link *,
int);
static void recovery_func(unsigned long data);
-wait_queue_head_t ccw_device_init_wq;
-atomic_t ccw_device_init_count;
static struct css_device_id io_subchannel_ids[] = {
{ .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, },
@@ -191,10 +192,7 @@
{
int ret;
- init_waitqueue_head(&ccw_device_init_wq);
- atomic_set(&ccw_device_init_count, 0);
setup_timer(&recovery_timer, recovery_func, 0);
-
ret = bus_register(&ccw_bus_type);
if (ret)
return ret;
@@ -1086,19 +1084,14 @@
dev_set_uevent_suppress(&sch->dev, 0);
kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
cdev = sch_get_cdev(sch);
- cdev->dev.groups = ccwdev_attr_groups;
- device_initialize(&cdev->dev);
- cdev->private->flags.initialized = 1;
- ccw_device_register(cdev);
- /*
- * Check if the device is already online. If it is
- * the reference count needs to be corrected since we
- * didn't obtain a reference in ccw_device_set_online.
- */
- if (cdev->private->state != DEV_STATE_NOT_OPER &&
- cdev->private->state != DEV_STATE_OFFLINE &&
- cdev->private->state != DEV_STATE_BOXED)
- get_device(&cdev->dev);
+ rc = ccw_device_register(cdev);
+ if (rc) {
+ /* Release online reference. */
+ put_device(&cdev->dev);
+ goto out_schedule;
+ }
+ if (atomic_dec_and_test(&ccw_device_init_count))
+ wake_up(&ccw_device_init_wq);
return 0;
}
io_subchannel_init_fields(sch);
@@ -1580,88 +1573,102 @@
}
#ifdef CONFIG_CCW_CONSOLE
-static struct ccw_device console_cdev;
-static struct ccw_device_private console_private;
-static int console_cdev_in_use;
-
-static DEFINE_SPINLOCK(ccw_console_lock);
-
-spinlock_t * cio_get_console_lock(void)
-{
- return &ccw_console_lock;
-}
-
static int ccw_device_console_enable(struct ccw_device *cdev,
struct subchannel *sch)
{
- struct io_subchannel_private *io_priv = cio_get_console_priv();
int rc;
- /* Attach subchannel private data. */
- memset(io_priv, 0, sizeof(*io_priv));
- set_io_private(sch, io_priv);
io_subchannel_init_fields(sch);
rc = cio_commit_config(sch);
if (rc)
return rc;
sch->driver = &io_subchannel_driver;
- /* Initialize the ccw_device structure. */
- cdev->dev.parent= &sch->dev;
sch_set_cdev(sch, cdev);
io_subchannel_recog(cdev, sch);
/* Now wait for the async. recognition to come to an end. */
spin_lock_irq(cdev->ccwlock);
while (!dev_fsm_final_state(cdev))
- wait_cons_dev();
- rc = -EIO;
- if (cdev->private->state != DEV_STATE_OFFLINE)
+ ccw_device_wait_idle(cdev);
+
+ /* Hold on to an extra reference while device is online. */
+ get_device(&cdev->dev);
+ rc = ccw_device_online(cdev);
+ if (rc)
goto out_unlock;
- ccw_device_online(cdev);
+
while (!dev_fsm_final_state(cdev))
- wait_cons_dev();
- if (cdev->private->state != DEV_STATE_ONLINE)
- goto out_unlock;
- rc = 0;
+ ccw_device_wait_idle(cdev);
+
+ if (cdev->private->state == DEV_STATE_ONLINE)
+ cdev->online = 1;
+ else
+ rc = -EIO;
out_unlock:
spin_unlock_irq(cdev->ccwlock);
+ if (rc) /* Give up online reference since onlining failed. */
+ put_device(&cdev->dev);
return rc;
}
-struct ccw_device *
-ccw_device_probe_console(void)
+struct ccw_device *ccw_device_probe_console(void)
{
+ struct io_subchannel_private *io_priv;
+ struct ccw_device *cdev;
struct subchannel *sch;
int ret;
- if (xchg(&console_cdev_in_use, 1) != 0)
- return ERR_PTR(-EBUSY);
sch = cio_probe_console();
- if (IS_ERR(sch)) {
- console_cdev_in_use = 0;
- return (void *) sch;
+ if (IS_ERR(sch))
+ return ERR_CAST(sch);
+
+ io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
+ if (!io_priv) {
+ put_device(&sch->dev);
+ return ERR_PTR(-ENOMEM);
}
- memset(&console_cdev, 0, sizeof(struct ccw_device));
- memset(&console_private, 0, sizeof(struct ccw_device_private));
- console_cdev.private = &console_private;
- console_private.cdev = &console_cdev;
- console_private.int_class = IRQIO_CIO;
- ret = ccw_device_console_enable(&console_cdev, sch);
+ cdev = io_subchannel_create_ccwdev(sch);
+ if (IS_ERR(cdev)) {
+ put_device(&sch->dev);
+ kfree(io_priv);
+ return cdev;
+ }
+ set_io_private(sch, io_priv);
+ ret = ccw_device_console_enable(cdev, sch);
if (ret) {
- cio_release_console();
- console_cdev_in_use = 0;
+ set_io_private(sch, NULL);
+ put_device(&sch->dev);
+ put_device(&cdev->dev);
+ kfree(io_priv);
return ERR_PTR(ret);
}
- console_cdev.online = 1;
- return &console_cdev;
+ return cdev;
+}
+
+/**
+ * ccw_device_wait_idle() - busy wait for device to become idle
+ * @cdev: ccw device
+ *
+ * Poll until activity control is zero, that is, no function or data
+ * transfer is pending/active.
+ * Called with device lock being held.
+ */
+void ccw_device_wait_idle(struct ccw_device *cdev)
+{
+ struct subchannel *sch = to_subchannel(cdev->dev.parent);
+
+ while (1) {
+ cio_tsch(sch);
+ if (sch->schib.scsw.cmd.actl == 0)
+ break;
+ udelay_simple(100);
+ }
}
static int ccw_device_pm_restore(struct device *dev);
-int ccw_device_force_console(void)
+int ccw_device_force_console(struct ccw_device *cdev)
{
- if (!console_cdev_in_use)
- return -ENODEV;
- return ccw_device_pm_restore(&console_cdev.dev);
+ return ccw_device_pm_restore(&cdev->dev);
}
EXPORT_SYMBOL_GPL(ccw_device_force_console);
#endif
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 7d4ecb6..8d1d298 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -81,8 +81,6 @@
cdev->private->state == DEV_STATE_BOXED);
}
-extern wait_queue_head_t ccw_device_init_wq;
-extern atomic_t ccw_device_init_count;
int __init io_subchannel_init(void);
void io_subchannel_recog_done(struct ccw_device *cdev);
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index c77b6e0..4845d64 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -704,9 +704,9 @@
int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
{
struct subchannel *sch = to_subchannel(cdev->dev.parent);
- struct channel_path_desc_fmt1 desc;
+ struct channel_path *chp;
struct chp_id chpid;
- int mdc = 0, ret, i;
+ int mdc = 0, i;
/* Adjust requested path mask to excluded varied off paths. */
if (mask)
@@ -719,14 +719,20 @@
if (!(mask & (0x80 >> i)))
continue;
chpid.id = sch->schib.pmcw.chpid[i];
- ret = chsc_determine_fmt1_channel_path_desc(chpid, &desc);
- if (ret)
- return ret;
- if (!desc.f)
+ chp = chpid_to_chp(chpid);
+ if (!chp)
+ continue;
+
+ mutex_lock(&chp->lock);
+ if (!chp->desc_fmt1.f) {
+ mutex_unlock(&chp->lock);
return 0;
- if (!desc.r)
+ }
+ if (!chp->desc_fmt1.r)
mdc = 1;
- mdc = mdc ? min(mdc, (int)desc.mdc) : desc.mdc;
+ mdc = mdc ? min_t(int, mdc, chp->desc_fmt1.mdc) :
+ chp->desc_fmt1.mdc;
+ mutex_unlock(&chp->lock);
}
return mdc;
diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c
index 65d13e3..5a99908 100644
--- a/drivers/s390/cio/idset.c
+++ b/drivers/s390/cio/idset.c
@@ -17,7 +17,7 @@
static inline unsigned long bitmap_size(int num_ssid, int num_id)
{
- return __BITOPS_WORDS(num_ssid * num_id) * sizeof(unsigned long);
+ return BITS_TO_LONGS(num_ssid * num_id) * sizeof(unsigned long);
}
static struct idset *idset_new(int num_ssid, int num_id)
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 8c06223..6ccb745 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -769,6 +769,7 @@
unsigned long thread_start_mask;
unsigned long thread_allowed_mask;
unsigned long thread_running_mask;
+ struct task_struct *recovery_task;
spinlock_t ip_lock;
struct list_head ip_list;
struct list_head *ip_tbd_list;
@@ -862,6 +863,8 @@
extern struct kmem_cache *qeth_core_header_cache;
extern struct qeth_dbf_info qeth_dbf[QETH_DBF_INFOS];
+void qeth_set_recovery_task(struct qeth_card *);
+void qeth_clear_recovery_task(struct qeth_card *);
void qeth_set_allowed_threads(struct qeth_card *, unsigned long , int);
int qeth_threads_running(struct qeth_card *, unsigned long);
int qeth_wait_for_threads(struct qeth_card *, unsigned long);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 0d73a99..451f920 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -177,6 +177,23 @@
return "n/a";
}
+void qeth_set_recovery_task(struct qeth_card *card)
+{
+ card->recovery_task = current;
+}
+EXPORT_SYMBOL_GPL(qeth_set_recovery_task);
+
+void qeth_clear_recovery_task(struct qeth_card *card)
+{
+ card->recovery_task = NULL;
+}
+EXPORT_SYMBOL_GPL(qeth_clear_recovery_task);
+
+static bool qeth_is_recovery_task(const struct qeth_card *card)
+{
+ return card->recovery_task == current;
+}
+
void qeth_set_allowed_threads(struct qeth_card *card, unsigned long threads,
int clear_start_mask)
{
@@ -205,6 +222,8 @@
int qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
{
+ if (qeth_is_recovery_task(card))
+ return 0;
return wait_event_interruptible(card->wait_q,
qeth_threads_running(card, threads) == 0);
}
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index d690166..155b101 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -1143,6 +1143,7 @@
QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n");
+ qeth_set_recovery_task(card);
__qeth_l2_set_offline(card->gdev, 1);
rc = __qeth_l2_set_online(card->gdev, 1);
if (!rc)
@@ -1153,6 +1154,7 @@
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
+ qeth_clear_recovery_task(card);
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index 8710337..1f7edf1 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -3515,6 +3515,7 @@
QETH_CARD_TEXT(card, 2, "recover2");
dev_warn(&card->gdev->dev,
"A recovery process has been started for the device\n");
+ qeth_set_recovery_task(card);
__qeth_l3_set_offline(card->gdev, 1);
rc = __qeth_l3_set_online(card->gdev, 1);
if (!rc)
@@ -3525,6 +3526,7 @@
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
+ qeth_clear_recovery_task(card);
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index 1a9d1e3..c1441ed 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -282,7 +282,7 @@
return IRQ_HANDLED;
}
-static void __init reset_one_i2c(struct bbc_i2c_bus *bp)
+static void reset_one_i2c(struct bbc_i2c_bus *bp)
{
writeb(I2C_PCF_PIN, bp->i2c_control_regs + 0x0);
writeb(bp->own, bp->i2c_control_regs + 0x1);
@@ -291,7 +291,7 @@
writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0);
}
-static struct bbc_i2c_bus * __init attach_one_i2c(struct platform_device *op, int index)
+static struct bbc_i2c_bus * attach_one_i2c(struct platform_device *op, int index)
{
struct bbc_i2c_bus *bp;
struct device_node *dp;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index a044f59..d0fa4b6 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -1899,8 +1899,8 @@
sdev->allow_restart = 1;
blk_queue_rq_timeout(sdev->request_queue, 120 * HZ);
}
- scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
spin_unlock_irqrestore(shost->host_lock, lock_flags);
+ scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
return 0;
}
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index f328089..2197b57 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -5148,7 +5148,7 @@
ipr_trace;
}
- list_add_tail(&ipr_cmd->queue, &hrrq->hrrq_free_q);
+ list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
if (!ipr_is_naca_model(res))
res->needs_sync_complete = 1;
@@ -9349,7 +9349,10 @@
int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+ if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ rc = request_irq(ioa_cfg->vectors_info[0].vec, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
+ else
+ rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg);
if (rc) {
dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq);
return rc;
@@ -9371,7 +9374,10 @@
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- free_irq(pdev->irq, ioa_cfg);
+ if (ioa_cfg->intr_flag == IPR_USE_MSIX)
+ free_irq(ioa_cfg->vectors_info[0].vec, ioa_cfg);
+ else
+ free_irq(pdev->irq, ioa_cfg);
LEAVE;
@@ -9722,6 +9728,7 @@
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
flush_work(&ioa_cfg->work_q);
+ INIT_LIST_HEAD(&ioa_cfg->used_res_q);
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
spin_lock(&ipr_driver_lock);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index aec2e0d..55cbd01 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -235,6 +235,17 @@
linkrate = phy->linkrate;
memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
+ /* Handle vacant phy - rest of dr data is not valid so skip it */
+ if (phy->phy_state == PHY_VACANT) {
+ memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ phy->attached_dev_type = NO_DEVICE;
+ if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
+ phy->phy_id = phy_id;
+ goto skip;
+ } else
+ goto out;
+ }
+
phy->attached_dev_type = to_dev_type(dr);
if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state))
goto out;
@@ -272,6 +283,7 @@
phy->phy->maximum_linkrate = dr->pmax_linkrate;
phy->phy->negotiated_linkrate = phy->linkrate;
+ skip:
if (new_phy)
if (sas_phy_add(phy->phy)) {
sas_phy_free(phy->phy);
@@ -388,7 +400,7 @@
if (!disc_req)
return -ENOMEM;
- disc_resp = alloc_smp_req(DISCOVER_RESP_SIZE);
+ disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
if (!disc_resp) {
kfree(disc_req);
return -ENOMEM;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 74b67d9..d43faf3 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -438,11 +438,12 @@
struct lpfc_rqe *temp_hrqe;
struct lpfc_rqe *temp_drqe;
struct lpfc_register doorbell;
- int put_index = hq->host_index;
+ int put_index;
/* sanity check on queue memory */
if (unlikely(!hq) || unlikely(!dq))
return -ENOMEM;
+ put_index = hq->host_index;
temp_hrqe = hq->qe[hq->host_index].rqe;
temp_drqe = dq->qe[dq->host_index].rqe;
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 408d254..684cc34 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -1488,7 +1488,4 @@
int max_index;
};
-#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-
#endif /*LSI_MEGARAID_SAS_H */
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 9d53540..7c90d57 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3984,12 +3984,12 @@
if (reset_devices) {
pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
if (pos) {
- pci_read_config_word(pdev, msi_control_reg(pos),
+ pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS,
&control);
if (control & PCI_MSIX_FLAGS_ENABLE) {
dev_info(&pdev->dev, "resetting MSI-X\n");
pci_write_config_word(pdev,
- msi_control_reg(pos),
+ pos + PCI_MSIX_FLAGS,
control &
~PCI_MSIX_FLAGS_ENABLE);
}
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
index ce90d05..7455092 100644
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -703,7 +703,7 @@
{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9480,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -712,7 +712,7 @@
.driver_data = chip_9480,
},
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9445,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
@@ -721,7 +721,7 @@
.driver_data = chip_9445,
},
{
- .vendor = 0x1b4b,
+ .vendor = PCI_VENDOR_ID_MARVELL_EXT,
.device = 0x9485,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index 4594cca..c3601b5 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -49,8 +49,8 @@
MODULE_DESCRIPTION("Marvell UMI Driver");
static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = {
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) },
- { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) },
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) },
{ 0 }
};
diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h
index e360135..41f1687 100644
--- a/drivers/scsi/mvumi.h
+++ b/drivers/scsi/mvumi.h
@@ -32,7 +32,6 @@
#define VER_BUILD 1500
#define MV_DRIVER_NAME "mvumi"
-#define PCI_VENDOR_ID_MARVELL_2 0x1b4b
#define PCI_DEVICE_ID_MARVELL_MV9143 0x9143
#define PCI_DEVICE_ID_MARVELL_MV9580 0x9580
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 1d82eef..b3db9dc 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1938,11 +1938,6 @@
"Timer for the VP[%d] has stopped\n", vha->vp_idx);
}
- /* No pending activities shall be there on the vha now */
- if (ql2xextended_error_logging & ql_dbg_user)
- msleep(random32()%10); /* Just to see if something falls on
- * the net we have placed below */
-
BUG_ON(atomic_read(&vha->vref_count));
qla2x00_free_fcports(vha);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 1626de5..fbc305f 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -15,6 +15,7 @@
* | Mailbox commands | 0x115b | 0x111a-0x111b |
* | | | 0x112c-0x112e |
* | | | 0x113a |
+ * | | | 0x1155-0x1158 |
* | Device Discovery | 0x2087 | 0x2020-0x2022, |
* | | | 0x2016 |
* | Queue Command and IO tracing | 0x3031 | 0x3006-0x300b |
@@ -401,7 +402,7 @@
void *ring;
} aq, *aqp;
- if (!ha->tgt.atio_q_length)
+ if (!ha->tgt.atio_ring)
return ptr;
num_queues = 1;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index c650991..65c5ff7 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -863,7 +863,6 @@
#define MBX_1 BIT_1
#define MBX_0 BIT_0
-#define RNID_TYPE_SET_VERSION 0x9
#define RNID_TYPE_ASIC_TEMP 0xC
/*
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index eb3ca21..b310fa9 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -358,9 +358,6 @@
qla2x00_disable_fce_trace(scsi_qla_host_t *, uint64_t *, uint64_t *);
extern int
-qla2x00_set_driver_version(scsi_qla_host_t *, char *);
-
-extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint8_t *,
uint16_t, uint16_t, uint16_t, uint16_t);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index edf4d14..b592033 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -619,8 +619,6 @@
if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha))
qla24xx_read_fcp_prio_cfg(vha);
- qla2x00_set_driver_version(vha, QLA2XXX_VERSION);
-
return (rval);
}
@@ -1399,7 +1397,7 @@
mq_size += ha->max_rsp_queues *
(rsp->length * sizeof(response_t));
}
- if (ha->tgt.atio_q_length)
+ if (ha->tgt.atio_ring)
mq_size += ha->tgt.atio_q_length * sizeof(request_t);
/* Allocate memory for Fibre Channel Event Buffer. */
if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha))
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 186dd59..43345af 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3866,64 +3866,6 @@
return rval;
}
-int
-qla2x00_set_driver_version(scsi_qla_host_t *vha, char *version)
-{
- int rval;
- mbx_cmd_t mc;
- mbx_cmd_t *mcp = &mc;
- int len;
- uint16_t dwlen;
- uint8_t *str;
- dma_addr_t str_dma;
- struct qla_hw_data *ha = vha->hw;
-
- if (!IS_FWI2_CAPABLE(ha) || IS_QLA82XX(ha))
- return QLA_FUNCTION_FAILED;
-
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1155,
- "Entered %s.\n", __func__);
-
- str = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &str_dma);
- if (!str) {
- ql_log(ql_log_warn, vha, 0x1156,
- "Failed to allocate driver version param.\n");
- return QLA_MEMORY_ALLOC_FAILED;
- }
-
- memcpy(str, "\x7\x3\x11\x0", 4);
- dwlen = str[0];
- len = dwlen * sizeof(uint32_t) - 4;
- memset(str + 4, 0, len);
- if (len > strlen(version))
- len = strlen(version);
- memcpy(str + 4, version, len);
-
- mcp->mb[0] = MBC_SET_RNID_PARAMS;
- mcp->mb[1] = RNID_TYPE_SET_VERSION << 8 | dwlen;
- mcp->mb[2] = MSW(LSD(str_dma));
- mcp->mb[3] = LSW(LSD(str_dma));
- mcp->mb[6] = MSW(MSD(str_dma));
- mcp->mb[7] = LSW(MSD(str_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
- mcp->in_mb = MBX_0;
- mcp->tov = MBX_TOV_SECONDS;
- mcp->flags = 0;
- rval = qla2x00_mailbox_command(vha, mcp);
-
- if (rval != QLA_SUCCESS) {
- ql_dbg(ql_dbg_mbx, vha, 0x1157,
- "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
- } else {
- ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1158,
- "Done %s.\n", __func__);
- }
-
- dma_pool_free(ha->s_dma_pool, str, str_dma);
-
- return rval;
-}
-
static int
qla2x00_read_asic_temperature(scsi_qla_host_t *vha, uint16_t *temp)
{
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 2b6e478..ec54036 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.04.00.08-k"
+#define QLA2XXX_VERSION "8.04.00.13-k"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 4
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 8697447..2a32036 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -4112,6 +4112,10 @@
tpnt->disk = disk;
disk->private_data = &tpnt->driver;
disk->queue = SDp->request_queue;
+ /* SCSI tape doesn't register this gendisk via add_disk(). Manually
+ * take queue reference that release_disk() expects. */
+ if (!blk_get_queue(disk->queue))
+ goto out_put_disk;
tpnt->driver = &st_template;
tpnt->device = SDp;
@@ -4185,7 +4189,7 @@
idr_preload_end();
if (error < 0) {
pr_warn("st: idr allocation failed: %d\n", error);
- goto out_put_disk;
+ goto out_put_queue;
}
tpnt->index = error;
sprintf(disk->disk_name, "st%d", tpnt->index);
@@ -4211,6 +4215,8 @@
spin_lock(&st_index_lock);
idr_remove(&st_index_idr, tpnt->index);
spin_unlock(&st_index_lock);
+out_put_queue:
+ blk_put_queue(disk->queue);
out_put_disk:
put_disk(disk);
kfree(tpnt);
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c
index 4c0f6d8..7b0bce9 100644
--- a/drivers/ssb/driver_chipcommon_pmu.c
+++ b/drivers/ssb/driver_chipcommon_pmu.c
@@ -675,3 +675,32 @@
return 0;
}
}
+
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid)
+{
+ u32 pmu_ctl = 0;
+
+ switch (cc->dev->bus->chip_id) {
+ case 0x4322:
+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070);
+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a);
+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854);
+ if (spuravoid == 1)
+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828);
+ else
+ ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828);
+ pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD;
+ break;
+ case 43222:
+ /* TODO: BCM43222 requires updating PLLs too */
+ return;
+ default:
+ ssb_printk(KERN_ERR PFX
+ "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n",
+ cc->dev->bus->chip_id);
+ return;
+ }
+
+ chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl);
+}
+EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate);
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index ff1c5ee..cbe48ab 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -409,6 +409,7 @@
case REPORT_LUNS:
case RECEIVE_DIAGNOSTIC:
case SEND_DIAGNOSTIC:
+ return 0;
case MAINTENANCE_IN:
switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
@@ -451,6 +452,7 @@
switch (cdb[0]) {
case INQUIRY:
case REPORT_LUNS:
+ return 0;
case MAINTENANCE_IN:
switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
@@ -491,6 +493,7 @@
switch (cdb[0]) {
case INQUIRY:
case REPORT_LUNS:
+ return 0;
case MAINTENANCE_IN:
switch (cdb[1] & 0x1f) {
case MI_REPORT_TARGET_PGS:
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 484b6a3..302909c 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -2643,9 +2643,9 @@
mxvar_sdriver, brd->idx + i, &pdev->dev);
if (IS_ERR(tty_dev)) {
retval = PTR_ERR(tty_dev);
- for (i--; i >= 0; i--)
+ for (; i > 0; i--)
tty_unregister_device(mxvar_sdriver,
- brd->idx + i);
+ brd->idx + i - 1);
goto err_relbrd;
}
}
@@ -2751,9 +2751,9 @@
tty_dev = tty_port_register_device(&brd->ports[i].port,
mxvar_sdriver, brd->idx + i, NULL);
if (IS_ERR(tty_dev)) {
- for (i--; i >= 0; i--)
+ for (; i > 0; i--)
tty_unregister_device(mxvar_sdriver,
- brd->idx + i);
+ brd->idx + i - 1);
for (i = 0; i < brd->info->nports; i++)
tty_port_destroy(&brd->ports[i].port);
free_irq(brd->irq, brd);
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index b3455a9..35d9ab9 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -429,7 +429,6 @@
{
struct uart_8250_port uart;
int ret, line, flags = dev_id->driver_data;
- struct resource *res = NULL;
if (flags & UNKNOWN_DEV) {
ret = serial_pnp_guess_board(dev);
@@ -440,12 +439,11 @@
memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
uart.port.irq = pnp_irq(dev, 0);
- if ((flags & CIR_PORT) && pnp_port_valid(dev, 2))
- res = pnp_get_resource(dev, IORESOURCE_IO, 2);
- else if (pnp_port_valid(dev, 0))
- res = pnp_get_resource(dev, IORESOURCE_IO, 0);
- if (pnp_resource_enabled(res)) {
- uart.port.iobase = res->start;
+ if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
+ uart.port.iobase = pnp_port_start(dev, 2);
+ uart.port.iotype = UPIO_PORT;
+ } else if (pnp_port_valid(dev, 0)) {
+ uart.port.iobase = pnp_port_start(dev, 0);
uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
uart.port.mapbase = pnp_mem_start(dev, 0);
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 4dc4140..30d4f7a 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -886,6 +886,17 @@
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
/* FIFO ENABLE, DMA MODE */
+ up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
+ /*
+ * NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
+ * sets Enables the granularity of 1 for TRIGGER RX
+ * level. Along with setting RX FIFO trigger level
+ * to 1 (as noted below, 16 characters) and TLR[3:0]
+ * to zero this will result RX FIFO threshold level
+ * to 1 character, instead of 16 as noted in comment
+ * below.
+ */
+
/* Set receive FIFO threshold to 16 characters and
* transmit FIFO threshold to 16 spaces
*/
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 05400ac..b045268 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -941,6 +941,14 @@
EXPORT_SYMBOL(start_tty);
+static void tty_update_time(struct timespec *time)
+{
+ unsigned long sec = get_seconds();
+ sec -= sec % 60;
+ if ((long)(sec - time->tv_sec) > 0)
+ time->tv_sec = sec;
+}
+
/**
* tty_read - read method for tty device files
* @file: pointer to tty file
@@ -960,10 +968,11 @@
loff_t *ppos)
{
int i;
+ struct inode *inode = file_inode(file);
struct tty_struct *tty = file_tty(file);
struct tty_ldisc *ld;
- if (tty_paranoia_check(tty, file_inode(file), "tty_read"))
+ if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
return -EIO;
@@ -977,6 +986,9 @@
i = -EIO;
tty_ldisc_deref(ld);
+ if (i > 0)
+ tty_update_time(&inode->i_atime);
+
return i;
}
@@ -1077,8 +1089,10 @@
break;
cond_resched();
}
- if (written)
+ if (written) {
+ tty_update_time(&file_inode(file)->i_mtime);
ret = written;
+ }
out:
tty_write_unlock(tty);
return ret;
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 8189cb6..09d2e3f 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -70,7 +70,7 @@
pci_write_config_word(pdev, PCI_COMMAND, cmd);
}
- msix_pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ msix_pos = pdev->msix_cap;
if (msix_pos) {
u16 flags;
u32 table;
@@ -78,8 +78,8 @@
pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags);
pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table);
- vdev->msix_bar = table & PCI_MSIX_FLAGS_BIRMASK;
- vdev->msix_offset = table & ~PCI_MSIX_FLAGS_BIRMASK;
+ vdev->msix_bar = table & PCI_MSIX_TABLE_BIR;
+ vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET;
vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16;
} else
vdev->msix_bar = 0xFF;
@@ -183,7 +183,7 @@
u8 pos;
u16 flags;
- pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSI);
+ pos = vdev->pdev->msi_cap;
if (pos) {
pci_read_config_word(vdev->pdev,
pos + PCI_MSI_FLAGS, &flags);
@@ -194,7 +194,7 @@
u8 pos;
u16 flags;
- pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSIX);
+ pos = vdev->pdev->msix_cap;
if (pos) {
pci_read_config_word(vdev->pdev,
pos + PCI_MSIX_FLAGS, &flags);
@@ -346,6 +346,7 @@
if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
size_t size;
+ int max = vfio_pci_get_irq_count(vdev, hdr.index);
if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
size = sizeof(uint8_t);
@@ -355,7 +356,7 @@
return -EINVAL;
if (hdr.argsz - minsz < hdr.count * size ||
- hdr.count > vfio_pci_get_irq_count(vdev, hdr.index))
+ hdr.start >= max || hdr.start + hdr.count > max)
return -EINVAL;
data = memdup_user((void __user *)(arg + minsz),
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 2968b49..957a0b9 100644
--- a/drivers/vhost/tcm_vhost.c
+++ b/drivers/vhost/tcm_vhost.c
@@ -74,9 +74,8 @@
struct vhost_scsi {
/* Protected by vhost_scsi->dev.mutex */
- struct tcm_vhost_tpg *vs_tpg[VHOST_SCSI_MAX_TARGET];
+ struct tcm_vhost_tpg **vs_tpg;
char vs_vhost_wwpn[TRANSPORT_IQN_LEN];
- bool vs_endpoint;
struct vhost_dev dev;
struct vhost_virtqueue vqs[VHOST_SCSI_MAX_VQ];
@@ -579,9 +578,27 @@
}
}
+static void vhost_scsi_send_bad_target(struct vhost_scsi *vs,
+ struct vhost_virtqueue *vq, int head, unsigned out)
+{
+ struct virtio_scsi_cmd_resp __user *resp;
+ struct virtio_scsi_cmd_resp rsp;
+ int ret;
+
+ memset(&rsp, 0, sizeof(rsp));
+ rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
+ resp = vq->iov[out].iov_base;
+ ret = __copy_to_user(resp, &rsp, sizeof(rsp));
+ if (!ret)
+ vhost_add_used_and_signal(&vs->dev, vq, head, 0);
+ else
+ pr_err("Faulted on virtio_scsi_cmd_resp\n");
+}
+
static void vhost_scsi_handle_vq(struct vhost_scsi *vs,
struct vhost_virtqueue *vq)
{
+ struct tcm_vhost_tpg **vs_tpg;
struct virtio_scsi_cmd_req v_req;
struct tcm_vhost_tpg *tv_tpg;
struct tcm_vhost_cmd *tv_cmd;
@@ -590,8 +607,16 @@
int head, ret;
u8 target;
- /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */
- if (unlikely(!vs->vs_endpoint))
+ /*
+ * We can handle the vq only after the endpoint is setup by calling the
+ * VHOST_SCSI_SET_ENDPOINT ioctl.
+ *
+ * TODO: Check that we are running from vhost_worker which acts
+ * as read-side critical section for vhost kind of RCU.
+ * See the comments in struct vhost_virtqueue in drivers/vhost/vhost.h
+ */
+ vs_tpg = rcu_dereference_check(vq->private_data, 1);
+ if (!vs_tpg)
return;
mutex_lock(&vq->mutex);
@@ -661,23 +686,11 @@
/* Extract the tpgt */
target = v_req.lun[1];
- tv_tpg = vs->vs_tpg[target];
+ tv_tpg = ACCESS_ONCE(vs_tpg[target]);
/* Target does not exist, fail the request */
if (unlikely(!tv_tpg)) {
- struct virtio_scsi_cmd_resp __user *resp;
- struct virtio_scsi_cmd_resp rsp;
-
- memset(&rsp, 0, sizeof(rsp));
- rsp.response = VIRTIO_SCSI_S_BAD_TARGET;
- resp = vq->iov[out].iov_base;
- ret = __copy_to_user(resp, &rsp, sizeof(rsp));
- if (!ret)
- vhost_add_used_and_signal(&vs->dev,
- vq, head, 0);
- else
- pr_err("Faulted on virtio_scsi_cmd_resp\n");
-
+ vhost_scsi_send_bad_target(vs, vq, head, out);
continue;
}
@@ -690,22 +703,13 @@
if (IS_ERR(tv_cmd)) {
vq_err(vq, "vhost_scsi_allocate_cmd failed %ld\n",
PTR_ERR(tv_cmd));
- break;
+ goto err_cmd;
}
pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction"
": %d\n", tv_cmd, exp_data_len, data_direction);
tv_cmd->tvc_vhost = vs;
tv_cmd->tvc_vq = vq;
-
- if (unlikely(vq->iov[out].iov_len !=
- sizeof(struct virtio_scsi_cmd_resp))) {
- vq_err(vq, "Expecting virtio_scsi_cmd_resp, got %zu"
- " bytes, out: %d, in: %d\n",
- vq->iov[out].iov_len, out, in);
- break;
- }
-
tv_cmd->tvc_resp = vq->iov[out].iov_base;
/*
@@ -725,7 +729,7 @@
" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
scsi_command_size(tv_cmd->tvc_cdb),
TCM_VHOST_MAX_CDB_SIZE);
- break; /* TODO */
+ goto err_free;
}
tv_cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF;
@@ -738,7 +742,7 @@
data_direction == DMA_TO_DEVICE);
if (unlikely(ret)) {
vq_err(vq, "Failed to map iov to sgl\n");
- break; /* TODO */
+ goto err_free;
}
}
@@ -759,6 +763,13 @@
}
mutex_unlock(&vq->mutex);
+ return;
+
+err_free:
+ vhost_scsi_free_cmd(tv_cmd);
+err_cmd:
+ vhost_scsi_send_bad_target(vs, vq, head, out);
+ mutex_unlock(&vq->mutex);
}
static void vhost_scsi_ctl_handle_kick(struct vhost_work *work)
@@ -780,6 +791,20 @@
vhost_scsi_handle_vq(vs, vq);
}
+static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
+{
+ vhost_poll_flush(&vs->dev.vqs[index].poll);
+}
+
+static void vhost_scsi_flush(struct vhost_scsi *vs)
+{
+ int i;
+
+ for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
+ vhost_scsi_flush_vq(vs, i);
+ vhost_work_flush(&vs->dev, &vs->vs_completion_work);
+}
+
/*
* Called from vhost_scsi_ioctl() context to walk the list of available
* tcm_vhost_tpg with an active struct tcm_vhost_nexus
@@ -790,8 +815,10 @@
{
struct tcm_vhost_tport *tv_tport;
struct tcm_vhost_tpg *tv_tpg;
+ struct tcm_vhost_tpg **vs_tpg;
+ struct vhost_virtqueue *vq;
+ int index, ret, i, len;
bool match = false;
- int index, ret;
mutex_lock(&vs->dev.mutex);
/* Verify that ring has been setup correctly. */
@@ -803,6 +830,15 @@
}
}
+ len = sizeof(vs_tpg[0]) * VHOST_SCSI_MAX_TARGET;
+ vs_tpg = kzalloc(len, GFP_KERNEL);
+ if (!vs_tpg) {
+ mutex_unlock(&vs->dev.mutex);
+ return -ENOMEM;
+ }
+ if (vs->vs_tpg)
+ memcpy(vs_tpg, vs->vs_tpg, len);
+
mutex_lock(&tcm_vhost_mutex);
list_for_each_entry(tv_tpg, &tcm_vhost_list, tv_tpg_list) {
mutex_lock(&tv_tpg->tv_tpg_mutex);
@@ -817,14 +853,15 @@
tv_tport = tv_tpg->tport;
if (!strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
- if (vs->vs_tpg[tv_tpg->tport_tpgt]) {
+ if (vs->vs_tpg && vs->vs_tpg[tv_tpg->tport_tpgt]) {
mutex_unlock(&tv_tpg->tv_tpg_mutex);
mutex_unlock(&tcm_vhost_mutex);
mutex_unlock(&vs->dev.mutex);
+ kfree(vs_tpg);
return -EEXIST;
}
tv_tpg->tv_tpg_vhost_count++;
- vs->vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
+ vs_tpg[tv_tpg->tport_tpgt] = tv_tpg;
smp_mb__after_atomic_inc();
match = true;
}
@@ -835,12 +872,27 @@
if (match) {
memcpy(vs->vs_vhost_wwpn, t->vhost_wwpn,
sizeof(vs->vs_vhost_wwpn));
- vs->vs_endpoint = true;
+ for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+ vq = &vs->vqs[i];
+ /* Flushing the vhost_work acts as synchronize_rcu */
+ mutex_lock(&vq->mutex);
+ rcu_assign_pointer(vq->private_data, vs_tpg);
+ vhost_init_used(vq);
+ mutex_unlock(&vq->mutex);
+ }
ret = 0;
} else {
ret = -EEXIST;
}
+ /*
+ * Act as synchronize_rcu to make sure access to
+ * old vs->vs_tpg is finished.
+ */
+ vhost_scsi_flush(vs);
+ kfree(vs->vs_tpg);
+ vs->vs_tpg = vs_tpg;
+
mutex_unlock(&vs->dev.mutex);
return ret;
}
@@ -851,6 +903,8 @@
{
struct tcm_vhost_tport *tv_tport;
struct tcm_vhost_tpg *tv_tpg;
+ struct vhost_virtqueue *vq;
+ bool match = false;
int index, ret, i;
u8 target;
@@ -862,9 +916,14 @@
goto err_dev;
}
}
+
+ if (!vs->vs_tpg) {
+ mutex_unlock(&vs->dev.mutex);
+ return 0;
+ }
+
for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
target = i;
-
tv_tpg = vs->vs_tpg[target];
if (!tv_tpg)
continue;
@@ -886,10 +945,27 @@
}
tv_tpg->tv_tpg_vhost_count--;
vs->vs_tpg[target] = NULL;
- vs->vs_endpoint = false;
+ match = true;
mutex_unlock(&tv_tpg->tv_tpg_mutex);
}
+ if (match) {
+ for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) {
+ vq = &vs->vqs[i];
+ /* Flushing the vhost_work acts as synchronize_rcu */
+ mutex_lock(&vq->mutex);
+ rcu_assign_pointer(vq->private_data, NULL);
+ mutex_unlock(&vq->mutex);
+ }
+ }
+ /*
+ * Act as synchronize_rcu to make sure access to
+ * old vs->vs_tpg is finished.
+ */
+ vhost_scsi_flush(vs);
+ kfree(vs->vs_tpg);
+ vs->vs_tpg = NULL;
mutex_unlock(&vs->dev.mutex);
+
return 0;
err_tpg:
@@ -899,6 +975,24 @@
return ret;
}
+static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
+{
+ if (features & ~VHOST_SCSI_FEATURES)
+ return -EOPNOTSUPP;
+
+ mutex_lock(&vs->dev.mutex);
+ if ((features & (1 << VHOST_F_LOG_ALL)) &&
+ !vhost_log_access_ok(&vs->dev)) {
+ mutex_unlock(&vs->dev.mutex);
+ return -EFAULT;
+ }
+ vs->dev.acked_features = features;
+ smp_wmb();
+ vhost_scsi_flush(vs);
+ mutex_unlock(&vs->dev.mutex);
+ return 0;
+}
+
static int vhost_scsi_open(struct inode *inode, struct file *f)
{
struct vhost_scsi *s;
@@ -939,38 +1033,6 @@
return 0;
}
-static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
-{
- vhost_poll_flush(&vs->dev.vqs[index].poll);
-}
-
-static void vhost_scsi_flush(struct vhost_scsi *vs)
-{
- int i;
-
- for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
- vhost_scsi_flush_vq(vs, i);
- vhost_work_flush(&vs->dev, &vs->vs_completion_work);
-}
-
-static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
-{
- if (features & ~VHOST_SCSI_FEATURES)
- return -EOPNOTSUPP;
-
- mutex_lock(&vs->dev.mutex);
- if ((features & (1 << VHOST_F_LOG_ALL)) &&
- !vhost_log_access_ok(&vs->dev)) {
- mutex_unlock(&vs->dev.mutex);
- return -EFAULT;
- }
- vs->dev.acked_features = features;
- smp_wmb();
- vhost_scsi_flush(vs);
- mutex_unlock(&vs->dev.mutex);
- return 0;
-}
-
static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
unsigned long arg)
{
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4c1546f..981c1c0 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -31,26 +31,8 @@
This framework adds support for low-level control of the video
output switch.
-config DISPLAY_TIMING
- bool
-
-config VIDEOMODE
- bool
-
-config OF_DISPLAY_TIMING
- bool "Enable device tree display timing support"
- depends on OF
- select DISPLAY_TIMING
- help
- helper to parse display timings from the devicetree
-
-config OF_VIDEOMODE
- bool "Enable device tree videomode support"
- depends on OF
- select VIDEOMODE
- select OF_DISPLAY_TIMING
- help
- helper to get videomodes from the devicetree
+config VIDEOMODE_HELPERS
+ bool
config HDMI
bool
@@ -212,14 +194,6 @@
depends on FB
default n
-config FB_WMT_GE_ROPS
- tristate
- depends on FB
- default n
- ---help---
- Include functions for accelerated rectangle filling and area
- copying using WonderMedia Graphics Engine operations.
-
config FB_DEFERRED_IO
bool
depends on FB
@@ -1797,22 +1771,37 @@
option au1200fb:panel=<name>.
config FB_VT8500
- bool "VT8500 LCD Driver"
+ bool "VIA VT8500 framebuffer support"
depends on (FB = y) && ARM && ARCH_VT8500
- select FB_WMT_GE_ROPS
+ select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+ select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
select FB_SYS_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
help
This is the framebuffer driver for VIA VT8500 integrated LCD
controller.
config FB_WM8505
- bool "WM8505 frame buffer support"
+ bool "Wondermedia WM8xxx-series frame buffer support"
depends on (FB = y) && ARM && ARCH_VT8500
- select FB_WMT_GE_ROPS
+ select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS)
+ select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS)
select FB_SYS_IMAGEBLIT
+ select FB_MODE_HELPERS
+ select VIDEOMODE_HELPERS
help
- This is the framebuffer driver for WonderMedia WM8505/WM8650
- integrated LCD controller.
+ This is the framebuffer driver for WonderMedia WM8xxx-series
+ integrated LCD controller. This driver covers the WM8505, WM8650
+ and WM8850 SoCs.
+
+config FB_WMT_GE_ROPS
+ bool "VT8500/WM8xxx accelerated raster ops support"
+ depends on (FB = y) && (FB_VT8500 || FB_WM8505)
+ default n
+ help
+ This adds support for accelerated raster operations on the
+ VIA VT8500 and Wondermedia 85xx series SoCs.
source "drivers/video/geode/Kconfig"
@@ -2277,7 +2266,7 @@
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
select FB_DEFERRED_IO
- select INPUT_XEN_KBDDEV_FRONTEND
+ select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC
select XEN_XENBUS_FRONTEND
default y
help
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9df3873..e414378 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -171,7 +171,7 @@
#video output switch sysfs driver
obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
-obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
-obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
-obj-$(CONFIG_VIDEOMODE) += videomode.o
-obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
+obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
+ifeq ($(CONFIG_OF),y)
+obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
+endif
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 7fa1bf8..77cb4ff 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -3788,19 +3788,7 @@
},
};
-static int __init amifb_init(void)
-{
- return platform_driver_probe(&amifb_driver, amifb_probe);
-}
-
-module_init(amifb_init);
-
-static void __exit amifb_exit(void)
-{
- platform_driver_unregister(&amifb_driver);
-}
-
-module_exit(amifb_exit);
+module_platform_driver_probe(amifb_driver, amifb_probe);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:amiga-video");
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 025428e..98348ec 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -1158,18 +1158,7 @@
},
};
-static int __init atmel_lcdfb_init(void)
-{
- return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
-}
-
-static void __exit atmel_lcdfb_exit(void)
-{
- platform_driver_unregister(&atmel_lcdfb_driver);
-}
-
-module_init(atmel_lcdfb_init);
-module_exit(atmel_lcdfb_exit);
+module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/auo_k1900fb.c
index 1a9ac6e..f5b668e 100644
--- a/drivers/video/auo_k1900fb.c
+++ b/drivers/video/auo_k1900fb.c
@@ -60,9 +60,12 @@
static void auok1900_init(struct auok190xfb_par *par)
{
+ struct device *dev = par->info->device;
struct auok190x_board *board = par->board;
u16 init_param = 0;
+ pm_runtime_get_sync(dev);
+
init_param |= AUOK1900_INIT_TEMP_AVERAGE;
init_param |= AUOK1900_INIT_ROTATE(par->rotation);
init_param |= AUOK190X_INIT_INVERSE_WHITE;
@@ -74,6 +77,9 @@
/* let the controller finish */
board->wait_for_rdy(par);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
static void auok1900_update_region(struct auok190xfb_par *par, int mode,
@@ -82,6 +88,7 @@
struct device *dev = par->info->device;
unsigned char *buf = (unsigned char *)par->info->screen_base;
int xres = par->info->var.xres;
+ int line_length = par->info->fix.line_length;
u16 args[4];
pm_runtime_get_sync(dev);
@@ -100,9 +107,9 @@
args[1] = y1 + 1;
args[2] = xres;
args[3] = y2 - y1;
- buf += y1 * xres;
+ buf += y1 * line_length;
auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
- ((y2 - y1) * xres)/2, (u16 *) buf);
+ ((y2 - y1) * line_length)/2, (u16 *) buf);
auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
par->update_cnt++;
diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/auo_k1901fb.c
index d1db165..12b9adc 100644
--- a/drivers/video/auo_k1901fb.c
+++ b/drivers/video/auo_k1901fb.c
@@ -101,9 +101,12 @@
static void auok1901_init(struct auok190xfb_par *par)
{
+ struct device *dev = par->info->device;
struct auok190x_board *board = par->board;
u16 init_param = 0;
+ pm_runtime_get_sync(dev);
+
init_param |= AUOK190X_INIT_INVERSE_WHITE;
init_param |= AUOK190X_INIT_FORMAT0;
init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
@@ -113,6 +116,9 @@
/* let the controller finish */
board->wait_for_rdy(par);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
}
static void auok1901_update_region(struct auok190xfb_par *par, int mode,
@@ -121,6 +127,7 @@
struct device *dev = par->info->device;
unsigned char *buf = (unsigned char *)par->info->screen_base;
int xres = par->info->var.xres;
+ int line_length = par->info->fix.line_length;
u16 args[5];
pm_runtime_get_sync(dev);
@@ -139,9 +146,9 @@
args[1] = y1 + 1;
args[2] = xres;
args[3] = y2 - y1;
- buf += y1 * xres;
+ buf += y1 * line_length;
auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
- args, ((y2 - y1) * xres)/2,
+ args, ((y2 - y1) * line_length)/2,
(u16 *) buf);
auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
diff --git a/drivers/video/auo_k190x.c b/drivers/video/auo_k190x.c
index 53846cb..b1f19b2 100644
--- a/drivers/video/auo_k190x.c
+++ b/drivers/video/auo_k190x.c
@@ -40,6 +40,14 @@
.w = 1024,
.h = 768,
},
+ [AUOK190X_RESOLUTION_600_800] = {
+ .w = 600,
+ .h = 800,
+ },
+ [AUOK190X_RESOLUTION_768_1024] = {
+ .w = 768,
+ .h = 1024,
+ },
};
/*
@@ -60,8 +68,48 @@
par->board->set_ctl(par, AUOK190X_I80_DC, 1);
}
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
- u16 *data)
+/**
+ * Conversion of 16bit color to 4bit grayscale
+ * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
+ */
+static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
+{
+ return ((((data & 0xF800) >> var->red.offset) * 77 +
+ ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
+ ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
+}
+
+static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
+ u16 *data)
+{
+ struct fb_var_screeninfo *var = &par->info->var;
+ struct device *dev = par->info->device;
+ int i;
+ u16 tmp;
+
+ if (size & 7) {
+ dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
+ size);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < (size >> 2); i++) {
+ par->board->set_ctl(par, AUOK190X_I80_WR, 0);
+
+ tmp = (rgb565_to_gray4(data[4*i], var) & 0x000F);
+ tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
+ tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
+ tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
+
+ par->board->set_hdb(par, tmp);
+ par->board->set_ctl(par, AUOK190X_I80_WR, 1);
+ }
+
+ return 0;
+}
+
+static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
+ u16 *data)
{
struct device *dev = par->info->device;
int i;
@@ -91,6 +139,23 @@
return 0;
}
+static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
+ u16 *data)
+{
+ struct fb_info *info = par->info;
+ struct device *dev = par->info->device;
+
+ if (info->var.bits_per_pixel == 8 && info->var.grayscale)
+ auok190x_issue_pixels_gray8(par, size, data);
+ else if (info->var.bits_per_pixel == 16)
+ auok190x_issue_pixels_rgb565(par, size, data);
+ else
+ dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
+ info->var.bits_per_pixel, info->var.grayscale);
+
+ return 0;
+}
+
static u16 auok190x_read_data(struct auok190xfb_par *par)
{
u16 data;
@@ -224,8 +289,8 @@
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct auok190xfb_par *par = info->par;
+ u16 line_length = info->fix.line_length;
u16 yres = info->var.yres;
- u16 xres = info->var.xres;
u16 y1 = 0, h = 0;
int prev_index = -1;
struct page *cur;
@@ -254,7 +319,7 @@
}
/* height increment is fixed per page */
- h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
+ h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
/* calculate number of pages from pixel height */
threshold = par->consecutive_threshold / h_inc;
@@ -265,7 +330,7 @@
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
if (prev_index < 0) {
/* just starting so assign first page */
- y1 = (cur->index << PAGE_SHIFT) / xres;
+ y1 = (cur->index << PAGE_SHIFT) / line_length;
h = h_inc;
} else if ((cur->index - prev_index) <= threshold) {
/* page is within our threshold for single updates */
@@ -275,7 +340,7 @@
par->update_partial(par, y1, y1 + h);
/* start over with our non consecutive page */
- y1 = (cur->index << PAGE_SHIFT) / xres;
+ y1 = (cur->index << PAGE_SHIFT) / line_length;
h = h_inc;
}
prev_index = cur->index;
@@ -376,27 +441,127 @@
static int auok190xfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
- if (info->var.xres != var->xres || info->var.yres != var->yres ||
- info->var.xres_virtual != var->xres_virtual ||
- info->var.yres_virtual != var->yres_virtual) {
- pr_info("%s: Resolution not supported: X%u x Y%u\n",
- __func__, var->xres, var->yres);
+ struct device *dev = info->device;
+ struct auok190xfb_par *par = info->par;
+ struct panel_info *panel = &panel_table[par->resolution];
+ int size;
+
+ /*
+ * Color depth
+ */
+
+ if (var->bits_per_pixel == 8 && var->grayscale == 1) {
+ /*
+ * For 8-bit grayscale, R, G, and B offset are equal.
+ */
+ var->red.length = 8;
+ var->red.offset = 0;
+ var->red.msb_right = 0;
+
+ var->green.length = 8;
+ var->green.offset = 0;
+ var->green.msb_right = 0;
+
+ var->blue.length = 8;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ } else if (var->bits_per_pixel == 16) {
+ var->red.length = 5;
+ var->red.offset = 11;
+ var->red.msb_right = 0;
+
+ var->green.length = 6;
+ var->green.offset = 5;
+ var->green.msb_right = 0;
+
+ var->blue.length = 5;
+ var->blue.offset = 0;
+ var->blue.msb_right = 0;
+
+ var->transp.length = 0;
+ var->transp.offset = 0;
+ var->transp.msb_right = 0;
+ } else {
+ dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
+ info->var.bits_per_pixel, info->var.grayscale);
return -EINVAL;
}
/*
+ * Dimensions
+ */
+
+ switch (var->rotate) {
+ case FB_ROTATE_UR:
+ case FB_ROTATE_UD:
+ var->xres = panel->w;
+ var->yres = panel->h;
+ break;
+ case FB_ROTATE_CW:
+ case FB_ROTATE_CCW:
+ var->xres = panel->h;
+ var->yres = panel->w;
+ break;
+ default:
+ dev_dbg(dev, "Invalid rotation request\n");
+ return -EINVAL;
+ }
+
+ var->xres_virtual = var->xres;
+ var->yres_virtual = var->yres;
+
+ /*
* Memory limit
*/
- if ((info->fix.line_length * var->yres_virtual) > info->fix.smem_len) {
- pr_info("%s: Memory Limit requested yres_virtual = %u\n",
- __func__, var->yres_virtual);
+ size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
+ if (size > info->fix.smem_len) {
+ dev_err(dev, "Memory limit exceeded, requested %dK\n",
+ size >> 10);
return -ENOMEM;
}
return 0;
}
+static int auok190xfb_set_fix(struct fb_info *info)
+{
+ struct fb_fix_screeninfo *fix = &info->fix;
+ struct fb_var_screeninfo *var = &info->var;
+
+ fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->accel = FB_ACCEL_NONE;
+ fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
+ : FB_VISUAL_TRUECOLOR;
+ fix->xpanstep = 0;
+ fix->ypanstep = 0;
+ fix->ywrapstep = 0;
+
+ return 0;
+}
+
+static int auok190xfb_set_par(struct fb_info *info)
+{
+ struct auok190xfb_par *par = info->par;
+
+ par->rotation = info->var.rotate;
+ auok190xfb_set_fix(info);
+
+ /* reinit the controller to honor the rotation */
+ par->init(par);
+
+ /* wait for init to complete */
+ par->board->wait_for_rdy(par);
+
+ return 0;
+}
+
static struct fb_ops auok190xfb_ops = {
.owner = THIS_MODULE,
.fb_read = fb_sys_read,
@@ -405,6 +570,7 @@
.fb_copyarea = auok190xfb_copyarea,
.fb_imageblit = auok190xfb_imageblit,
.fb_check_var = auok190xfb_check_var,
+ .fb_set_par = auok190xfb_set_par,
};
/*
@@ -588,10 +754,16 @@
static void auok190x_recover(struct auok190xfb_par *par)
{
+ struct device *dev = par->info->device;
+
auok190x_power(par, 0);
msleep(100);
auok190x_power(par, 1);
+ /* after powercycling the device, it's always active */
+ pm_runtime_set_active(dev);
+ par->standby = 0;
+
par->init(par);
/* wait for init to complete */
@@ -875,42 +1047,17 @@
/* initialise fix, var, resolution and rotation */
strlcpy(info->fix.id, init->id, 16);
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
- info->fix.xpanstep = 0;
- info->fix.ypanstep = 0;
- info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_NONE;
-
info->var.bits_per_pixel = 8;
info->var.grayscale = 1;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
panel = &panel_table[board->resolution];
- /* if 90 degree rotation, switch width and height */
- if (board->rotation & 1) {
- info->var.xres = panel->h;
- info->var.yres = panel->w;
- info->var.xres_virtual = panel->h;
- info->var.yres_virtual = panel->w;
- info->fix.line_length = panel->h;
- } else {
- info->var.xres = panel->w;
- info->var.yres = panel->h;
- info->var.xres_virtual = panel->w;
- info->var.yres_virtual = panel->h;
- info->fix.line_length = panel->w;
- }
-
par->resolution = board->resolution;
- par->rotation = board->rotation;
+ par->rotation = 0;
/* videomemory handling */
- videomemorysize = roundup((panel->w * panel->h), PAGE_SIZE);
+ videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
videomemory = vmalloc(videomemorysize);
if (!videomemory) {
ret = -ENOMEM;
@@ -924,6 +1071,12 @@
info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
info->fbops = &auok190xfb_ops;
+ ret = auok190xfb_check_var(&info->var, info);
+ if (ret)
+ goto err_defio;
+
+ auok190xfb_set_fix(info);
+
/* deferred io init */
info->fbdefio = devm_kzalloc(info->device,
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 0c189b3..67b77b4 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -285,36 +285,26 @@
static int controlfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
- unsigned long off, start;
- u32 len;
+ unsigned long mmio_pgoff;
+ unsigned long start;
+ u32 len;
- off = vma->vm_pgoff << PAGE_SHIFT;
+ start = info->fix.smem_start;
+ len = info->fix.smem_len;
+ mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+ if (vma->vm_pgoff >= mmio_pgoff) {
+ if (info->var.accel_flags)
+ return -EINVAL;
+ vma->vm_pgoff -= mmio_pgoff;
+ start = info->fix.mmio_start;
+ len = info->fix.mmio_len;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ } else {
+ /* framebuffer */
+ vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
+ }
- /* frame buffer memory */
- start = info->fix.smem_start;
- len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.smem_len);
- if (off >= len) {
- /* memory mapped io */
- off -= len;
- if (info->var.accel_flags)
- return -EINVAL;
- start = info->fix.mmio_start;
- len = PAGE_ALIGN((start & ~PAGE_MASK)+info->fix.mmio_len);
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- } else {
- /* framebuffer */
- vma->vm_page_prot = pgprot_cached_wthru(vma->vm_page_prot);
- }
- start &= PAGE_MASK;
- if ((vma->vm_end - vma->vm_start + off) > len)
- return -EINVAL;
- off += start;
- vma->vm_pgoff = off >> PAGE_SHIFT;
- if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
- return -EAGAIN;
-
- return 0;
+ return vm_iomap_memory(vma, start, len);
}
static int controlfb_blank(int blank_mode, struct fb_info *info)
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index fac7df6..3dd43ca 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -35,8 +35,6 @@
#include <video/exynos_mipi_dsim.h>
-#include <plat/fb.h>
-
#include "exynos_mipi_dsi_common.h"
#include "exynos_mipi_dsi_lowlevel.h"
diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c
index c70cb89..520fc9b 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_common.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_common.c
@@ -31,8 +31,6 @@
#include <video/mipi_display.h>
#include <video/exynos_mipi_dsim.h>
-#include <mach/map.h>
-
#include "exynos_mipi_dsi_regs.h"
#include "exynos_mipi_dsi_lowlevel.h"
#include "exynos_mipi_dsi_common.h"
diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
index 95cb99a..15c5abd 100644
--- a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
+++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
@@ -26,8 +26,6 @@
#include <video/exynos_mipi_dsim.h>
-#include <mach/map.h>
-
#include "exynos_mipi_dsi_regs.h"
void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c
index 7d106f1f..27fc956 100644
--- a/drivers/video/fb-puv3.c
+++ b/drivers/video/fb-puv3.c
@@ -640,21 +640,9 @@
int unifb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long pos = info->fix.smem_start + offset;
-
- if (offset + size > info->fix.smem_len)
- return -EINVAL;
-
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- if (io_remap_pfn_range(vma, vma->vm_start, pos >> PAGE_SHIFT, size,
- vma->vm_page_prot))
- return -EAGAIN;
-
- /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
- return 0;
+ return vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
}
static struct fb_ops unifb_ops = {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7c25408..dcb669e 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1373,15 +1373,12 @@
{
struct fb_info *info = file_fb_info(file);
struct fb_ops *fb;
- unsigned long off;
+ unsigned long mmio_pgoff;
unsigned long start;
u32 len;
if (!info)
return -ENODEV;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
- off = vma->vm_pgoff << PAGE_SHIFT;
fb = info->fbops;
if (!fb)
return -ENODEV;
@@ -1393,32 +1390,29 @@
return res;
}
- /* frame buffer memory */
+ /*
+ * Ugh. This can be either the frame buffer mapping, or
+ * if pgoff points past it, the mmio mapping.
+ */
start = info->fix.smem_start;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
- if (off >= len) {
- /* memory mapped io */
- off -= len;
+ len = info->fix.smem_len;
+ mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
+ if (vma->vm_pgoff >= mmio_pgoff) {
if (info->var.accel_flags) {
mutex_unlock(&info->mm_lock);
return -EINVAL;
}
+
+ vma->vm_pgoff -= mmio_pgoff;
start = info->fix.mmio_start;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+ len = info->fix.mmio_len;
}
mutex_unlock(&info->mm_lock);
- start &= PAGE_MASK;
- if ((vma->vm_end - vma->vm_start + off) > len)
- return -EINVAL;
- off += start;
- vma->vm_pgoff = off >> PAGE_SHIFT;
- /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by io_remap_pfn_range()*/
+
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
- fb_pgprotect(file, vma, off);
- if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot))
- return -EAGAIN;
- return 0;
+ fb_pgprotect(file, vma, start);
+
+ return vm_iomap_memory(vma, start, len);
}
static int
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 7f67099..6103fa6 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -1376,7 +1376,7 @@
return err;
}
-#if IS_ENABLED(CONFIG_VIDEOMODE)
+#ifdef CONFIG_VIDEOMODE_HELPERS
int fb_videomode_from_videomode(const struct videomode *vm,
struct fb_videomode *fbmode)
{
@@ -1398,13 +1398,13 @@
fbmode->sync = 0;
fbmode->vmode = 0;
- if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+ if (vm->flags & DISPLAY_FLAGS_HSYNC_HIGH)
fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
+ if (vm->flags & DISPLAY_FLAGS_VSYNC_HIGH)
fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
+ if (vm->flags & DISPLAY_FLAGS_INTERLACED)
fbmode->vmode |= FB_VMODE_INTERLACED;
- if (vm->data_flags & DISPLAY_FLAGS_DOUBLESCAN)
+ if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
fbmode->vmode |= FB_VMODE_DOUBLE;
fbmode->flag = 0;
@@ -1424,9 +1424,8 @@
return 0;
}
EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
-#endif
-#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+#ifdef CONFIG_OF
static inline void dump_fb_videomode(const struct fb_videomode *m)
{
pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
@@ -1465,7 +1464,8 @@
return 0;
}
EXPORT_SYMBOL_GPL(of_get_fb_videomode);
-#endif
+#endif /* CONFIG_OF */
+#endif /* CONFIG_VIDEOMODE_HELPERS */
#else
int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index 41fbd94..6c27805 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -375,7 +375,10 @@
struct diu_ad dummy_ad __aligned(8);
struct diu_ad ad[NUM_AOIS] __aligned(8);
u8 gamma[256 * 3] __aligned(32);
- u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
+ /* It's easier to parse the cursor data as little-endian */
+ __le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
+ /* Blank cursor data -- used to hide the cursor */
+ __le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
uint8_t edid_data[EDID_LENGTH];
bool has_edid;
} __aligned(32);
@@ -824,7 +827,6 @@
/* Program DIU registers */
out_be32(&hw->gamma, DMA_ADDR(data, gamma));
- out_be32(&hw->cursor, DMA_ADDR(data, cursor));
out_be32(&hw->bgnd, 0x007F7F7F); /* Set background to grey */
out_be32(&hw->disp_size, (var->yres << 16) | var->xres);
@@ -968,6 +970,156 @@
}
/*
+ * Copies a cursor image from user space to the proper place in driver
+ * memory so that the hardware can display the cursor image.
+ *
+ * Cursor data is represented as a sequence of 'width' bits packed into bytes.
+ * That is, the first 8 bits are in the first byte, the second 8 bits in the
+ * second byte, and so on. Therefore, the each row of the cursor is (width +
+ * 7) / 8 bytes of 'data'
+ *
+ * The DIU only supports cursors up to 32x32 (MAX_CURS). We reject cursors
+ * larger than this, so we already know that 'width' <= 32. Therefore, we can
+ * simplify our code by using a 32-bit big-endian integer ("line") to read in
+ * a single line of pixels, and only look at the top 'width' bits of that
+ * integer.
+ *
+ * This could result in an unaligned 32-bit read. For example, if the cursor
+ * is 24x24, then the first three bytes of 'image' contain the pixel data for
+ * the top line of the cursor. We do a 32-bit read of 'image', but we look
+ * only at the top 24 bits. Then we increment 'image' by 3 bytes. The next
+ * read is unaligned. The only problem is that we might read past the end of
+ * 'image' by 1-3 bytes, but that should not cause any problems.
+ */
+static void fsl_diu_load_cursor_image(struct fb_info *info,
+ const void *image, uint16_t bg, uint16_t fg,
+ unsigned int width, unsigned int height)
+{
+ struct mfb_info *mfbi = info->par;
+ struct fsl_diu_data *data = mfbi->parent;
+ __le16 *cursor = data->cursor;
+ __le16 _fg = cpu_to_le16(fg);
+ __le16 _bg = cpu_to_le16(bg);
+ unsigned int h, w;
+
+ for (h = 0; h < height; h++) {
+ uint32_t mask = 1 << 31;
+ uint32_t line = be32_to_cpup(image);
+
+ for (w = 0; w < width; w++) {
+ cursor[w] = (line & mask) ? _fg : _bg;
+ mask >>= 1;
+ }
+
+ cursor += MAX_CURS;
+ image += DIV_ROUND_UP(width, 8);
+ }
+}
+
+/*
+ * Set a hardware cursor. The image data for the cursor is passed via the
+ * fb_cursor object.
+ */
+static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ struct mfb_info *mfbi = info->par;
+ struct fsl_diu_data *data = mfbi->parent;
+ struct diu __iomem *hw = data->diu_reg;
+
+ if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+ return -EINVAL;
+
+ /* The cursor size has changed */
+ if (cursor->set & FB_CUR_SETSIZE) {
+ /*
+ * The DIU cursor is a fixed size, so when we get this
+ * message, instead of resizing the cursor, we just clear
+ * all the image data, in expectation of new data. However,
+ * in tests this control does not appear to be normally
+ * called.
+ */
+ memset(data->cursor, 0, sizeof(data->cursor));
+ }
+
+ /* The cursor position has changed (cursor->image.dx|dy) */
+ if (cursor->set & FB_CUR_SETPOS) {
+ uint32_t xx, yy;
+
+ yy = (cursor->image.dy - info->var.yoffset) & 0x7ff;
+ xx = (cursor->image.dx - info->var.xoffset) & 0x7ff;
+
+ out_be32(&hw->curs_pos, yy << 16 | xx);
+ }
+
+ /*
+ * FB_CUR_SETIMAGE - the cursor image has changed
+ * FB_CUR_SETCMAP - the cursor colors has changed
+ * FB_CUR_SETSHAPE - the cursor bitmask has changed
+ */
+ if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+ unsigned int image_size =
+ DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+ unsigned int image_words =
+ DIV_ROUND_UP(image_size, sizeof(uint32_t));
+ unsigned int bg_idx = cursor->image.bg_color;
+ unsigned int fg_idx = cursor->image.fg_color;
+ uint8_t buffer[image_size];
+ uint32_t *image, *source, *mask;
+ uint16_t fg, bg;
+ unsigned int i;
+
+ if (info->state != FBINFO_STATE_RUNNING)
+ return 0;
+
+ /*
+ * Determine the size of the cursor image data. Normally,
+ * it's 8x16.
+ */
+ image_size = DIV_ROUND_UP(cursor->image.width, 8) *
+ cursor->image.height;
+
+ bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+ ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+ ((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
+ 1 << 15;
+
+ fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+ ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+ ((info->cmap.blue[fg_idx] & 0xf8) >> 3) |
+ 1 << 15;
+
+ /* Use 32-bit operations on the data to improve performance */
+ image = (uint32_t *)buffer;
+ source = (uint32_t *)cursor->image.data;
+ mask = (uint32_t *)cursor->mask;
+
+ if (cursor->rop == ROP_XOR)
+ for (i = 0; i < image_words; i++)
+ image[i] = source[i] ^ mask[i];
+ else
+ for (i = 0; i < image_words; i++)
+ image[i] = source[i] & mask[i];
+
+ fsl_diu_load_cursor_image(info, image, bg, fg,
+ cursor->image.width, cursor->image.height);
+ };
+
+ /*
+ * Show or hide the cursor. The cursor data is always stored in the
+ * 'cursor' memory block, and the actual cursor position is always in
+ * the DIU's CURS_POS register. To hide the cursor, we redirect the
+ * CURSOR register to a blank cursor. The show the cursor, we
+ * redirect the CURSOR register to the real cursor data.
+ */
+ if (cursor->enable)
+ out_be32(&hw->cursor, DMA_ADDR(data, cursor));
+ else
+ out_be32(&hw->cursor, DMA_ADDR(data, blank_cursor));
+
+ return 0;
+}
+
+/*
* Using the fb_var_screeninfo in fb_info we set the resolution of this
* particular framebuffer. This function alters the fb_fix_screeninfo stored
* in fb_info. It does not alter var in fb_info since we are using that
@@ -1312,6 +1464,7 @@
.fb_ioctl = fsl_diu_ioctl,
.fb_open = fsl_diu_open,
.fb_release = fsl_diu_release,
+ .fb_cursor = fsl_diu_cursor,
};
static int install_fb(struct fb_info *info)
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index bda5e39..ceab370 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1016,7 +1016,9 @@
/* check range */
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
- if (offset + size > gbe_mem_size)
+ if (size > gbe_mem_size)
+ return -EINVAL;
+ if (offset > gbe_mem_size - size)
return -EINVAL;
/* remap using the fastest write-through mode on architecture */
diff --git a/drivers/video/mmp/core.c b/drivers/video/mmp/core.c
index 9ed8341..84de263 100644
--- a/drivers/video/mmp/core.c
+++ b/drivers/video/mmp/core.c
@@ -252,7 +252,5 @@
kfree(path);
mutex_unlock(&disp_lock);
-
- dev_info(path->dev, "de-register %s\n", path->name);
}
EXPORT_SYMBOL_GPL(mmp_unregister_path);
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
index 13ecd98..56009bc 100644
--- a/drivers/video/of_display_timing.c
+++ b/drivers/video/of_display_timing.c
@@ -79,25 +79,24 @@
ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
- dt->dmt_flags = 0;
- dt->data_flags = 0;
+ dt->flags = 0;
if (!of_property_read_u32(np, "vsync-active", &val))
- dt->dmt_flags |= val ? VESA_DMT_VSYNC_HIGH :
- VESA_DMT_VSYNC_LOW;
+ dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+ DISPLAY_FLAGS_VSYNC_LOW;
if (!of_property_read_u32(np, "hsync-active", &val))
- dt->dmt_flags |= val ? VESA_DMT_HSYNC_HIGH :
- VESA_DMT_HSYNC_LOW;
+ dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+ DISPLAY_FLAGS_HSYNC_LOW;
if (!of_property_read_u32(np, "de-active", &val))
- dt->data_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+ dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
DISPLAY_FLAGS_DE_LOW;
if (!of_property_read_u32(np, "pixelclk-active", &val))
- dt->data_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+ dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
DISPLAY_FLAGS_PIXDATA_NEGEDGE;
if (of_property_read_bool(np, "interlaced"))
- dt->data_flags |= DISPLAY_FLAGS_INTERLACED;
+ dt->flags |= DISPLAY_FLAGS_INTERLACED;
if (of_property_read_bool(np, "doublescan"))
- dt->data_flags |= DISPLAY_FLAGS_DOUBLESCAN;
+ dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
if (ret) {
pr_err("%s: error reading timing properties\n",
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
index 5b8066c..111c2d1 100644
--- a/drivers/video/of_videomode.c
+++ b/drivers/video/of_videomode.c
@@ -43,7 +43,7 @@
if (index == OF_USE_NATIVE_MODE)
index = disp->native_mode;
- ret = videomode_from_timing(disp, vm, index);
+ ret = videomode_from_timings(disp, vm, index);
if (ret)
return ret;
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig
index e512581..0bc3a93 100644
--- a/drivers/video/omap/Kconfig
+++ b/drivers/video/omap/Kconfig
@@ -39,17 +39,6 @@
the Mobile Industry Processor Interface DBI-C/DCS
specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
-config FB_OMAP_CONSISTENT_DMA_SIZE
- int "Consistent DMA memory size (MB)"
- depends on FB_OMAP
- range 1 14
- default 2
- help
- Increase the DMA consistent memory size according to your video
- memory needs, for example if you want to use multiple planes.
- The size must be 2MB aligned.
- If unsure say 1.
-
config FB_OMAP_DMA_TUNE
bool "Set DMA SDRAM access priority high"
depends on FB_OMAP
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index ca585ef..717f13a 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -1101,41 +1101,25 @@
struct omapfb_info *ofbi = FB2OFB(fbi);
struct fb_fix_screeninfo *fix = &fbi->fix;
struct omapfb2_mem_region *rg;
- unsigned long off;
unsigned long start;
u32 len;
- int r = -EINVAL;
-
- if (vma->vm_end - vma->vm_start == 0)
- return 0;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
- off = vma->vm_pgoff << PAGE_SHIFT;
+ int r;
rg = omapfb_get_mem_region(ofbi->region);
start = omapfb_get_region_paddr(ofbi);
len = fix->smem_len;
- if (off >= len)
- goto error;
- if ((vma->vm_end - vma->vm_start + off) > len)
- goto error;
- off += start;
+ DBG("user mmap region start %lx, len %d, off %lx\n", start, len,
+ vma->vm_pgoff << PAGE_SHIFT);
- DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
-
- vma->vm_pgoff = off >> PAGE_SHIFT;
- /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &mmap_user_ops;
vma->vm_private_data = rg;
- if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot)) {
- r = -EAGAIN;
+
+ r = vm_iomap_memory(vma, start, len);
+ if (r)
goto error;
- }
/* vm_ops.open won't be called for mmap itself. */
atomic_inc(&rg->map_count);
@@ -1144,7 +1128,7 @@
return 0;
- error:
+error:
omapfb_put_mem_region(ofbi->region);
return r;
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 10560ef..5261229 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -397,18 +397,7 @@
.remove = __exit_p(vrfb_remove),
};
-static int __init vrfb_init(void)
-{
- return platform_driver_probe(&vrfb_driver, &vrfb_probe);
-}
-
-static void __exit vrfb_exit(void)
-{
- platform_driver_unregister(&vrfb_driver);
-}
-
-module_init(vrfb_init);
-module_exit(vrfb_exit);
+module_platform_driver_probe(vrfb_driver, vrfb_probe);
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
MODULE_DESCRIPTION("OMAP VRFB");
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index 920c27b..d9f08c6 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -705,21 +705,15 @@
static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
- unsigned long size, offset;
+ int r;
- size = vma->vm_end - vma->vm_start;
- offset = vma->vm_pgoff << PAGE_SHIFT;
- if (offset + size > info->fix.smem_len)
- return -EINVAL;
-
- offset += info->fix.smem_start;
- if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- return -EAGAIN;
+ r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len);
dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n",
- offset, vma->vm_start);
- return 0;
+ info->fix.smem_start + vma->vm_pgoff << PAGE_SHIFT,
+ vma->vm_start);
+
+ return r;
}
/*
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 968a625..2e7991c 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -24,10 +24,9 @@
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/platform_data/video_s3c.h>
#include <video/samsung_fimd.h>
-#include <mach/map.h>
-#include <plat/fb.h>
/* This driver will export a number of framebuffer interfaces depending
* on the configuration passed in via the platform data. Each fb instance
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cfbde5e..f34c858 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -556,7 +556,7 @@
struct vm_area_struct *vma)
{
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
- unsigned long start, len, off = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
if (off < info->fix.smem_len) {
vma->vm_pgoff += 1; /* skip over the palette */
@@ -564,19 +564,9 @@
fbi->map_dma, fbi->map_size);
}
- start = info->fix.mmio_start;
- len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
-
- if ((vma->vm_end - vma->vm_start + off) > len)
- return -EINVAL;
-
- off += start & PAGE_MASK;
- vma->vm_pgoff = off >> PAGE_SHIFT;
- vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
+
+ return vm_iomap_memory(vma, info->fix.mmio_start, info->fix.mmio_len);
}
static struct fb_ops sa1100fb_ops = {
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index 2331fad..b2a8912 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -705,23 +705,17 @@
static int sgivwfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ int r;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
- if (offset + size > sgivwfb_mem_size)
- return -EINVAL;
- offset += sgivwfb_mem_phys;
pgprot_val(vma->vm_page_prot) =
- pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
- vma->vm_flags |= VM_IO;
- if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- return -EAGAIN;
+ pgprot_val(vma->vm_page_prot) | _PAGE_PCD;
+
+ r = vm_iomap_memory(vma, sgivwfb_mem_phys, sgivwfb_mem_size);
+
printk(KERN_DEBUG "sgivwfb: mmap framebuffer P(%lx)->V(%lx)\n",
offset, vma->vm_start);
- return 0;
+
+ return r;
}
int __init sgivwfb_setup(char *options)
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 701b461..6cad530 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -581,17 +581,7 @@
},
};
-static int __init sh_mipi_init(void)
-{
- return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
-}
-module_init(sh_mipi_init);
-
-static void __exit sh_mipi_exit(void)
-{
- platform_driver_unregister(&sh_mipi_driver);
-}
-module_exit(sh_mipi_exit);
+module_platform_driver_probe(sh_mipi_driver, sh_mipi_probe);
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 930e550..bfe4728 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -1445,17 +1445,7 @@
},
};
-static int __init sh_hdmi_init(void)
-{
- return platform_driver_probe(&sh_hdmi_driver, sh_hdmi_probe);
-}
-module_init(sh_hdmi_init);
-
-static void __exit sh_hdmi_exit(void)
-{
- platform_driver_unregister(&sh_hdmi_driver);
-}
-module_exit(sh_hdmi_exit);
+module_platform_driver_probe(sh_hdmi_driver, sh_hdmi_probe);
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
MODULE_DESCRIPTION("SuperH / ARM-shmobile HDMI driver");
diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c
index 97bd662..b2b33fc 100644
--- a/drivers/video/smscufx.c
+++ b/drivers/video/smscufx.c
@@ -782,7 +782,11 @@
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
- if (offset + size > info->fix.smem_len)
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+ if (size > info->fix.smem_len)
+ return -EINVAL;
+ if (offset > info->fix.smem_len - size)
return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset;
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 86d449e..ec03e72 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -324,7 +324,11 @@
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
- if (offset + size > info->fix.smem_len)
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+ return -EINVAL;
+ if (size > info->fix.smem_len)
+ return -EINVAL;
+ if (offset > info->fix.smem_len - size)
return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset;
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
index 0aa516f..09a1366 100644
--- a/drivers/video/vermilion/vermilion.c
+++ b/drivers/video/vermilion/vermilion.c
@@ -1003,24 +1003,18 @@
static int vmlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct vml_info *vinfo = container_of(info, struct vml_info, info);
- unsigned long size = vma->vm_end - vma->vm_start;
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
int ret;
- if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
- return -EINVAL;
- if (offset + size > vinfo->vram_contig_size)
- return -EINVAL;
ret = vmlfb_vram_offset(vinfo, offset);
if (ret)
return -EINVAL;
- offset += vinfo->vram_start;
+
pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
pgprot_val(vma->vm_page_prot) &= ~_PAGE_PWT;
- if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT,
- size, vma->vm_page_prot))
- return -EAGAIN;
- return 0;
+
+ return vm_iomap_memory(vma, vinfo->vram_start,
+ vinfo->vram_contig_size);
}
static int vmlfb_sync(struct fb_info *info)
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 8bc1f93..ee5985e 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -420,9 +420,12 @@
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long page, pos;
- if (offset + size > info->fix.smem_len) {
+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
return -EINVAL;
- }
+ if (size > info->fix.smem_len)
+ return -EINVAL;
+ if (offset > info->fix.smem_len - size)
+ return -EINVAL;
pos = (unsigned long)info->fix.smem_start + offset;
diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
index 21c47a2..df375c9 100644
--- a/drivers/video/videomode.c
+++ b/drivers/video/videomode.c
@@ -11,7 +11,25 @@
#include <video/display_timing.h>
#include <video/videomode.h>
-int videomode_from_timing(const struct display_timings *disp,
+void videomode_from_timing(const struct display_timing *dt,
+ struct videomode *vm)
+{
+ vm->pixelclock = dt->pixelclock.typ;
+ vm->hactive = dt->hactive.typ;
+ vm->hfront_porch = dt->hfront_porch.typ;
+ vm->hback_porch = dt->hback_porch.typ;
+ vm->hsync_len = dt->hsync_len.typ;
+
+ vm->vactive = dt->vactive.typ;
+ vm->vfront_porch = dt->vfront_porch.typ;
+ vm->vback_porch = dt->vback_porch.typ;
+ vm->vsync_len = dt->vsync_len.typ;
+
+ vm->flags = dt->flags;
+}
+EXPORT_SYMBOL_GPL(videomode_from_timing);
+
+int videomode_from_timings(const struct display_timings *disp,
struct videomode *vm, unsigned int index)
{
struct display_timing *dt;
@@ -20,20 +38,8 @@
if (!dt)
return -EINVAL;
- vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
- vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
- vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
- vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
- vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
-
- vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
- vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
- vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
- vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
-
- vm->dmt_flags = dt->dmt_flags;
- vm->data_flags = dt->data_flags;
+ videomode_from_timing(dt, vm);
return 0;
}
-EXPORT_SYMBOL_GPL(videomode_from_timing);
+EXPORT_SYMBOL_GPL(videomode_from_timings);
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index aa2579c..9547e18 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -15,22 +15,21 @@
* GNU General Public License for more details.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/dma-mapping.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/wait.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <video/of_display_timing.h>
#include "vt8500lcdfb.h"
#include "wmt_ge_rops.h"
@@ -277,11 +276,11 @@
{
struct vt8500lcd_info *fbi;
struct resource *res;
+ struct display_timings *disp_timing;
void *addr;
int irq, ret;
struct fb_videomode of_mode;
- struct device_node *np;
u32 bpp;
dma_addr_t fb_mem_phys;
unsigned long fb_mem_len;
@@ -346,32 +345,18 @@
goto failed_free_res;
}
- np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
- if (!np) {
- pr_err("%s: No display description in Device Tree\n", __func__);
- ret = -EINVAL;
- goto failed_free_res;
- }
+ disp_timing = of_get_display_timings(pdev->dev.of_node);
+ if (!disp_timing)
+ return -EINVAL;
- /*
- * This code is copied from Sascha Hauer's of_videomode helper
- * and can be replaced with a call to the helper once mainlined
- */
- ret = 0;
- ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
- ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
- ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
- ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
- ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
- ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
- ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
- ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
- ret |= of_property_read_u32(np, "bpp", &bpp);
- if (ret) {
- pr_err("%s: Unable to read display properties\n", __func__);
- goto failed_free_res;
- }
- of_mode.vmode = FB_VMODE_NONINTERLACED;
+ ret = of_get_fb_videomode(pdev->dev.of_node, &of_mode,
+ OF_USE_NATIVE_MODE);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+ if (ret)
+ return ret;
/* try allocating the framebuffer */
fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 4dd0580..01f9ace 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -14,25 +14,25 @@
* GNU General Public License for more details.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/fb.h>
+#include <linux/errno.h>
+#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
+#include <linux/kernel.h>
+#include <linux/memblock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
-#include <linux/memblock.h>
-
-#include <linux/platform_data/video-vt8500lcdfb.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <video/of_display_timing.h>
#include "wm8505fb_regs.h"
#include "wmt_ge_rops.h"
@@ -263,26 +263,22 @@
static int wm8505fb_probe(struct platform_device *pdev)
{
struct wm8505fb_info *fbi;
- struct resource *res;
+ struct resource *res;
+ struct display_timings *disp_timing;
void *addr;
int ret;
- struct fb_videomode of_mode;
- struct device_node *np;
+ struct fb_videomode mode;
u32 bpp;
dma_addr_t fb_mem_phys;
unsigned long fb_mem_len;
void *fb_mem_virt;
- ret = -ENOMEM;
- fbi = NULL;
-
fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
sizeof(u32) * 16, GFP_KERNEL);
if (!fbi) {
dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
- ret = -ENOMEM;
- goto failed;
+ return -ENOMEM;
}
strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -308,54 +304,23 @@
fbi->fb.pseudo_palette = addr;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no I/O memory resource defined\n");
- ret = -ENODEV;
- goto failed_fbi;
- }
+ fbi->regbase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(fbi->regbase))
+ return PTR_ERR(fbi->regbase);
- res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to request I/O memory\n");
- ret = -EBUSY;
- goto failed_fbi;
- }
+ disp_timing = of_get_display_timings(pdev->dev.of_node);
+ if (!disp_timing)
+ return -EINVAL;
- fbi->regbase = ioremap(res->start, resource_size(res));
- if (fbi->regbase == NULL) {
- dev_err(&pdev->dev, "failed to map I/O memory\n");
- ret = -EBUSY;
- goto failed_free_res;
- }
+ ret = of_get_fb_videomode(pdev->dev.of_node, &mode, OF_USE_NATIVE_MODE);
+ if (ret)
+ return ret;
- np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
- if (!np) {
- pr_err("%s: No display description in Device Tree\n", __func__);
- ret = -EINVAL;
- goto failed_free_res;
- }
+ ret = of_property_read_u32(pdev->dev.of_node, "bits-per-pixel", &bpp);
+ if (ret)
+ return ret;
- /*
- * This code is copied from Sascha Hauer's of_videomode helper
- * and can be replaced with a call to the helper once mainlined
- */
- ret = 0;
- ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
- ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
- ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
- ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
- ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
- ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
- ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
- ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
- ret |= of_property_read_u32(np, "bpp", &bpp);
- if (ret) {
- pr_err("%s: Unable to read display properties\n", __func__);
- goto failed_free_res;
- }
-
- of_mode.vmode = FB_VMODE_NONINTERLACED;
- fb_videomode_to_var(&fbi->fb.var, &of_mode);
+ fb_videomode_to_var(&fbi->fb.var, &mode);
fbi->fb.var.nonstd = 0;
fbi->fb.var.activate = FB_ACTIVATE_NOW;
@@ -364,16 +329,16 @@
fbi->fb.var.width = -1;
/* try allocating the framebuffer */
- fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
- fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+ fb_mem_len = mode.xres * mode.yres * 2 * (bpp / 8);
+ fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
GFP_KERNEL);
if (!fb_mem_virt) {
pr_err("%s: Failed to allocate framebuffer\n", __func__);
return -ENOMEM;
- };
+ }
- fbi->fb.var.xres_virtual = of_mode.xres;
- fbi->fb.var.yres_virtual = of_mode.yres * 2;
+ fbi->fb.var.xres_virtual = mode.xres;
+ fbi->fb.var.yres_virtual = mode.yres * 2;
fbi->fb.var.bits_per_pixel = bpp;
fbi->fb.fix.smem_start = fb_mem_phys;
@@ -381,28 +346,29 @@
fbi->fb.screen_base = fb_mem_virt;
fbi->fb.screen_size = fb_mem_len;
- if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
- dev_err(&pdev->dev, "Failed to allocate color map\n");
- ret = -ENOMEM;
- goto failed_free_io;
- }
-
- wm8505fb_init_hw(&fbi->fb);
-
- fbi->contrast = 0x80;
+ fbi->contrast = 0x10;
ret = wm8505fb_set_par(&fbi->fb);
if (ret) {
dev_err(&pdev->dev, "Failed to set parameters\n");
- goto failed_free_cmap;
+ return ret;
}
+ if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+ dev_err(&pdev->dev, "Failed to allocate color map\n");
+ return -ENOMEM;
+ }
+
+ wm8505fb_init_hw(&fbi->fb);
+
platform_set_drvdata(pdev, fbi);
ret = register_framebuffer(&fbi->fb);
if (ret < 0) {
dev_err(&pdev->dev,
"Failed to register framebuffer device: %d\n", ret);
- goto failed_free_cmap;
+ if (fbi->fb.cmap.len)
+ fb_dealloc_cmap(&fbi->fb.cmap);
+ return ret;
}
ret = device_create_file(&pdev->dev, &dev_attr_contrast);
@@ -416,25 +382,11 @@
fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
return 0;
-
-failed_free_cmap:
- if (fbi->fb.cmap.len)
- fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_io:
- iounmap(fbi->regbase);
-failed_free_res:
- release_mem_region(res->start, resource_size(res));
-failed_fbi:
- platform_set_drvdata(pdev, NULL);
- kfree(fbi);
-failed:
- return ret;
}
static int wm8505fb_remove(struct platform_device *pdev)
{
struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
- struct resource *res;
device_remove_file(&pdev->dev, &dev_attr_contrast);
@@ -445,13 +397,6 @@
if (fbi->fb.cmap.len)
fb_dealloc_cmap(&fbi->fb.cmap);
- iounmap(fbi->regbase);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- kfree(fbi);
-
return 0;
}
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
index 8738075..f73ec63 100644
--- a/drivers/video/wmt_ge_rops.h
+++ b/drivers/video/wmt_ge_rops.h
@@ -1,5 +1,28 @@
+#ifdef CONFIG_FB_WMT_GE_ROPS
+
extern void wmt_ge_fillrect(struct fb_info *info,
const struct fb_fillrect *rect);
extern void wmt_ge_copyarea(struct fb_info *info,
const struct fb_copyarea *area);
extern int wmt_ge_sync(struct fb_info *info);
+
+#else
+
+static inline int wmt_ge_sync(struct fb_info *p)
+{
+ return 0;
+}
+
+static inline void wmt_ge_fillrect(struct fb_info *p,
+ const struct fb_fillrect *rect)
+{
+ sys_fillrect(p, rect);
+}
+
+static inline void wmt_ge_copyarea(struct fb_info *p,
+ const struct fb_copyarea *area)
+{
+ sys_copyarea(p, area);
+}
+
+#endif
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 9fcc70c..e89fc31 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -117,7 +117,7 @@
config AT91RM9200_WATCHDOG
tristate "AT91RM9200 watchdog"
- depends on ARCH_AT91
+ depends on ARCH_AT91RM9200
help
Watchdog timer embedded into AT91RM9200 chips. This will reboot your
system when the timeout is reached.
diff --git a/drivers/xen/events.c b/drivers/xen/events.c
index aa85881..d8cc812 100644
--- a/drivers/xen/events.c
+++ b/drivers/xen/events.c
@@ -85,8 +85,7 @@
* event channel - irq->event channel mapping
* cpu - cpu this event channel is bound to
* index - type-specific information:
- * PIRQ - vector, with MSB being "needs EIO", or physical IRQ of the HVM
- * guest, or GSI (real passthrough IRQ) of the device.
+ * PIRQ - physical IRQ, GSI, flags, and owner domain
* VIRQ - virq number
* IPI - IPI vector
* EVTCHN -
@@ -105,7 +104,6 @@
struct {
unsigned short pirq;
unsigned short gsi;
- unsigned char vector;
unsigned char flags;
uint16_t domid;
} pirq;
@@ -211,7 +209,6 @@
unsigned short evtchn,
unsigned short pirq,
unsigned short gsi,
- unsigned short vector,
uint16_t domid,
unsigned char flags)
{
@@ -221,7 +218,6 @@
info->u.pirq.pirq = pirq;
info->u.pirq.gsi = gsi;
- info->u.pirq.vector = vector;
info->u.pirq.domid = domid;
info->u.pirq.flags = flags;
}
@@ -519,6 +515,9 @@
{
struct irq_info *info = irq_get_handler_data(irq);
+ if (WARN_ON(!info))
+ return;
+
list_del(&info->list);
irq_set_handler_data(irq, NULL);
@@ -714,7 +713,7 @@
goto out;
}
- xen_irq_info_pirq_init(irq, 0, pirq, gsi, irq_op.vector, DOMID_SELF,
+ xen_irq_info_pirq_init(irq, 0, pirq, gsi, DOMID_SELF,
shareable ? PIRQ_SHAREABLE : 0);
pirq_query_unmask(irq);
@@ -762,8 +761,7 @@
}
int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
- int pirq, int vector, const char *name,
- domid_t domid)
+ int pirq, const char *name, domid_t domid)
{
int irq, ret;
@@ -776,7 +774,7 @@
irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq,
name);
- xen_irq_info_pirq_init(irq, 0, pirq, 0, vector, domid, 0);
+ xen_irq_info_pirq_init(irq, 0, pirq, 0, domid, 0);
ret = irq_set_msi_desc(irq, msidesc);
if (ret < 0)
goto error_irq;
@@ -1008,6 +1006,9 @@
int evtchn = evtchn_from_irq(irq);
struct irq_info *info = irq_get_handler_data(irq);
+ if (WARN_ON(!info))
+ return;
+
mutex_lock(&irq_mapping_update_lock);
if (info->refcnt > 0) {
@@ -1135,6 +1136,10 @@
void unbind_from_irqhandler(unsigned int irq, void *dev_id)
{
+ struct irq_info *info = irq_get_handler_data(irq);
+
+ if (WARN_ON(!info))
+ return;
free_irq(irq, dev_id);
unbind_from_irq(irq);
}
@@ -1316,7 +1321,7 @@
{
int start_word_idx, start_bit_idx;
int word_idx, bit_idx;
- int i;
+ int i, irq;
int cpu = get_cpu();
struct shared_info *s = HYPERVISOR_shared_info;
struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
@@ -1324,6 +1329,8 @@
do {
xen_ulong_t pending_words;
+ xen_ulong_t pending_bits;
+ struct irq_desc *desc;
vcpu_info->evtchn_upcall_pending = 0;
@@ -1335,6 +1342,17 @@
* selector flag. xchg_xen_ulong must contain an
* appropriate barrier.
*/
+ if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) {
+ int evtchn = evtchn_from_irq(irq);
+ word_idx = evtchn / BITS_PER_LONG;
+ pending_bits = evtchn % BITS_PER_LONG;
+ if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) {
+ desc = irq_to_desc(irq);
+ if (desc)
+ generic_handle_irq_desc(irq, desc);
+ }
+ }
+
pending_words = xchg_xen_ulong(&vcpu_info->evtchn_pending_sel, 0);
start_word_idx = __this_cpu_read(current_word_idx);
@@ -1343,7 +1361,6 @@
word_idx = start_word_idx;
for (i = 0; pending_words != 0; i++) {
- xen_ulong_t pending_bits;
xen_ulong_t words;
words = MASK_LSBS(pending_words, word_idx);
@@ -1372,8 +1389,7 @@
do {
xen_ulong_t bits;
- int port, irq;
- struct irq_desc *desc;
+ int port;
bits = MASK_LSBS(pending_bits, bit_idx);
@@ -1446,6 +1462,9 @@
{
struct irq_info *info = info_for_irq(irq);
+ if (WARN_ON(!info))
+ return;
+
/* Make sure the irq is masked, since the new event channel
will also be masked. */
disable_irq(irq);
@@ -1719,7 +1738,12 @@
int xen_test_irq_shared(int irq)
{
struct irq_info *info = info_for_irq(irq);
- struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
+ struct physdev_irq_status_query irq_status;
+
+ if (WARN_ON(!info))
+ return -ENOENT;
+
+ irq_status.irq = info->u.pirq.pirq;
if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
return 0;
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 90e34ac..8abd7d5 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <linux/syscore_ops.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
#include <acpi/processor.h>
@@ -51,9 +52,9 @@
/* Which ACPI ID we have processed from 'struct acpi_processor'. */
static unsigned long *acpi_ids_done;
/* Which ACPI ID exist in the SSDT/DSDT processor definitions. */
-static unsigned long __initdata *acpi_id_present;
+static unsigned long *acpi_id_present;
/* And if there is an _CST definition (or a PBLK) for the ACPI IDs */
-static unsigned long __initdata *acpi_id_cst_present;
+static unsigned long *acpi_id_cst_present;
static int push_cxx_to_hypervisor(struct acpi_processor *_pr)
{
@@ -329,7 +330,7 @@
* for_each_[present|online]_cpu macros which are banded to the virtual
* CPU amount.
*/
-static acpi_status __init
+static acpi_status
read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
{
u32 acpi_id;
@@ -384,12 +385,16 @@
return AE_OK;
}
-static int __init check_acpi_ids(struct acpi_processor *pr_backup)
+static int check_acpi_ids(struct acpi_processor *pr_backup)
{
if (!pr_backup)
return -ENODEV;
+ if (acpi_id_present && acpi_id_cst_present)
+ /* OK, done this once .. skip to uploading */
+ goto upload;
+
/* All online CPUs have been processed at this stage. Now verify
* whether in fact "online CPUs" == physical CPUs.
*/
@@ -408,6 +413,7 @@
read_acpi_id, NULL, NULL, NULL);
acpi_get_devices("ACPI0007", read_acpi_id, NULL, NULL);
+upload:
if (!bitmap_equal(acpi_id_present, acpi_ids_done, nr_acpi_bits)) {
unsigned int i;
for_each_set_bit(i, acpi_id_present, nr_acpi_bits) {
@@ -417,10 +423,7 @@
(void)upload_pm_data(pr_backup);
}
}
- kfree(acpi_id_present);
- acpi_id_present = NULL;
- kfree(acpi_id_cst_present);
- acpi_id_cst_present = NULL;
+
return 0;
}
static int __init check_prereq(void)
@@ -467,10 +470,47 @@
free_percpu(acpi_perf_data);
}
-static int __init xen_acpi_processor_init(void)
+static int xen_upload_processor_pm_data(void)
{
struct acpi_processor *pr_backup = NULL;
unsigned int i;
+ int rc = 0;
+
+ pr_info(DRV_NAME "Uploading Xen processor PM info\n");
+
+ for_each_possible_cpu(i) {
+ struct acpi_processor *_pr;
+ _pr = per_cpu(processors, i /* APIC ID */);
+ if (!_pr)
+ continue;
+
+ if (!pr_backup) {
+ pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
+ if (pr_backup)
+ memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
+ }
+ (void)upload_pm_data(_pr);
+ }
+
+ rc = check_acpi_ids(pr_backup);
+ kfree(pr_backup);
+
+ return rc;
+}
+
+static void xen_acpi_processor_resume(void)
+{
+ bitmap_zero(acpi_ids_done, nr_acpi_bits);
+ xen_upload_processor_pm_data();
+}
+
+static struct syscore_ops xap_syscore_ops = {
+ .resume = xen_acpi_processor_resume,
+};
+
+static int __init xen_acpi_processor_init(void)
+{
+ unsigned int i;
int rc = check_prereq();
if (rc)
@@ -514,27 +554,12 @@
goto err_out;
}
- for_each_possible_cpu(i) {
- struct acpi_processor *_pr;
- _pr = per_cpu(processors, i /* APIC ID */);
- if (!_pr)
- continue;
-
- if (!pr_backup) {
- pr_backup = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
- if (pr_backup)
- memcpy(pr_backup, _pr, sizeof(struct acpi_processor));
- }
- (void)upload_pm_data(_pr);
- }
- rc = check_acpi_ids(pr_backup);
-
- kfree(pr_backup);
- pr_backup = NULL;
-
+ rc = xen_upload_processor_pm_data();
if (rc)
goto err_unregister;
+ register_syscore_ops(&xap_syscore_ops);
+
return 0;
err_unregister:
for_each_possible_cpu(i) {
@@ -552,7 +577,10 @@
{
int i;
+ unregister_syscore_ops(&xap_syscore_ops);
kfree(acpi_ids_done);
+ kfree(acpi_id_present);
+ kfree(acpi_id_cst_present);
for_each_possible_cpu(i) {
struct acpi_processor_performance *perf;
perf = per_cpu_ptr(acpi_perf_data, i);
diff --git a/fs/aio.c b/fs/aio.c
index 3f941f2..1dc8786 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1029,9 +1029,9 @@
spin_unlock(&info->ring_lock);
out:
- kunmap_atomic(ring);
dprintk("leaving aio_read_evt: %d h%lu t%lu\n", ret,
(unsigned long)ring->head, (unsigned long)ring->tail);
+ kunmap_atomic(ring);
return ret;
}
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 3939829..86af964 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1137,6 +1137,7 @@
goto whole;
if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
goto whole;
+ return 0;
}
/* Do not dump I/O mapped devices or special mappings */
diff --git a/fs/bio.c b/fs/bio.c
index bb5768f..b96fc6c 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1428,8 +1428,6 @@
else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
error = -EIO;
- trace_block_bio_complete(bio, error);
-
if (bio->bi_end_io)
bio->bi_end_io(bio, error);
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 451fad9..ef96381 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -317,6 +317,7 @@
unsigned long src_ptr;
unsigned long dst_ptr;
int overwrite_root = 0;
+ bool inode_item = key->type == BTRFS_INODE_ITEM_KEY;
if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
overwrite_root = 1;
@@ -326,6 +327,9 @@
/* look for the key in the destination tree */
ret = btrfs_search_slot(NULL, root, key, path, 0, 0);
+ if (ret < 0)
+ return ret;
+
if (ret == 0) {
char *src_copy;
char *dst_copy;
@@ -367,6 +371,30 @@
return 0;
}
+ /*
+ * We need to load the old nbytes into the inode so when we
+ * replay the extents we've logged we get the right nbytes.
+ */
+ if (inode_item) {
+ struct btrfs_inode_item *item;
+ u64 nbytes;
+
+ item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+ struct btrfs_inode_item);
+ nbytes = btrfs_inode_nbytes(path->nodes[0], item);
+ item = btrfs_item_ptr(eb, slot,
+ struct btrfs_inode_item);
+ btrfs_set_inode_nbytes(eb, item, nbytes);
+ }
+ } else if (inode_item) {
+ struct btrfs_inode_item *item;
+
+ /*
+ * New inode, set nbytes to 0 so that the nbytes comes out
+ * properly when we replay the extents.
+ */
+ item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item);
+ btrfs_set_inode_nbytes(eb, item, 0);
}
insert:
btrfs_release_path(path);
@@ -486,7 +514,7 @@
int found_type;
u64 extent_end;
u64 start = key->offset;
- u64 saved_nbytes;
+ u64 nbytes = 0;
struct btrfs_file_extent_item *item;
struct inode *inode = NULL;
unsigned long size;
@@ -496,10 +524,19 @@
found_type = btrfs_file_extent_type(eb, item);
if (found_type == BTRFS_FILE_EXTENT_REG ||
- found_type == BTRFS_FILE_EXTENT_PREALLOC)
- extent_end = start + btrfs_file_extent_num_bytes(eb, item);
- else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
+ found_type == BTRFS_FILE_EXTENT_PREALLOC) {
+ nbytes = btrfs_file_extent_num_bytes(eb, item);
+ extent_end = start + nbytes;
+
+ /*
+ * We don't add to the inodes nbytes if we are prealloc or a
+ * hole.
+ */
+ if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
+ nbytes = 0;
+ } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
size = btrfs_file_extent_inline_len(eb, item);
+ nbytes = btrfs_file_extent_ram_bytes(eb, item);
extent_end = ALIGN(start + size, root->sectorsize);
} else {
ret = 0;
@@ -548,7 +585,6 @@
}
btrfs_release_path(path);
- saved_nbytes = inode_get_bytes(inode);
/* drop any overlapping extents */
ret = btrfs_drop_extents(trans, root, inode, start, extent_end, 1);
BUG_ON(ret);
@@ -635,7 +671,7 @@
BUG_ON(ret);
}
- inode_set_bytes(inode, saved_nbytes);
+ inode_add_bytes(inode, nbytes);
ret = btrfs_update_inode(trans, root, inode);
out:
if (inode)
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 991c63c..21b3a29 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1575,14 +1575,24 @@
}
break;
case Opt_blank_pass:
- vol->password = NULL;
- break;
- case Opt_pass:
/* passwords have to be handled differently
* to allow the character used for deliminator
* to be passed within them
*/
+ /*
+ * Check if this is a case where the password
+ * starts with a delimiter
+ */
+ tmp_end = strchr(data, '=');
+ tmp_end++;
+ if (!(tmp_end < end && tmp_end[1] == delim)) {
+ /* No it is not. Set the password to NULL */
+ vol->password = NULL;
+ break;
+ }
+ /* Yes it is. Drop down to Opt_pass below.*/
+ case Opt_pass:
/* Obtain the value string */
value = strchr(data, '=');
value++;
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 412e6ed..e4141f2 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -80,13 +80,6 @@
int rc;
mutex_lock(&ecryptfs_daemon_hash_mux);
- rc = try_module_get(THIS_MODULE);
- if (rc == 0) {
- rc = -EIO;
- printk(KERN_ERR "%s: Error attempting to increment module use "
- "count; rc = [%d]\n", __func__, rc);
- goto out_unlock_daemon_list;
- }
rc = ecryptfs_find_daemon_by_euid(&daemon);
if (!rc) {
rc = -EINVAL;
@@ -96,7 +89,7 @@
if (rc) {
printk(KERN_ERR "%s: Error attempting to spawn daemon; "
"rc = [%d]\n", __func__, rc);
- goto out_module_put_unlock_daemon_list;
+ goto out_unlock_daemon_list;
}
mutex_lock(&daemon->mux);
if (daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN) {
@@ -108,9 +101,6 @@
atomic_inc(&ecryptfs_num_miscdev_opens);
out_unlock_daemon:
mutex_unlock(&daemon->mux);
-out_module_put_unlock_daemon_list:
- if (rc)
- module_put(THIS_MODULE);
out_unlock_daemon_list:
mutex_unlock(&ecryptfs_daemon_hash_mux);
return rc;
@@ -147,7 +137,6 @@
"bug.\n", __func__, rc);
BUG();
}
- module_put(THIS_MODULE);
return rc;
}
@@ -471,6 +460,7 @@
static const struct file_operations ecryptfs_miscdev_fops = {
+ .owner = THIS_MODULE,
.open = ecryptfs_miscdev_open,
.poll = ecryptfs_miscdev_poll,
.read = ecryptfs_miscdev_read,
diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c
index a94f0f7..fe0a762 100644
--- a/fs/hfsplus/extents.c
+++ b/fs/hfsplus/extents.c
@@ -533,7 +533,7 @@
struct address_space *mapping = inode->i_mapping;
struct page *page;
void *fsdata;
- u32 size = inode->i_size;
+ loff_t size = inode->i_size;
res = pagecache_write_begin(NULL, mapping, size, 0,
AOP_FLAG_UNINTERRUPTIBLE,
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 84e3d85..523464e 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -110,7 +110,7 @@
* way when do_mmap_pgoff unwinds (may be important on powerpc
* and ia64).
*/
- vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_flags |= VM_HUGETLB | VM_DONTEXPAND;
vma->vm_ops = &hugetlb_vm_ops;
if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT))
diff --git a/fs/inode.c b/fs/inode.c
index f5f7c06..a898b3d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -725,7 +725,7 @@
* inode to the back of the list so we don't spin on it.
*/
if (!spin_trylock(&inode->i_lock)) {
- list_move_tail(&inode->i_lru, &sb->s_inode_lru);
+ list_move(&inode->i_lru, &sb->s_inode_lru);
continue;
}
diff --git a/fs/namespace.c b/fs/namespace.c
index d581e45..341d3f5 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1690,7 +1690,7 @@
if (IS_ERR(mnt)) {
err = PTR_ERR(mnt);
- goto out;
+ goto out2;
}
err = graft_tree(mnt, path);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index ac4fc9a..66b6664 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -300,7 +300,7 @@
struct rpc_cred *cred)
{
struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
- struct nfs_client *pos, *n, *prev = NULL;
+ struct nfs_client *pos, *prev = NULL;
struct nfs4_setclientid_res clid = {
.clientid = new->cl_clientid,
.confirm = new->cl_confirm,
@@ -308,10 +308,23 @@
int status = -NFS4ERR_STALE_CLIENTID;
spin_lock(&nn->nfs_client_lock);
- list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+ list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
/* If "pos" isn't marked ready, we can't trust the
* remaining fields in "pos" */
- if (pos->cl_cons_state < NFS_CS_READY)
+ if (pos->cl_cons_state > NFS_CS_READY) {
+ atomic_inc(&pos->cl_count);
+ spin_unlock(&nn->nfs_client_lock);
+
+ if (prev)
+ nfs_put_client(prev);
+ prev = pos;
+
+ status = nfs_wait_client_init_complete(pos);
+ spin_lock(&nn->nfs_client_lock);
+ if (status < 0)
+ continue;
+ }
+ if (pos->cl_cons_state != NFS_CS_READY)
continue;
if (pos->rpc_ops != new->rpc_ops)
@@ -423,16 +436,16 @@
struct rpc_cred *cred)
{
struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
- struct nfs_client *pos, *n, *prev = NULL;
+ struct nfs_client *pos, *prev = NULL;
int status = -NFS4ERR_STALE_CLIENTID;
spin_lock(&nn->nfs_client_lock);
- list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
+ list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
/* If "pos" isn't marked ready, we can't trust the
* remaining fields in "pos", especially the client
* ID and serverowner fields. Wait for CREATE_SESSION
* to finish. */
- if (pos->cl_cons_state < NFS_CS_READY) {
+ if (pos->cl_cons_state > NFS_CS_READY) {
atomic_inc(&pos->cl_count);
spin_unlock(&nn->nfs_client_lock);
@@ -440,18 +453,17 @@
nfs_put_client(prev);
prev = pos;
- nfs4_schedule_lease_recovery(pos);
status = nfs_wait_client_init_complete(pos);
- if (status < 0) {
- nfs_put_client(pos);
- spin_lock(&nn->nfs_client_lock);
- continue;
+ if (status == 0) {
+ nfs4_schedule_lease_recovery(pos);
+ status = nfs4_wait_clnt_recover(pos);
}
- status = pos->cl_cons_state;
spin_lock(&nn->nfs_client_lock);
if (status < 0)
continue;
}
+ if (pos->cl_cons_state != NFS_CS_READY)
+ continue;
if (pos->rpc_ops != new->rpc_ops)
continue;
@@ -469,17 +481,18 @@
continue;
atomic_inc(&pos->cl_count);
- spin_unlock(&nn->nfs_client_lock);
+ *result = pos;
+ status = 0;
dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
__func__, pos, atomic_read(&pos->cl_count));
-
- *result = pos;
- return 0;
+ break;
}
/* No matching nfs_client found. */
spin_unlock(&nn->nfs_client_lock);
dprintk("NFS: <-- %s status = %d\n", __func__, status);
+ if (prev)
+ nfs_put_client(prev);
return status;
}
#endif /* CONFIG_NFS_V4_1 */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 26431cf..0ad025e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1046,6 +1046,7 @@
/* Save the delegation */
nfs4_stateid_copy(&stateid, &delegation->stateid);
rcu_read_unlock();
+ nfs_release_seqid(opendata->o_arg.seqid);
ret = nfs_may_open(state->inode, state->owner->so_cred, open_mode);
if (ret != 0)
goto out;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 6ace365..d41a351 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1886,7 +1886,13 @@
status = PTR_ERR(clnt);
break;
}
- clp->cl_rpcclient = clnt;
+ /* Note: this is safe because we haven't yet marked the
+ * client as ready, so we are the only user of
+ * clp->cl_rpcclient
+ */
+ clnt = xchg(&clp->cl_rpcclient, clnt);
+ rpc_shutdown_client(clnt);
+ clnt = clp->cl_rpcclient;
goto again;
case -NFS4ERR_MINOR_VERS_MISMATCH:
diff --git a/fs/proc/array.c b/fs/proc/array.c
index f7ed9ee..cbd0f1b 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -143,6 +143,7 @@
"x (dead)", /* 64 */
"K (wakekill)", /* 128 */
"W (waking)", /* 256 */
+ "P (parked)", /* 512 */
};
static inline const char *get_task_state(struct task_struct *tsk)
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 4b3b3ff..21e1a8f 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -755,37 +755,8 @@
free_proc_entry(pde);
}
-/*
- * Remove a /proc entry and free it if it's not currently in use.
- */
-void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+static void entry_rundown(struct proc_dir_entry *de)
{
- struct proc_dir_entry **p;
- struct proc_dir_entry *de = NULL;
- const char *fn = name;
- unsigned int len;
-
- spin_lock(&proc_subdir_lock);
- if (__xlate_proc_name(name, &parent, &fn) != 0) {
- spin_unlock(&proc_subdir_lock);
- return;
- }
- len = strlen(fn);
-
- for (p = &parent->subdir; *p; p=&(*p)->next ) {
- if (proc_match(len, fn, *p)) {
- de = *p;
- *p = de->next;
- de->next = NULL;
- break;
- }
- }
- spin_unlock(&proc_subdir_lock);
- if (!de) {
- WARN(1, "name '%s'\n", name);
- return;
- }
-
spin_lock(&de->pde_unload_lock);
/*
* Stop accepting new callers into module. If you're
@@ -817,6 +788,40 @@
spin_lock(&de->pde_unload_lock);
}
spin_unlock(&de->pde_unload_lock);
+}
+
+/*
+ * Remove a /proc entry and free it if it's not currently in use.
+ */
+void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
+{
+ struct proc_dir_entry **p;
+ struct proc_dir_entry *de = NULL;
+ const char *fn = name;
+ unsigned int len;
+
+ spin_lock(&proc_subdir_lock);
+ if (__xlate_proc_name(name, &parent, &fn) != 0) {
+ spin_unlock(&proc_subdir_lock);
+ return;
+ }
+ len = strlen(fn);
+
+ for (p = &parent->subdir; *p; p=&(*p)->next ) {
+ if (proc_match(len, fn, *p)) {
+ de = *p;
+ *p = de->next;
+ de->next = NULL;
+ break;
+ }
+ }
+ spin_unlock(&proc_subdir_lock);
+ if (!de) {
+ WARN(1, "name '%s'\n", name);
+ return;
+ }
+
+ entry_rundown(de);
if (S_ISDIR(de->mode))
parent->nlink--;
@@ -827,3 +832,57 @@
pde_put(de);
}
EXPORT_SYMBOL(remove_proc_entry);
+
+int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
+{
+ struct proc_dir_entry **p;
+ struct proc_dir_entry *root = NULL, *de, *next;
+ const char *fn = name;
+ unsigned int len;
+
+ spin_lock(&proc_subdir_lock);
+ if (__xlate_proc_name(name, &parent, &fn) != 0) {
+ spin_unlock(&proc_subdir_lock);
+ return -ENOENT;
+ }
+ len = strlen(fn);
+
+ for (p = &parent->subdir; *p; p=&(*p)->next ) {
+ if (proc_match(len, fn, *p)) {
+ root = *p;
+ *p = root->next;
+ root->next = NULL;
+ break;
+ }
+ }
+ if (!root) {
+ spin_unlock(&proc_subdir_lock);
+ return -ENOENT;
+ }
+ de = root;
+ while (1) {
+ next = de->subdir;
+ if (next) {
+ de->subdir = next->next;
+ next->next = NULL;
+ de = next;
+ continue;
+ }
+ spin_unlock(&proc_subdir_lock);
+
+ entry_rundown(de);
+ next = de->parent;
+ if (S_ISDIR(de->mode))
+ next->nlink--;
+ de->nlink = 0;
+ if (de == root)
+ break;
+ pde_put(de);
+
+ spin_lock(&proc_subdir_lock);
+ de = next;
+ }
+ pde_put(root);
+ return 0;
+}
+EXPORT_SYMBOL(remove_proc_subtree);
diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
index 25f01d0..b1b1fa6 100644
--- a/include/asm-generic/tlb.h
+++ b/include/asm-generic/tlb.h
@@ -99,7 +99,12 @@
unsigned int need_flush : 1, /* Did free PTEs */
fast_mode : 1; /* No batching */
- unsigned int fullmm;
+ /* we are in the middle of an operation to clear
+ * a full mm and can make some optimizations */
+ unsigned int fullmm : 1,
+ /* we have performed an operation which
+ * requires a complete flush of the tlb */
+ need_flush_all : 1;
struct mmu_gather_batch *active;
struct mmu_gather_batch local;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index bcbdd74..03053ac 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -152,15 +152,6 @@
void acpi_pci_irq_disable (struct pci_dev *dev);
-struct acpi_pci_driver {
- struct list_head node;
- int (*add)(struct acpi_pci_root *root);
- void (*remove)(struct acpi_pci_root *root);
-};
-
-int acpi_pci_register_driver(struct acpi_pci_driver *driver);
-void acpi_pci_unregister_driver(struct acpi_pci_driver *driver);
-
extern int ec_read(u8 addr, u8 *val);
extern int ec_write(u8 addr, u8 val);
extern int ec_transaction(u8 command,
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 8f7a3d6..ee0bd95 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -954,7 +954,7 @@
}
}
-static inline bool atapi_command_packet_set(const u16 *dev_id)
+static inline int atapi_command_packet_set(const u16 *dev_id)
{
return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f;
}
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 0ea61e0..7c2e030 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -12,7 +12,6 @@
struct blk_trace {
int trace_state;
- bool rq_based;
struct rchan *rchan;
unsigned long __percpu *sequence;
unsigned char __percpu *msg_data;
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 98503b7..d9a4f7f 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -35,6 +35,7 @@
#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
+struct file;
struct inode;
struct dentry;
struct user_namespace;
@@ -211,6 +212,7 @@
extern bool ns_capable(struct user_namespace *ns, int cap);
extern bool nsown_capable(int cap);
extern bool inode_capable(const struct inode *inode, int cap);
+extern bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap);
/* audit system wants to get cap info from files as well */
extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 9bf2f1f..3d7df3d 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -333,6 +333,7 @@
unsigned long count,
u64 *max_size,
int *reset_type);
+typedef efi_status_t efi_query_variable_store_t(u32 attributes, unsigned long size);
/*
* EFI Configuration Table and GUID definitions
@@ -575,9 +576,15 @@
#ifdef CONFIG_X86
extern void efi_late_init(void);
extern void efi_free_boot_services(void);
+extern efi_status_t efi_query_variable_store(u32 attributes, unsigned long size);
#else
static inline void efi_late_init(void) {}
static inline void efi_free_boot_services(void) {}
+
+static inline efi_status_t efi_query_variable_store(u32 attributes, unsigned long size)
+{
+ return EFI_SUCCESS;
+}
#endif
extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
extern u64 efi_get_iobase (void);
@@ -731,7 +738,7 @@
efi_get_variable_t *get_variable;
efi_get_next_variable_t *get_next_variable;
efi_set_variable_t *set_variable;
- efi_query_variable_info_t *query_variable_info;
+ efi_query_variable_store_t *query_variable_store;
};
struct efivars {
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e5ca8ef..52da2a2 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -89,6 +89,7 @@
* that the call back has its own recursion protection. If it does
* not set this, then the ftrace infrastructure will add recursion
* protection for the caller.
+ * STUB - The ftrace_ops is just a place holder.
*/
enum {
FTRACE_OPS_FL_ENABLED = 1 << 0,
@@ -98,6 +99,7 @@
FTRACE_OPS_FL_SAVE_REGS = 1 << 4,
FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED = 1 << 5,
FTRACE_OPS_FL_RECURSION_SAFE = 1 << 6,
+ FTRACE_OPS_FL_STUB = 1 << 7,
};
struct ftrace_ops {
@@ -394,7 +396,6 @@
size_t cnt, loff_t *ppos);
ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf,
size_t cnt, loff_t *ppos);
-loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int whence);
int ftrace_regex_release(struct inode *inode, struct file *file);
void __init
@@ -567,6 +568,8 @@
ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; }
#endif /* CONFIG_DYNAMIC_FTRACE */
+loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence);
+
/* totally disable ftrace - can not re-enable after this */
void ftrace_kill(void);
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index d2e6927..d78d28a 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -200,6 +200,8 @@
int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
+int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
+ unsigned long long *crash_size, unsigned long long *crash_base);
int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
unsigned long long *crash_size, unsigned long long *crash_base);
int crash_shrink_memory(unsigned long new_size);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 91c9d10..eae7a05 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -398,6 +398,7 @@
ATA_HORKAGE_NOSETXFER = (1 << 14), /* skip SETXFER, SATA only */
ATA_HORKAGE_BROKEN_FPDMA_AA = (1 << 15), /* skip AA */
ATA_HORKAGE_DUMP_ID = (1 << 16), /* dump IDENTIFY data */
+ ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e19ff30..e2091b8 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1611,6 +1611,8 @@
unsigned long pfn);
int vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr,
unsigned long pfn);
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len);
+
struct page *follow_page_mask(struct vm_area_struct *vma,
unsigned long address, unsigned int foll_flags,
diff --git a/include/linux/msi.h b/include/linux/msi.h
index ce93a34..20c2d6d 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -13,14 +13,14 @@
/* Helper functions */
struct irq_data;
struct msi_desc;
-extern void mask_msi_irq(struct irq_data *data);
-extern void unmask_msi_irq(struct irq_data *data);
-extern void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
-extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
-extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
+void mask_msi_irq(struct irq_data *data);
+void unmask_msi_irq(struct irq_data *data);
+void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void read_msi_msg(unsigned int irq, struct msi_msg *msg);
+void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
+void write_msi_msg(unsigned int irq, struct msi_msg *msg);
struct msi_desc {
struct {
@@ -54,9 +54,8 @@
*/
int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc);
void arch_teardown_msi_irq(unsigned int irq);
-extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
-extern void arch_teardown_msi_irqs(struct pci_dev *dev);
-extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
-
+int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
+void arch_teardown_msi_irqs(struct pci_dev *dev);
+int arch_msi_check_device(struct pci_dev* dev, int nvec, int type);
#endif /* LINUX_MSI_H */
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 9121595..433da8a 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -53,6 +53,9 @@
#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)
struct task_struct *owner;
#endif
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+ void *spin_mlock; /* Spinner MCS lock */
+#endif
#ifdef CONFIG_DEBUG_MUTEXES
const char *name;
void *magic;
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index 01d25e6..0214c4c 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -291,6 +291,7 @@
#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
#define type_pf_data_next TOKEN(TYPE, PF, _data_next)
#define type_pf_data_flags TOKEN(TYPE, PF, _data_flags)
+#define type_pf_data_reset_flags TOKEN(TYPE, PF, _data_reset_flags)
#ifdef IP_SET_HASH_WITH_NETS
#define type_pf_data_match TOKEN(TYPE, PF, _data_match)
#else
@@ -385,9 +386,9 @@
struct ip_set_hash *h = set->data;
struct htable *t, *orig = h->table;
u8 htable_bits = orig->htable_bits;
- const struct type_pf_elem *data;
+ struct type_pf_elem *data;
struct hbucket *n, *m;
- u32 i, j;
+ u32 i, j, flags = 0;
int ret;
retry:
@@ -412,9 +413,16 @@
n = hbucket(orig, i);
for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j);
+#ifdef IP_SET_HASH_WITH_NETS
+ flags = 0;
+ type_pf_data_reset_flags(data, &flags);
+#endif
m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_add(m, data, AHASH_MAX(h), 0);
+ ret = type_pf_elem_add(m, data, AHASH_MAX(h), flags);
if (ret < 0) {
+#ifdef IP_SET_HASH_WITH_NETS
+ type_pf_data_flags(data, flags);
+#endif
read_unlock_bh(&set->lock);
ahash_destroy(t);
if (ret == -EAGAIN)
@@ -836,9 +844,9 @@
struct ip_set_hash *h = set->data;
struct htable *t, *orig = h->table;
u8 htable_bits = orig->htable_bits;
- const struct type_pf_elem *data;
+ struct type_pf_elem *data;
struct hbucket *n, *m;
- u32 i, j;
+ u32 i, j, flags = 0;
int ret;
/* Try to cleanup once */
@@ -873,10 +881,17 @@
n = hbucket(orig, i);
for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j);
+#ifdef IP_SET_HASH_WITH_NETS
+ flags = 0;
+ type_pf_data_reset_flags(data, &flags);
+#endif
m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), 0,
- ip_set_timeout_get(type_pf_data_timeout(data)));
+ ret = type_pf_elem_tadd(m, data, AHASH_MAX(h), flags,
+ ip_set_timeout_get(type_pf_data_timeout(data)));
if (ret < 0) {
+#ifdef IP_SET_HASH_WITH_NETS
+ type_pf_data_flags(data, flags);
+#endif
read_unlock_bh(&set->lock);
ahash_destroy(t);
if (ret == -EAGAIN)
@@ -1187,6 +1202,7 @@
#undef type_pf_data_tlist
#undef type_pf_data_next
#undef type_pf_data_flags
+#undef type_pf_data_reset_flags
#undef type_pf_data_match
#undef type_pf_elem
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 9a22b5e..81b3161 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -41,8 +41,37 @@
return DEVICE_ACPI_HANDLE(dev);
}
+
+void acpi_pci_add_bus(struct pci_bus *bus);
+void acpi_pci_remove_bus(struct pci_bus *bus);
+
+#ifdef CONFIG_ACPI_PCI_SLOT
+void acpi_pci_slot_init(void);
+void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle);
+void acpi_pci_slot_remove(struct pci_bus *bus);
+#else
+static inline void acpi_pci_slot_init(void) { }
+static inline void acpi_pci_slot_enumerate(struct pci_bus *bus,
+ acpi_handle handle) { }
+static inline void acpi_pci_slot_remove(struct pci_bus *bus) { }
#endif
+#ifdef CONFIG_HOTPLUG_PCI_ACPI
+void acpiphp_init(void);
+void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle);
+void acpiphp_remove_slots(struct pci_bus *bus);
+#else
+static inline void acpiphp_init(void) { }
+static inline void acpiphp_enumerate_slots(struct pci_bus *bus,
+ acpi_handle handle) { }
+static inline void acpiphp_remove_slots(struct pci_bus *bus) { }
+#endif
+
+#else /* CONFIG_ACPI */
+static inline void acpi_pci_add_bus(struct pci_bus *bus) { }
+static inline void acpi_pci_remove_bus(struct pci_bus *bus) { }
+#endif /* CONFIG_ACPI */
+
#ifdef CONFIG_ACPI_APEI
extern bool aer_acpi_firmware_first(void);
#else
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
index c832014..8af4610 100644
--- a/include/linux/pci-aspm.h
+++ b/include/linux/pci-aspm.h
@@ -23,14 +23,14 @@
#define PCIE_LINK_STATE_CLKPM 4
#ifdef CONFIG_PCIEASPM
-extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
-extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
-extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
-extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
-extern void pci_disable_link_state(struct pci_dev *pdev, int state);
-extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-extern void pcie_clear_aspm(struct pci_bus *bus);
-extern void pcie_no_aspm(void);
+void pcie_aspm_init_link_state(struct pci_dev *pdev);
+void pcie_aspm_exit_link_state(struct pci_dev *pdev);
+void pcie_aspm_pm_state_change(struct pci_dev *pdev);
+void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
+void pci_disable_link_state(struct pci_dev *pdev, int state);
+void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
+void pcie_clear_aspm(struct pci_bus *bus);
+void pcie_no_aspm(void);
#else
static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
{
@@ -56,8 +56,8 @@
#endif
#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
-extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
-extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
#else
static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
{
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
index 7ef6872..68bcefd 100644
--- a/include/linux/pci-ats.h
+++ b/include/linux/pci-ats.h
@@ -14,9 +14,9 @@
#ifdef CONFIG_PCI_ATS
-extern int pci_enable_ats(struct pci_dev *dev, int ps);
-extern void pci_disable_ats(struct pci_dev *dev);
-extern int pci_ats_queue_depth(struct pci_dev *dev);
+int pci_enable_ats(struct pci_dev *dev, int ps);
+void pci_disable_ats(struct pci_dev *dev);
+int pci_ats_queue_depth(struct pci_dev *dev);
/**
* pci_ats_enabled - query the ATS status
@@ -54,12 +54,12 @@
#ifdef CONFIG_PCI_PRI
-extern int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
-extern void pci_disable_pri(struct pci_dev *pdev);
-extern bool pci_pri_enabled(struct pci_dev *pdev);
-extern int pci_reset_pri(struct pci_dev *pdev);
-extern bool pci_pri_stopped(struct pci_dev *pdev);
-extern int pci_pri_status(struct pci_dev *pdev);
+int pci_enable_pri(struct pci_dev *pdev, u32 reqs);
+void pci_disable_pri(struct pci_dev *pdev);
+bool pci_pri_enabled(struct pci_dev *pdev);
+int pci_reset_pri(struct pci_dev *pdev);
+bool pci_pri_stopped(struct pci_dev *pdev);
+int pci_pri_status(struct pci_dev *pdev);
#else /* CONFIG_PCI_PRI */
@@ -95,10 +95,10 @@
#ifdef CONFIG_PCI_PASID
-extern int pci_enable_pasid(struct pci_dev *pdev, int features);
-extern void pci_disable_pasid(struct pci_dev *pdev);
-extern int pci_pasid_features(struct pci_dev *pdev);
-extern int pci_max_pasids(struct pci_dev *pdev);
+int pci_enable_pasid(struct pci_dev *pdev, int features);
+void pci_disable_pasid(struct pci_dev *pdev);
+int pci_pasid_features(struct pci_dev *pdev);
+int pci_max_pasids(struct pci_dev *pdev);
#else /* CONFIG_PCI_PASID */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 710067f..e73dfa3 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -35,6 +35,21 @@
/* Include the ID list */
#include <linux/pci_ids.h>
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices. The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ * 7:3 = slot
+ * 2:0 = function
+ * PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() are defined uapi/linux/pci.h
+ * In the interest of not exposing interfaces to user-space unnecessarily,
+ * the following kernel only defines are being added here.
+ */
+#define PCI_DEVID(bus, devfn) ((((u16)bus) << 8) | devfn)
+/* return bus from PCI devid = ((u16)bus_number) << 8) | devfn */
+#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff)
+
/* pci_slot represents a physical slot */
struct pci_slot {
struct pci_bus *bus; /* The bus this slot is on */
@@ -232,6 +247,8 @@
u8 revision; /* PCI revision, low byte of class word */
u8 hdr_type; /* PCI header type (`multi' flag masked out) */
u8 pcie_cap; /* PCI-E capability offset */
+ u8 msi_cap; /* MSI capability offset */
+ u8 msix_cap; /* MSI-X capability offset */
u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */
u8 rom_base_reg; /* which config register controls the ROM */
u8 pin; /* which interrupt pin this device uses */
@@ -249,8 +266,7 @@
pci_power_t current_state; /* Current operating state. In ACPI-speak,
this is D0-D3, D0 being fully functional,
and D3 being off. */
- int pm_cap; /* PM capability offset in the
- configuration space */
+ u8 pm_cap; /* PM capability offset */
unsigned int pme_support:5; /* Bitmask of states from which PME#
can be generated */
unsigned int pme_interrupt:1;
@@ -348,7 +364,7 @@
return dev;
}
-extern struct pci_dev *alloc_pci_dev(void);
+struct pci_dev *alloc_pci_dev(void);
#define to_pci_dev(n) container_of(n, struct pci_dev, dev)
#define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL)
@@ -504,10 +520,10 @@
* ACPI needs to be able to access PCI config space before we've done a
* PCI bus scan and created pci_bus structures.
*/
-extern int raw_pci_read(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *val);
-extern int raw_pci_write(unsigned int domain, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 val);
+int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 *val);
+int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
+ int reg, int len, u32 val);
struct pci_bus_region {
resource_size_t start;
@@ -658,7 +674,7 @@
/* these external functions are only available when PCI support is enabled */
#ifdef CONFIG_PCI
-extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
+void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss);
enum pcie_bus_config_types {
PCIE_BUS_TUNE_OFF,
@@ -675,9 +691,11 @@
* code, or pci core code. */
extern struct list_head pci_root_buses; /* list of all known PCI buses */
/* Some device drivers need know if pci is initiated */
-extern int no_pci_devices(void);
+int no_pci_devices(void);
void pcibios_resource_survey_bus(struct pci_bus *bus);
+void pcibios_add_bus(struct pci_bus *bus);
+void pcibios_remove_bus(struct pci_bus *bus);
void pcibios_fixup_bus(struct pci_bus *);
int __must_check pcibios_enable_device(struct pci_dev *, int mask);
/* Architecture specific versions may override this (weak) */
@@ -699,7 +717,7 @@
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region);
void pcibios_scan_specific_bus(int busn);
-extern struct pci_bus *pci_find_bus(int domain, int busnr);
+struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus);
struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata);
@@ -732,14 +750,14 @@
u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin);
int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp);
-extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
-extern void pci_dev_put(struct pci_dev *dev);
-extern void pci_remove_bus(struct pci_bus *b);
-extern void pci_stop_and_remove_bus_device(struct pci_dev *dev);
+struct pci_dev *pci_dev_get(struct pci_dev *dev);
+void pci_dev_put(struct pci_dev *dev);
+void pci_remove_bus(struct pci_bus *b);
+void pci_stop_and_remove_bus_device(struct pci_dev *dev);
void pci_stop_root_bus(struct pci_bus *bus);
void pci_remove_root_bus(struct pci_bus *bus);
void pci_setup_cardbus(struct pci_bus *bus);
-extern void pci_sort_breadthfirst(void);
+void pci_sort_breadthfirst(void);
#define dev_is_pci(d) ((d)->bus == &pci_bus_type)
#define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
#define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
@@ -1142,18 +1160,17 @@
return 0;
}
#else
-extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
-extern int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
-extern void pci_msi_shutdown(struct pci_dev *dev);
-extern void pci_disable_msi(struct pci_dev *dev);
-extern int pci_msix_table_size(struct pci_dev *dev);
-extern int pci_enable_msix(struct pci_dev *dev,
- struct msix_entry *entries, int nvec);
-extern void pci_msix_shutdown(struct pci_dev *dev);
-extern void pci_disable_msix(struct pci_dev *dev);
-extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
-extern void pci_restore_msi_state(struct pci_dev *dev);
-extern int pci_msi_enabled(void);
+int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec);
+int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec);
+void pci_msi_shutdown(struct pci_dev *dev);
+void pci_disable_msi(struct pci_dev *dev);
+int pci_msix_table_size(struct pci_dev *dev);
+int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec);
+void pci_msix_shutdown(struct pci_dev *dev);
+void pci_disable_msix(struct pci_dev *dev);
+void msi_remove_pci_irq_vectors(struct pci_dev *dev);
+void pci_restore_msi_state(struct pci_dev *dev);
+int pci_msi_enabled(void);
#endif
#ifdef CONFIG_PCIEPORTBUS
@@ -1168,8 +1185,8 @@
static inline int pcie_aspm_enabled(void) { return 0; }
static inline bool pcie_aspm_support_enabled(void) { return false; }
#else
-extern int pcie_aspm_enabled(void);
-extern bool pcie_aspm_support_enabled(void);
+int pcie_aspm_enabled(void);
+bool pcie_aspm_support_enabled(void);
#endif
#ifdef CONFIG_PCIEAER
@@ -1187,8 +1204,8 @@
}
static inline void pcie_ecrc_get_policy(char *str) {};
#else
-extern void pcie_set_ecrc_checking(struct pci_dev *dev);
-extern void pcie_ecrc_get_policy(char *str);
+void pcie_set_ecrc_checking(struct pci_dev *dev);
+void pcie_ecrc_get_policy(char *str);
#endif
#define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1)
@@ -1199,9 +1216,9 @@
void ht_destroy_irq(unsigned int irq);
#endif /* CONFIG_HT_IRQ */
-extern void pci_cfg_access_lock(struct pci_dev *dev);
-extern bool pci_cfg_access_trylock(struct pci_dev *dev);
-extern void pci_cfg_access_unlock(struct pci_dev *dev);
+void pci_cfg_access_lock(struct pci_dev *dev);
+bool pci_cfg_access_trylock(struct pci_dev *dev);
+void pci_cfg_access_unlock(struct pci_dev *dev);
/*
* PCI domain support. Sometimes called PCI segment (eg by ACPI),
@@ -1226,7 +1243,7 @@
/* some architectures require additional setup to direct VGA traffic */
typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode,
unsigned int command_bits, u32 flags);
-extern void pci_register_set_vga_state(arch_set_vga_state_t func);
+void pci_register_set_vga_state(arch_set_vga_state_t func);
#else /* CONFIG_PCI is not enabled */
@@ -1628,8 +1645,8 @@
int pcibios_add_device(struct pci_dev *dev);
#ifdef CONFIG_PCI_MMCONFIG
-extern void __init pci_mmcfg_early_init(void);
-extern void __init pci_mmcfg_late_init(void);
+void __init pci_mmcfg_early_init(void);
+void __init pci_mmcfg_late_init(void);
#else
static inline void pci_mmcfg_early_init(void) { }
static inline void pci_mmcfg_late_init(void) { }
@@ -1640,12 +1657,12 @@
void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar);
#ifdef CONFIG_PCI_IOV
-extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
-extern void pci_disable_sriov(struct pci_dev *dev);
-extern irqreturn_t pci_sriov_migration(struct pci_dev *dev);
-extern int pci_num_vf(struct pci_dev *dev);
-extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
-extern int pci_sriov_get_totalvfs(struct pci_dev *dev);
+int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
+void pci_disable_sriov(struct pci_dev *dev);
+irqreturn_t pci_sriov_migration(struct pci_dev *dev);
+int pci_num_vf(struct pci_dev *dev);
+int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs);
+int pci_sriov_get_totalvfs(struct pci_dev *dev);
#else
static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn)
{
@@ -1673,8 +1690,8 @@
#endif
#if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE)
-extern void pci_hp_create_module_link(struct pci_slot *pci_slot);
-extern void pci_hp_remove_module_link(struct pci_slot *pci_slot);
+void pci_hp_create_module_link(struct pci_slot *pci_slot);
+void pci_hp_remove_module_link(struct pci_slot *pci_slot);
#endif
/**
@@ -1818,13 +1835,13 @@
/* PCI <-> OF binding helpers */
#ifdef CONFIG_OF
struct device_node;
-extern void pci_set_of_node(struct pci_dev *dev);
-extern void pci_release_of_node(struct pci_dev *dev);
-extern void pci_set_bus_of_node(struct pci_bus *bus);
-extern void pci_release_bus_of_node(struct pci_bus *bus);
+void pci_set_of_node(struct pci_dev *dev);
+void pci_release_of_node(struct pci_dev *dev);
+void pci_set_bus_of_node(struct pci_bus *bus);
+void pci_release_bus_of_node(struct pci_bus *bus);
/* Arch may override this (weak) */
-extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus);
+struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus);
static inline struct device_node *
pci_device_to_OF_node(const struct pci_dev *pdev)
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index 45fc162..8db71dc 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -125,12 +125,12 @@
return pci_slot_name(slot->pci_slot);
}
-extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus,
- int nr, const char *name,
- struct module *owner, const char *mod_name);
-extern int pci_hp_deregister(struct hotplug_slot *slot);
-extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot,
- struct hotplug_slot_info *info);
+int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, int nr,
+ const char *name, struct module *owner,
+ const char *mod_name);
+int pci_hp_deregister(struct hotplug_slot *slot);
+int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
+ struct hotplug_slot_info *info);
/* use a define to avoid include chaining to get THIS_MODULE & friends */
#define pci_hp_register(slot, pbus, devnr, name) \
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index f11c1c2..a80f9e6 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1604,6 +1604,7 @@
#define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334
#define PCI_VENDOR_ID_MARVELL 0x11ab
+#define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b
#define PCI_DEVICE_ID_MARVELL_GT64111 0x4146
#define PCI_DEVICE_ID_MARVELL_GT64260 0x6430
#define PCI_DEVICE_ID_MARVELL_MV64360 0x6460
diff --git a/include/linux/pcieport_if.h b/include/linux/pcieport_if.h
index e6f91b1..9572669 100644
--- a/include/linux/pcieport_if.h
+++ b/include/linux/pcieport_if.h
@@ -62,7 +62,7 @@
#define to_service_driver(d) \
container_of(d, struct pcie_port_service_driver, driver)
-extern int pcie_port_service_register(struct pcie_port_service_driver *new);
-extern void pcie_port_service_unregister(struct pcie_port_service_driver *new);
+int pcie_port_service_register(struct pcie_port_service_driver *new);
+void pcie_port_service_unregister(struct pcie_port_service_driver *new);
#endif /* _PCIEPORT_IF_H_ */
diff --git a/include/linux/pinctrl/pinconf.h b/include/linux/pinctrl/pinconf.h
index e7a7201..1ad4f31 100644
--- a/include/linux/pinctrl/pinconf.h
+++ b/include/linux/pinctrl/pinconf.h
@@ -14,6 +14,8 @@
#ifdef CONFIG_PINCONF
+#include <linux/pinctrl/machine.h>
+
struct pinctrl_dev;
struct seq_file;
@@ -28,6 +30,7 @@
* @pin_config_set: configure an individual pin
* @pin_config_group_get: get configurations for an entire pin group
* @pin_config_group_set: configure all pins in a group
+ * @pin_config_group_dbg_set: optional debugfs to modify a pin configuration
* @pin_config_dbg_show: optional debugfs display hook that will provide
* per-device info for a certain pin in debugfs
* @pin_config_group_dbg_show: optional debugfs display hook that will provide
@@ -51,6 +54,9 @@
int (*pin_config_group_set) (struct pinctrl_dev *pctldev,
unsigned selector,
unsigned long config);
+ int (*pin_config_dbg_parse_modify) (struct pinctrl_dev *pctldev,
+ const char *arg,
+ unsigned long *config);
void (*pin_config_dbg_show) (struct pinctrl_dev *pctldev,
struct seq_file *s,
unsigned offset);
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 778804d..2c2a9e8 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -118,9 +118,9 @@
const char *name;
struct pinctrl_pin_desc const *pins;
unsigned int npins;
- struct pinctrl_ops *pctlops;
- struct pinmux_ops *pmxops;
- struct pinconf_ops *confops;
+ const struct pinctrl_ops *pctlops;
+ const struct pinmux_ops *pmxops;
+ const struct pinconf_ops *confops;
struct module *owner;
};
diff --git a/include/linux/platform_data/video-vt8500lcdfb.h b/include/linux/platform_data/video-vt8500lcdfb.h
deleted file mode 100644
index 7f399c3..0000000
--- a/include/linux/platform_data/video-vt8500lcdfb.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * VT8500/WM8505 Frame Buffer platform data definitions
- *
- * Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- */
-
-#ifndef _VT8500FB_H
-#define _VT8500FB_H
-
-#include <linux/fb.h>
-
-struct vt8500fb_platform_data {
- struct fb_videomode mode;
- u32 xres_virtual;
- u32 yres_virtual;
- u32 bpp;
- unsigned long video_mem_phys;
- void *video_mem_virt;
- unsigned long video_mem_len;
-};
-
-#endif /* _VT8500FB_H */
diff --git a/include/linux/platform_data/video_s3c.h b/include/linux/platform_data/video_s3c.h
new file mode 100644
index 0000000..4888399
--- /dev/null
+++ b/include/linux/platform_data/video_s3c.h
@@ -0,0 +1,54 @@
+#ifndef __PLATFORM_DATA_VIDEO_S3C
+#define __PLATFORM_DATA_VIDEO_S3C
+
+/* S3C_FB_MAX_WIN
+ * Set to the maximum number of windows that any of the supported hardware
+ * can use. Since the platform data uses this for an array size, having it
+ * set to the maximum of any version of the hardware can do is safe.
+ */
+#define S3C_FB_MAX_WIN (5)
+
+/**
+ * struct s3c_fb_pd_win - per window setup data
+ * @xres : The window X size.
+ * @yres : The window Y size.
+ * @virtual_x: The virtual X size.
+ * @virtual_y: The virtual Y size.
+ */
+struct s3c_fb_pd_win {
+ unsigned short default_bpp;
+ unsigned short max_bpp;
+ unsigned short xres;
+ unsigned short yres;
+ unsigned short virtual_x;
+ unsigned short virtual_y;
+};
+
+/**
+ * struct s3c_fb_platdata - S3C driver platform specific information
+ * @setup_gpio: Setup the external GPIO pins to the right state to transfer
+ * the data from the display system to the connected display
+ * device.
+ * @vidcon0: The base vidcon0 values to control the panel data format.
+ * @vidcon1: The base vidcon1 values to control the panel data output.
+ * @vtiming: Video timing when connected to a RGB type panel.
+ * @win: The setup data for each hardware window, or NULL for unused.
+ * @display_mode: The LCD output display mode.
+ *
+ * The platform data supplies the video driver with all the information
+ * it requires to work with the display(s) attached to the machine. It
+ * controls the initial mode, the number of display windows (0 is always
+ * the base framebuffer) that are initialised etc.
+ *
+ */
+struct s3c_fb_platdata {
+ void (*setup_gpio)(void);
+
+ struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN];
+ struct fb_videomode *vtiming;
+
+ u32 vidcon0;
+ u32 vidcon1;
+};
+
+#endif
diff --git a/include/linux/preempt.h b/include/linux/preempt.h
index 5a710b9..87a03c7 100644
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -93,14 +93,20 @@
#else /* !CONFIG_PREEMPT_COUNT */
-#define preempt_disable() do { } while (0)
-#define sched_preempt_enable_no_resched() do { } while (0)
-#define preempt_enable_no_resched() do { } while (0)
-#define preempt_enable() do { } while (0)
+/*
+ * Even if we don't have any preemption, we need preempt disable/enable
+ * to be barriers, so that we don't have things like get_user/put_user
+ * that can cause faults and scheduling migrate into our preempt-protected
+ * region.
+ */
+#define preempt_disable() barrier()
+#define sched_preempt_enable_no_resched() barrier()
+#define preempt_enable_no_resched() barrier()
+#define preempt_enable() barrier()
-#define preempt_disable_notrace() do { } while (0)
-#define preempt_enable_no_resched_notrace() do { } while (0)
-#define preempt_enable_notrace() do { } while (0)
+#define preempt_disable_notrace() barrier()
+#define preempt_enable_no_resched_notrace() barrier()
+#define preempt_enable_notrace() barrier()
#endif /* CONFIG_PREEMPT_COUNT */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 8307f2f..94dfb2a 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -117,6 +117,7 @@
const struct file_operations *proc_fops,
void *data);
extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
+extern int remove_proc_subtree(const char *name, struct proc_dir_entry *parent);
struct pid_namespace;
@@ -202,6 +203,7 @@
return NULL;
}
#define remove_proc_entry(name, parent) do {} while (0)
+#define remove_proc_subtree(name, parent) do {} while (0)
static inline struct proc_dir_entry *proc_symlink(const char *name,
struct proc_dir_entry *parent,const char *dest) {return NULL;}
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d35d2b6..2d02c76 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -163,9 +163,10 @@
#define TASK_DEAD 64
#define TASK_WAKEKILL 128
#define TASK_WAKING 256
-#define TASK_STATE_MAX 512
+#define TASK_PARKED 512
+#define TASK_STATE_MAX 1024
-#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW"
+#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
extern char ___assert_task_state[1 - 2*!!(
sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)];
@@ -320,7 +321,6 @@
extern signed long schedule_timeout_uninterruptible(signed long timeout);
asmlinkage void schedule(void);
extern void schedule_preempt_disabled(void);
-extern int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner);
struct nsproxy;
struct user_namespace;
diff --git a/include/linux/security.h b/include/linux/security.h
index eee7478..032c366 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1012,6 +1012,10 @@
* This hook can be used by the module to update any security state
* associated with the TUN device's security structure.
* @security pointer to the TUN devices's security structure.
+ * @skb_owned_by:
+ * This hook sets the packet's owning sock.
+ * @skb is the packet.
+ * @sk the sock which owns the packet.
*
* Security hooks for XFRM operations.
*
@@ -1638,6 +1642,7 @@
int (*tun_dev_attach_queue) (void *security);
int (*tun_dev_attach) (struct sock *sk, void *security);
int (*tun_dev_open) (void *security);
+ void (*skb_owned_by) (struct sk_buff *skb, struct sock *sk);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2588,6 +2593,8 @@
int security_tun_dev_attach(struct sock *sk, void *security);
int security_tun_dev_open(void *security);
+void security_skb_owned_by(struct sk_buff *skb, struct sock *sk);
+
#else /* CONFIG_SECURITY_NETWORK */
static inline int security_unix_stream_connect(struct sock *sock,
struct sock *other,
@@ -2779,6 +2786,11 @@
{
return 0;
}
+
+static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+}
+
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h
index a26e2fb..e2369c16 100644
--- a/include/linux/spinlock_up.h
+++ b/include/linux/spinlock_up.h
@@ -16,7 +16,10 @@
* In the debug case, 1 means unlocked, 0 means locked. (the values
* are inverted, to catch initialization bugs)
*
- * No atomicity anywhere, we are on UP.
+ * No atomicity anywhere, we are on UP. However, we still need
+ * the compiler barriers, because we do not want the compiler to
+ * move potentially faulting instructions (notably user accesses)
+ * into the locked sequence, resulting in non-atomic execution.
*/
#ifdef CONFIG_DEBUG_SPINLOCK
@@ -25,6 +28,7 @@
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
lock->slock = 0;
+ barrier();
}
static inline void
@@ -32,6 +36,7 @@
{
local_irq_save(flags);
lock->slock = 0;
+ barrier();
}
static inline int arch_spin_trylock(arch_spinlock_t *lock)
@@ -39,32 +44,34 @@
char oldval = lock->slock;
lock->slock = 0;
+ barrier();
return oldval > 0;
}
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
+ barrier();
lock->slock = 1;
}
/*
* Read-write spinlocks. No debug version.
*/
-#define arch_read_lock(lock) do { (void)(lock); } while (0)
-#define arch_write_lock(lock) do { (void)(lock); } while (0)
-#define arch_read_trylock(lock) ({ (void)(lock); 1; })
-#define arch_write_trylock(lock) ({ (void)(lock); 1; })
-#define arch_read_unlock(lock) do { (void)(lock); } while (0)
-#define arch_write_unlock(lock) do { (void)(lock); } while (0)
+#define arch_read_lock(lock) do { barrier(); (void)(lock); } while (0)
+#define arch_write_lock(lock) do { barrier(); (void)(lock); } while (0)
+#define arch_read_trylock(lock) ({ barrier(); (void)(lock); 1; })
+#define arch_write_trylock(lock) ({ barrier(); (void)(lock); 1; })
+#define arch_read_unlock(lock) do { barrier(); (void)(lock); } while (0)
+#define arch_write_unlock(lock) do { barrier(); (void)(lock); } while (0)
#else /* DEBUG_SPINLOCK */
#define arch_spin_is_locked(lock) ((void)(lock), 0)
/* for sched.c and kernel_lock.c: */
-# define arch_spin_lock(lock) do { (void)(lock); } while (0)
-# define arch_spin_lock_flags(lock, flags) do { (void)(lock); } while (0)
-# define arch_spin_unlock(lock) do { (void)(lock); } while (0)
-# define arch_spin_trylock(lock) ({ (void)(lock); 1; })
+# define arch_spin_lock(lock) do { barrier(); (void)(lock); } while (0)
+# define arch_spin_lock_flags(lock, flags) do { barrier(); (void)(lock); } while (0)
+# define arch_spin_unlock(lock) do { barrier(); (void)(lock); } while (0)
+# define arch_spin_trylock(lock) ({ barrier(); (void)(lock); 1; })
#endif /* DEBUG_SPINLOCK */
#define arch_spin_is_contended(lock) (((void)(lock), 0))
diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h
index 9e492be..6fcfe99 100644
--- a/include/linux/ssb/ssb_driver_chipcommon.h
+++ b/include/linux/ssb/ssb_driver_chipcommon.h
@@ -219,6 +219,7 @@
#define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */
#define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */
#define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16
+#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400
#define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */
#define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */
#define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */
@@ -667,5 +668,6 @@
void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc,
enum ssb_pmu_ldo_volt_id id, u32 voltage);
void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on);
+void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid);
#endif /* LINUX_SSB_CHIPCO_H_ */
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 2de42f94..a5ffd32 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -25,6 +25,7 @@
extern void swiotlb_init(int verbose);
int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose);
extern unsigned long swiotlb_nr_tbl(void);
+unsigned long swiotlb_size_or_default(void);
extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs);
/*
diff --git a/include/linux/ucs2_string.h b/include/linux/ucs2_string.h
new file mode 100644
index 0000000..cbb20af
--- /dev/null
+++ b/include/linux/ucs2_string.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_UCS2_STRING_H_
+#define _LINUX_UCS2_STRING_H_
+
+#include <linux/types.h> /* for size_t */
+#include <linux/stddef.h> /* for NULL */
+
+typedef u16 ucs2_char_t;
+
+unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
+unsigned long ucs2_strlen(const ucs2_char_t *s);
+unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
+int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
+
+#endif /* _LINUX_UCS2_STRING_H_ */
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 40be2a0..84a6440 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -199,6 +199,7 @@
/* Device notifier */
extern int register_inet6addr_notifier(struct notifier_block *nb);
extern int unregister_inet6addr_notifier(struct notifier_block *nb);
+extern int inet6addr_notifier_call_chain(unsigned long val, void *v);
extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
struct ipv6_devconf *devconf);
diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h
index f741091..f132924 100644
--- a/include/net/irda/irlmp.h
+++ b/include/net/irda/irlmp.h
@@ -256,7 +256,8 @@
return (self && self->lap) ? self->lap->daddr : 0;
}
-extern const char *irlmp_reasons[];
+const char *irlmp_reason_str(LM_REASON reason);
+
extern int sysctl_discovery_timeout;
extern int sysctl_discovery_slots;
extern int sysctl_discovery;
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index cc7c197..714cc9a 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -130,6 +130,14 @@
enum iucv_tx_notify n);
};
+struct iucv_skb_cb {
+ u32 class; /* target class of message */
+ u32 tag; /* tag associated with message */
+ u32 offset; /* offset for skb receival */
+};
+
+#define IUCV_SKB_CB(__skb) ((struct iucv_skb_cb *)&((__skb)->cb[0]))
+
/* iucv socket options (SOL_IUCV) */
#define SO_IPRMDATA_MSG 0x0080 /* send/recv IPRM_DATA msgs */
#define SO_MSGLIMIT 0x1000 /* get/set IUCV MSGLIMIT */
diff --git a/include/net/scm.h b/include/net/scm.h
index 975cca0..b117081 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -56,8 +56,8 @@
scm->pid = get_pid(pid);
scm->cred = cred ? get_cred(cred) : NULL;
scm->creds.pid = pid_vnr(pid);
- scm->creds.uid = cred ? cred->euid : INVALID_UID;
- scm->creds.gid = cred ? cred->egid : INVALID_GID;
+ scm->creds.uid = cred ? cred->uid : INVALID_UID;
+ scm->creds.gid = cred ? cred->gid : INVALID_GID;
}
static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
diff --git a/include/trace/events/block.h b/include/trace/events/block.h
index 9961726..9c14673 100644
--- a/include/trace/events/block.h
+++ b/include/trace/events/block.h
@@ -257,6 +257,7 @@
/**
* block_bio_complete - completed all work on the block operation
+ * @q: queue holding the block operation
* @bio: block operation completed
* @error: io error value
*
@@ -265,9 +266,9 @@
*/
TRACE_EVENT(block_bio_complete,
- TP_PROTO(struct bio *bio, int error),
+ TP_PROTO(struct request_queue *q, struct bio *bio, int error),
- TP_ARGS(bio, error),
+ TP_ARGS(q, bio, error),
TP_STRUCT__entry(
__field( dev_t, dev )
@@ -278,8 +279,7 @@
),
TP_fast_assign(
- __entry->dev = bio->bi_bdev ?
- bio->bi_bdev->bd_dev : 0;
+ __entry->dev = bio->bi_bdev->bd_dev;
__entry->sector = bio->bi_sector;
__entry->nr_sector = bio->bi_size >> 9;
__entry->error = error;
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 5a8671e..e5586ca 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -147,7 +147,7 @@
__print_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|",
{ 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" },
{ 16, "Z" }, { 32, "X" }, { 64, "x" },
- { 128, "W" }) : "R",
+ { 128, "K" }, { 256, "W" }, { 512, "P" }) : "R",
__entry->prev_state & TASK_STATE_MAX ? "+" : "",
__entry->next_comm, __entry->next_pid, __entry->next_prio)
);
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index 4c43b44..706d035 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -95,15 +95,10 @@
#ifndef _LINUX_FUSE_H
#define _LINUX_FUSE_H
-#ifdef __linux__
+#ifdef __KERNEL__
#include <linux/types.h>
#else
#include <stdint.h>
-#define __u64 uint64_t
-#define __s64 int64_t
-#define __u32 uint32_t
-#define __s32 int32_t
-#define __u16 uint16_t
#endif
/*
@@ -139,42 +134,42 @@
userspace works under 64bit kernels */
struct fuse_attr {
- __u64 ino;
- __u64 size;
- __u64 blocks;
- __u64 atime;
- __u64 mtime;
- __u64 ctime;
- __u32 atimensec;
- __u32 mtimensec;
- __u32 ctimensec;
- __u32 mode;
- __u32 nlink;
- __u32 uid;
- __u32 gid;
- __u32 rdev;
- __u32 blksize;
- __u32 padding;
+ uint64_t ino;
+ uint64_t size;
+ uint64_t blocks;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t ctime;
+ uint32_t atimensec;
+ uint32_t mtimensec;
+ uint32_t ctimensec;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t rdev;
+ uint32_t blksize;
+ uint32_t padding;
};
struct fuse_kstatfs {
- __u64 blocks;
- __u64 bfree;
- __u64 bavail;
- __u64 files;
- __u64 ffree;
- __u32 bsize;
- __u32 namelen;
- __u32 frsize;
- __u32 padding;
- __u32 spare[6];
+ uint64_t blocks;
+ uint64_t bfree;
+ uint64_t bavail;
+ uint64_t files;
+ uint64_t ffree;
+ uint32_t bsize;
+ uint32_t namelen;
+ uint32_t frsize;
+ uint32_t padding;
+ uint32_t spare[6];
};
struct fuse_file_lock {
- __u64 start;
- __u64 end;
- __u32 type;
- __u32 pid; /* tgid */
+ uint64_t start;
+ uint64_t end;
+ uint32_t type;
+ uint32_t pid; /* tgid */
};
/**
@@ -364,143 +359,143 @@
#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
struct fuse_entry_out {
- __u64 nodeid; /* Inode ID */
- __u64 generation; /* Inode generation: nodeid:gen must
- be unique for the fs's lifetime */
- __u64 entry_valid; /* Cache timeout for the name */
- __u64 attr_valid; /* Cache timeout for the attributes */
- __u32 entry_valid_nsec;
- __u32 attr_valid_nsec;
+ uint64_t nodeid; /* Inode ID */
+ uint64_t generation; /* Inode generation: nodeid:gen must
+ be unique for the fs's lifetime */
+ uint64_t entry_valid; /* Cache timeout for the name */
+ uint64_t attr_valid; /* Cache timeout for the attributes */
+ uint32_t entry_valid_nsec;
+ uint32_t attr_valid_nsec;
struct fuse_attr attr;
};
struct fuse_forget_in {
- __u64 nlookup;
+ uint64_t nlookup;
};
struct fuse_forget_one {
- __u64 nodeid;
- __u64 nlookup;
+ uint64_t nodeid;
+ uint64_t nlookup;
};
struct fuse_batch_forget_in {
- __u32 count;
- __u32 dummy;
+ uint32_t count;
+ uint32_t dummy;
};
struct fuse_getattr_in {
- __u32 getattr_flags;
- __u32 dummy;
- __u64 fh;
+ uint32_t getattr_flags;
+ uint32_t dummy;
+ uint64_t fh;
};
#define FUSE_COMPAT_ATTR_OUT_SIZE 96
struct fuse_attr_out {
- __u64 attr_valid; /* Cache timeout for the attributes */
- __u32 attr_valid_nsec;
- __u32 dummy;
+ uint64_t attr_valid; /* Cache timeout for the attributes */
+ uint32_t attr_valid_nsec;
+ uint32_t dummy;
struct fuse_attr attr;
};
#define FUSE_COMPAT_MKNOD_IN_SIZE 8
struct fuse_mknod_in {
- __u32 mode;
- __u32 rdev;
- __u32 umask;
- __u32 padding;
+ uint32_t mode;
+ uint32_t rdev;
+ uint32_t umask;
+ uint32_t padding;
};
struct fuse_mkdir_in {
- __u32 mode;
- __u32 umask;
+ uint32_t mode;
+ uint32_t umask;
};
struct fuse_rename_in {
- __u64 newdir;
+ uint64_t newdir;
};
struct fuse_link_in {
- __u64 oldnodeid;
+ uint64_t oldnodeid;
};
struct fuse_setattr_in {
- __u32 valid;
- __u32 padding;
- __u64 fh;
- __u64 size;
- __u64 lock_owner;
- __u64 atime;
- __u64 mtime;
- __u64 unused2;
- __u32 atimensec;
- __u32 mtimensec;
- __u32 unused3;
- __u32 mode;
- __u32 unused4;
- __u32 uid;
- __u32 gid;
- __u32 unused5;
+ uint32_t valid;
+ uint32_t padding;
+ uint64_t fh;
+ uint64_t size;
+ uint64_t lock_owner;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t unused2;
+ uint32_t atimensec;
+ uint32_t mtimensec;
+ uint32_t unused3;
+ uint32_t mode;
+ uint32_t unused4;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t unused5;
};
struct fuse_open_in {
- __u32 flags;
- __u32 unused;
+ uint32_t flags;
+ uint32_t unused;
};
struct fuse_create_in {
- __u32 flags;
- __u32 mode;
- __u32 umask;
- __u32 padding;
+ uint32_t flags;
+ uint32_t mode;
+ uint32_t umask;
+ uint32_t padding;
};
struct fuse_open_out {
- __u64 fh;
- __u32 open_flags;
- __u32 padding;
+ uint64_t fh;
+ uint32_t open_flags;
+ uint32_t padding;
};
struct fuse_release_in {
- __u64 fh;
- __u32 flags;
- __u32 release_flags;
- __u64 lock_owner;
+ uint64_t fh;
+ uint32_t flags;
+ uint32_t release_flags;
+ uint64_t lock_owner;
};
struct fuse_flush_in {
- __u64 fh;
- __u32 unused;
- __u32 padding;
- __u64 lock_owner;
+ uint64_t fh;
+ uint32_t unused;
+ uint32_t padding;
+ uint64_t lock_owner;
};
struct fuse_read_in {
- __u64 fh;
- __u64 offset;
- __u32 size;
- __u32 read_flags;
- __u64 lock_owner;
- __u32 flags;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t read_flags;
+ uint64_t lock_owner;
+ uint32_t flags;
+ uint32_t padding;
};
#define FUSE_COMPAT_WRITE_IN_SIZE 24
struct fuse_write_in {
- __u64 fh;
- __u64 offset;
- __u32 size;
- __u32 write_flags;
- __u64 lock_owner;
- __u32 flags;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t write_flags;
+ uint64_t lock_owner;
+ uint32_t flags;
+ uint32_t padding;
};
struct fuse_write_out {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
#define FUSE_COMPAT_STATFS_SIZE 48
@@ -510,32 +505,32 @@
};
struct fuse_fsync_in {
- __u64 fh;
- __u32 fsync_flags;
- __u32 padding;
+ uint64_t fh;
+ uint32_t fsync_flags;
+ uint32_t padding;
};
struct fuse_setxattr_in {
- __u32 size;
- __u32 flags;
+ uint32_t size;
+ uint32_t flags;
};
struct fuse_getxattr_in {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_getxattr_out {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_lk_in {
- __u64 fh;
- __u64 owner;
+ uint64_t fh;
+ uint64_t owner;
struct fuse_file_lock lk;
- __u32 lk_flags;
- __u32 padding;
+ uint32_t lk_flags;
+ uint32_t padding;
};
struct fuse_lk_out {
@@ -543,134 +538,135 @@
};
struct fuse_access_in {
- __u32 mask;
- __u32 padding;
+ uint32_t mask;
+ uint32_t padding;
};
struct fuse_init_in {
- __u32 major;
- __u32 minor;
- __u32 max_readahead;
- __u32 flags;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
};
struct fuse_init_out {
- __u32 major;
- __u32 minor;
- __u32 max_readahead;
- __u32 flags;
- __u16 max_background;
- __u16 congestion_threshold;
- __u32 max_write;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
+ uint16_t max_background;
+ uint16_t congestion_threshold;
+ uint32_t max_write;
};
#define CUSE_INIT_INFO_MAX 4096
struct cuse_init_in {
- __u32 major;
- __u32 minor;
- __u32 unused;
- __u32 flags;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t unused;
+ uint32_t flags;
};
struct cuse_init_out {
- __u32 major;
- __u32 minor;
- __u32 unused;
- __u32 flags;
- __u32 max_read;
- __u32 max_write;
- __u32 dev_major; /* chardev major */
- __u32 dev_minor; /* chardev minor */
- __u32 spare[10];
+ uint32_t major;
+ uint32_t minor;
+ uint32_t unused;
+ uint32_t flags;
+ uint32_t max_read;
+ uint32_t max_write;
+ uint32_t dev_major; /* chardev major */
+ uint32_t dev_minor; /* chardev minor */
+ uint32_t spare[10];
};
struct fuse_interrupt_in {
- __u64 unique;
+ uint64_t unique;
};
struct fuse_bmap_in {
- __u64 block;
- __u32 blocksize;
- __u32 padding;
+ uint64_t block;
+ uint32_t blocksize;
+ uint32_t padding;
};
struct fuse_bmap_out {
- __u64 block;
+ uint64_t block;
};
struct fuse_ioctl_in {
- __u64 fh;
- __u32 flags;
- __u32 cmd;
- __u64 arg;
- __u32 in_size;
- __u32 out_size;
+ uint64_t fh;
+ uint32_t flags;
+ uint32_t cmd;
+ uint64_t arg;
+ uint32_t in_size;
+ uint32_t out_size;
};
struct fuse_ioctl_iovec {
- __u64 base;
- __u64 len;
+ uint64_t base;
+ uint64_t len;
};
struct fuse_ioctl_out {
- __s32 result;
- __u32 flags;
- __u32 in_iovs;
- __u32 out_iovs;
+ int32_t result;
+ uint32_t flags;
+ uint32_t in_iovs;
+ uint32_t out_iovs;
};
struct fuse_poll_in {
- __u64 fh;
- __u64 kh;
- __u32 flags;
- __u32 events;
+ uint64_t fh;
+ uint64_t kh;
+ uint32_t flags;
+ uint32_t events;
};
struct fuse_poll_out {
- __u32 revents;
- __u32 padding;
+ uint32_t revents;
+ uint32_t padding;
};
struct fuse_notify_poll_wakeup_out {
- __u64 kh;
+ uint64_t kh;
};
struct fuse_fallocate_in {
- __u64 fh;
- __u64 offset;
- __u64 length;
- __u32 mode;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint64_t length;
+ uint32_t mode;
+ uint32_t padding;
};
struct fuse_in_header {
- __u32 len;
- __u32 opcode;
- __u64 unique;
- __u64 nodeid;
- __u32 uid;
- __u32 gid;
- __u32 pid;
- __u32 padding;
+ uint32_t len;
+ uint32_t opcode;
+ uint64_t unique;
+ uint64_t nodeid;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t pid;
+ uint32_t padding;
};
struct fuse_out_header {
- __u32 len;
- __s32 error;
- __u64 unique;
+ uint32_t len;
+ int32_t error;
+ uint64_t unique;
};
struct fuse_dirent {
- __u64 ino;
- __u64 off;
- __u32 namelen;
- __u32 type;
+ uint64_t ino;
+ uint64_t off;
+ uint32_t namelen;
+ uint32_t type;
char name[];
};
#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
-#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_ALIGN(x) \
+ (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1))
#define FUSE_DIRENT_SIZE(d) \
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
@@ -685,47 +681,47 @@
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
struct fuse_notify_inval_inode_out {
- __u64 ino;
- __s64 off;
- __s64 len;
+ uint64_t ino;
+ int64_t off;
+ int64_t len;
};
struct fuse_notify_inval_entry_out {
- __u64 parent;
- __u32 namelen;
- __u32 padding;
+ uint64_t parent;
+ uint32_t namelen;
+ uint32_t padding;
};
struct fuse_notify_delete_out {
- __u64 parent;
- __u64 child;
- __u32 namelen;
- __u32 padding;
+ uint64_t parent;
+ uint64_t child;
+ uint32_t namelen;
+ uint32_t padding;
};
struct fuse_notify_store_out {
- __u64 nodeid;
- __u64 offset;
- __u32 size;
- __u32 padding;
+ uint64_t nodeid;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_notify_retrieve_out {
- __u64 notify_unique;
- __u64 nodeid;
- __u64 offset;
- __u32 size;
- __u32 padding;
+ uint64_t notify_unique;
+ uint64_t nodeid;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t padding;
};
/* Matches the size of fuse_write_in */
struct fuse_notify_retrieve_in {
- __u64 dummy1;
- __u64 offset;
- __u32 size;
- __u32 dummy2;
- __u64 dummy3;
- __u64 dummy4;
+ uint64_t dummy1;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t dummy2;
+ uint64_t dummy3;
+ uint64_t dummy4;
};
#endif /* _LINUX_FUSE_H */
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index ebfadc5..864e324 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -292,12 +292,12 @@
/* Message Signalled Interrupts registers */
-#define PCI_MSI_FLAGS 2 /* Various flags */
-#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
-#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
-#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
-#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
-#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */
+#define PCI_MSI_FLAGS 2 /* Message Control */
+#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */
+#define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */
+#define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */
#define PCI_MSI_RFU 3 /* Rest of capability flags */
#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
@@ -309,13 +309,17 @@
#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */
/* MSI-X registers */
-#define PCI_MSIX_FLAGS 2
-#define PCI_MSIX_FLAGS_QSIZE 0x7FF
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
-#define PCI_MSIX_TABLE 4
-#define PCI_MSIX_PBA 8
-#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
+#define PCI_MSIX_FLAGS 2 /* Message Control */
+#define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */
+#define PCI_MSIX_FLAGS_MASKALL 0x4000 /* Mask all vectors for this function */
+#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */
+#define PCI_MSIX_TABLE 4 /* Table offset */
+#define PCI_MSIX_TABLE_BIR 0x00000007 /* BAR index */
+#define PCI_MSIX_TABLE_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_MSIX_PBA 8 /* Pending Bit Array offset */
+#define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */
+#define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) /* deprecated */
#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */
/* MSI-X entry's format */
diff --git a/include/video/auo_k190xfb.h b/include/video/auo_k190xfb.h
index 609efe8..ac329ee 100644
--- a/include/video/auo_k190xfb.h
+++ b/include/video/auo_k190xfb.h
@@ -22,6 +22,8 @@
*/
#define AUOK190X_RESOLUTION_800_600 0
#define AUOK190X_RESOLUTION_1024_768 1
+#define AUOK190X_RESOLUTION_600_800 4
+#define AUOK190X_RESOLUTION_768_1024 5
/*
* struct used by auok190x. board specific stuff comes from *board
@@ -98,7 +100,6 @@
int gpio_nbusy;
int resolution;
- int rotation;
int quirks;
int fps;
};
diff --git a/include/video/display_timing.h b/include/video/display_timing.h
index 71e9a38..5d0259b 100644
--- a/include/video/display_timing.h
+++ b/include/video/display_timing.h
@@ -12,19 +12,22 @@
#include <linux/bitops.h>
#include <linux/types.h>
-/* VESA display monitor timing parameters */
-#define VESA_DMT_HSYNC_LOW BIT(0)
-#define VESA_DMT_HSYNC_HIGH BIT(1)
-#define VESA_DMT_VSYNC_LOW BIT(2)
-#define VESA_DMT_VSYNC_HIGH BIT(3)
+enum display_flags {
+ DISPLAY_FLAGS_HSYNC_LOW = BIT(0),
+ DISPLAY_FLAGS_HSYNC_HIGH = BIT(1),
+ DISPLAY_FLAGS_VSYNC_LOW = BIT(2),
+ DISPLAY_FLAGS_VSYNC_HIGH = BIT(3),
-/* display specific flags */
-#define DISPLAY_FLAGS_DE_LOW BIT(0) /* data enable flag */
-#define DISPLAY_FLAGS_DE_HIGH BIT(1)
-#define DISPLAY_FLAGS_PIXDATA_POSEDGE BIT(2) /* drive data on pos. edge */
-#define DISPLAY_FLAGS_PIXDATA_NEGEDGE BIT(3) /* drive data on neg. edge */
-#define DISPLAY_FLAGS_INTERLACED BIT(4)
-#define DISPLAY_FLAGS_DOUBLESCAN BIT(5)
+ /* data enable flag */
+ DISPLAY_FLAGS_DE_LOW = BIT(4),
+ DISPLAY_FLAGS_DE_HIGH = BIT(5),
+ /* drive data on pos. edge */
+ DISPLAY_FLAGS_PIXDATA_POSEDGE = BIT(6),
+ /* drive data on neg. edge */
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE = BIT(7),
+ DISPLAY_FLAGS_INTERLACED = BIT(8),
+ DISPLAY_FLAGS_DOUBLESCAN = BIT(9),
+};
/*
* A single signal can be specified via a range of minimal and maximal values
@@ -36,12 +39,6 @@
u32 max;
};
-enum timing_entry_index {
- TE_MIN = 0,
- TE_TYP = 1,
- TE_MAX = 2,
-};
-
/*
* Single "mode" entry. This describes one set of signal timings a display can
* have in one setting. This struct can later be converted to struct videomode
@@ -72,8 +69,7 @@
struct timing_entry vback_porch; /* ver. back porch */
struct timing_entry vsync_len; /* ver. sync len */
- unsigned int dmt_flags; /* VESA DMT flags */
- unsigned int data_flags; /* video data flags */
+ enum display_flags flags; /* display flags */
};
/*
@@ -89,25 +85,6 @@
struct display_timing **timings;
};
-/* get value specified by index from struct timing_entry */
-static inline u32 display_timing_get_value(const struct timing_entry *te,
- enum timing_entry_index index)
-{
- switch (index) {
- case TE_MIN:
- return te->min;
- break;
- case TE_TYP:
- return te->typ;
- break;
- case TE_MAX:
- return te->max;
- break;
- default:
- return te->typ;
- }
-}
-
/* get one entry from struct display_timings */
static inline struct display_timing *display_timings_get(const struct
display_timings *disp,
diff --git a/include/video/videomode.h b/include/video/videomode.h
index a421562..3f1049d 100644
--- a/include/video/videomode.h
+++ b/include/video/videomode.h
@@ -29,20 +29,30 @@
u32 vback_porch;
u32 vsync_len;
- unsigned int dmt_flags; /* VESA DMT flags */
- unsigned int data_flags; /* video data flags */
+ enum display_flags flags; /* display flags */
};
/**
* videomode_from_timing - convert display timing to videomode
+ * @dt: display_timing structure
+ * @vm: return value
+ *
+ * DESCRIPTION:
+ * This function converts a struct display_timing to a struct videomode.
+ */
+void videomode_from_timing(const struct display_timing *dt,
+ struct videomode *vm);
+
+/**
+ * videomode_from_timings - convert one display timings entry to videomode
* @disp: structure with all possible timing entries
* @vm: return value
* @index: index into the list of display timings in devicetree
*
* DESCRIPTION:
- * This function converts a struct display_timing to a struct videomode.
+ * This function converts one struct display_timing entry to a struct videomode.
*/
-int videomode_from_timing(const struct display_timings *disp,
+int videomode_from_timings(const struct display_timings *disp,
struct videomode *vm, unsigned int index);
#endif
diff --git a/include/xen/events.h b/include/xen/events.h
index c6bfe01..b2b27c6 100644
--- a/include/xen/events.h
+++ b/include/xen/events.h
@@ -90,8 +90,7 @@
int xen_allocate_pirq_msi(struct pci_dev *dev, struct msi_desc *msidesc);
/* Bind an PSI pirq to an irq. */
int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,
- int pirq, int vector, const char *name,
- domid_t domid);
+ int pirq, const char *name, domid_t domid);
#endif
/* De-allocates the above mentioned physical interrupt. */
diff --git a/kernel/.gitignore b/kernel/.gitignore
index ab4f109..b3097bd 100644
--- a/kernel/.gitignore
+++ b/kernel/.gitignore
@@ -4,3 +4,4 @@
config_data.h
config_data.gz
timeconst.h
+hz.bc
diff --git a/kernel/capability.c b/kernel/capability.c
index 493d972..f6c2ce5 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -393,6 +393,30 @@
EXPORT_SYMBOL(ns_capable);
/**
+ * file_ns_capable - Determine if the file's opener had a capability in effect
+ * @file: The file we want to check
+ * @ns: The usernamespace we want the capability in
+ * @cap: The capability to be tested for
+ *
+ * Return true if task that opened the file had a capability in effect
+ * when the file was opened.
+ *
+ * This does not set PF_SUPERPRIV because the caller may not
+ * actually be privileged.
+ */
+bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap)
+{
+ if (WARN_ON_ONCE(!cap_valid(cap)))
+ return false;
+
+ if (security_capable(file->f_cred, ns, cap) == 0)
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL(file_ns_capable);
+
+/**
* capable - Determine if the current task has a superior capability in effect
* @cap: The capability to be tested for
*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 59412d0..9fcb094 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4596,6 +4596,7 @@
struct perf_event_context *ctx;
int ctxn;
+ rcu_read_lock();
for_each_task_context_nr(ctxn) {
ctx = task->perf_event_ctxp[ctxn];
if (!ctx)
@@ -4603,6 +4604,7 @@
perf_event_enable_on_exec(ctx);
}
+ rcu_read_unlock();
if (!atomic_read(&nr_comm_events))
return;
@@ -4737,7 +4739,8 @@
} else {
if (arch_vma_name(mmap_event->vma)) {
name = strncpy(tmp, arch_vma_name(mmap_event->vma),
- sizeof(tmp));
+ sizeof(tmp) - 1);
+ tmp[sizeof(tmp) - 1] = '\0';
goto got_name;
}
@@ -5330,7 +5333,7 @@
static int perf_swevent_init(struct perf_event *event)
{
- int event_id = event->attr.config;
+ u64 event_id = event->attr.config;
if (event->attr.type != PERF_TYPE_SOFTWARE)
return -ENOENT;
@@ -5986,6 +5989,7 @@
if (pmu->pmu_cpu_context)
goto got_cpu_context;
+ ret = -ENOMEM;
pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context);
if (!pmu->pmu_cpu_context)
goto free_dev;
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index d56a64c..eb675c4 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -16,7 +16,7 @@
int page_order; /* allocation order */
#endif
int nr_pages; /* nr of data pages */
- int writable; /* are we writable */
+ int overwrite; /* can overwrite itself */
atomic_t poll; /* POLL_ for wakeups */
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 23cb34f..97fddb0 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -18,12 +18,24 @@
static bool perf_output_space(struct ring_buffer *rb, unsigned long tail,
unsigned long offset, unsigned long head)
{
- unsigned long mask;
+ unsigned long sz = perf_data_size(rb);
+ unsigned long mask = sz - 1;
- if (!rb->writable)
+ /*
+ * check if user-writable
+ * overwrite : over-write its own tail
+ * !overwrite: buffer possibly drops events.
+ */
+ if (rb->overwrite)
return true;
- mask = perf_data_size(rb) - 1;
+ /*
+ * verify that payload is not bigger than buffer
+ * otherwise masking logic may fail to detect
+ * the "not enough space" condition
+ */
+ if ((head - offset) > sz)
+ return false;
offset = (offset - tail) & mask;
head = (head - tail) & mask;
@@ -212,7 +224,9 @@
rb->watermark = max_size / 2;
if (flags & RING_BUFFER_WRITABLE)
- rb->writable = 1;
+ rb->overwrite = 0;
+ else
+ rb->overwrite = 1;
atomic_set(&rb->refcount, 1);
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index cc47812..14be27f 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -63,6 +63,7 @@
DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
{
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
.clock_base =
{
{
@@ -1642,8 +1643,6 @@
struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu);
int i;
- raw_spin_lock_init(&cpu_base->lock);
-
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
cpu_base->clock_base[i].cpu_base = cpu_base;
timerqueue_init_head(&cpu_base->clock_base[i].active);
diff --git a/kernel/kexec.c b/kernel/kexec.c
index bddd3d7..ffd4e11 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -55,7 +55,7 @@
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
struct resource crashk_low_res = {
- .name = "Crash kernel low",
+ .name = "Crash kernel",
.start = 0,
.end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
@@ -1368,35 +1368,114 @@
return 0;
}
+#define SUFFIX_HIGH 0
+#define SUFFIX_LOW 1
+#define SUFFIX_NULL 2
+static __initdata char *suffix_tbl[] = {
+ [SUFFIX_HIGH] = ",high",
+ [SUFFIX_LOW] = ",low",
+ [SUFFIX_NULL] = NULL,
+};
+
/*
- * That function is the entry point for command line parsing and should be
- * called from the arch-specific code.
+ * That function parses "suffix" crashkernel command lines like
+ *
+ * crashkernel=size,[high|low]
+ *
+ * It returns 0 on success and -EINVAL on failure.
*/
+static int __init parse_crashkernel_suffix(char *cmdline,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base,
+ const char *suffix)
+{
+ char *cur = cmdline;
+
+ *crash_size = memparse(cmdline, &cur);
+ if (cmdline == cur) {
+ pr_warn("crashkernel: memory value expected\n");
+ return -EINVAL;
+ }
+
+ /* check with suffix */
+ if (strncmp(cur, suffix, strlen(suffix))) {
+ pr_warn("crashkernel: unrecognized char\n");
+ return -EINVAL;
+ }
+ cur += strlen(suffix);
+ if (*cur != ' ' && *cur != '\0') {
+ pr_warn("crashkernel: unrecognized char\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static __init char *get_last_crashkernel(char *cmdline,
+ const char *name,
+ const char *suffix)
+{
+ char *p = cmdline, *ck_cmdline = NULL;
+
+ /* find crashkernel and use the last one if there are more */
+ p = strstr(p, name);
+ while (p) {
+ char *end_p = strchr(p, ' ');
+ char *q;
+
+ if (!end_p)
+ end_p = p + strlen(p);
+
+ if (!suffix) {
+ int i;
+
+ /* skip the one with any known suffix */
+ for (i = 0; suffix_tbl[i]; i++) {
+ q = end_p - strlen(suffix_tbl[i]);
+ if (!strncmp(q, suffix_tbl[i],
+ strlen(suffix_tbl[i])))
+ goto next;
+ }
+ ck_cmdline = p;
+ } else {
+ q = end_p - strlen(suffix);
+ if (!strncmp(q, suffix, strlen(suffix)))
+ ck_cmdline = p;
+ }
+next:
+ p = strstr(p+1, name);
+ }
+
+ if (!ck_cmdline)
+ return NULL;
+
+ return ck_cmdline;
+}
+
static int __init __parse_crashkernel(char *cmdline,
unsigned long long system_ram,
unsigned long long *crash_size,
unsigned long long *crash_base,
- const char *name)
+ const char *name,
+ const char *suffix)
{
- char *p = cmdline, *ck_cmdline = NULL;
char *first_colon, *first_space;
+ char *ck_cmdline;
BUG_ON(!crash_size || !crash_base);
*crash_size = 0;
*crash_base = 0;
- /* find crashkernel and use the last one if there are more */
- p = strstr(p, name);
- while (p) {
- ck_cmdline = p;
- p = strstr(p+1, name);
- }
+ ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
if (!ck_cmdline)
return -EINVAL;
ck_cmdline += strlen(name);
+ if (suffix)
+ return parse_crashkernel_suffix(ck_cmdline, crash_size,
+ crash_base, suffix);
/*
* if the commandline contains a ':', then that's the extended
* syntax -- if not, it must be the classic syntax
@@ -1413,13 +1492,26 @@
return 0;
}
+/*
+ * That function is the entry point for command line parsing and should be
+ * called from the arch-specific code.
+ */
int __init parse_crashkernel(char *cmdline,
unsigned long long system_ram,
unsigned long long *crash_size,
unsigned long long *crash_base)
{
return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
- "crashkernel=");
+ "crashkernel=", NULL);
+}
+
+int __init parse_crashkernel_high(char *cmdline,
+ unsigned long long system_ram,
+ unsigned long long *crash_size,
+ unsigned long long *crash_base)
+{
+ return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+ "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
}
int __init parse_crashkernel_low(char *cmdline,
@@ -1428,7 +1520,7 @@
unsigned long long *crash_base)
{
return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
- "crashkernel_low=");
+ "crashkernel=", suffix_tbl[SUFFIX_LOW]);
}
static void update_vmcoreinfo_note(void)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index e35be53..3fed7f0 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -794,16 +794,16 @@
}
#ifdef CONFIG_SYSCTL
-/* This should be called with kprobe_mutex locked */
static void __kprobes optimize_all_kprobes(void)
{
struct hlist_head *head;
struct kprobe *p;
unsigned int i;
+ mutex_lock(&kprobe_mutex);
/* If optimization is already allowed, just return */
if (kprobes_allow_optimization)
- return;
+ goto out;
kprobes_allow_optimization = true;
for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
@@ -813,18 +813,22 @@
optimize_kprobe(p);
}
printk(KERN_INFO "Kprobes globally optimized\n");
+out:
+ mutex_unlock(&kprobe_mutex);
}
-/* This should be called with kprobe_mutex locked */
static void __kprobes unoptimize_all_kprobes(void)
{
struct hlist_head *head;
struct kprobe *p;
unsigned int i;
+ mutex_lock(&kprobe_mutex);
/* If optimization is already prohibited, just return */
- if (!kprobes_allow_optimization)
+ if (!kprobes_allow_optimization) {
+ mutex_unlock(&kprobe_mutex);
return;
+ }
kprobes_allow_optimization = false;
for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
@@ -834,11 +838,14 @@
unoptimize_kprobe(p, false);
}
}
+ mutex_unlock(&kprobe_mutex);
+
/* Wait for unoptimizing completion */
wait_for_kprobe_optimizer();
printk(KERN_INFO "Kprobes globally unoptimized\n");
}
+static DEFINE_MUTEX(kprobe_sysctl_mutex);
int sysctl_kprobes_optimization;
int proc_kprobes_optimization_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *length,
@@ -846,7 +853,7 @@
{
int ret;
- mutex_lock(&kprobe_mutex);
+ mutex_lock(&kprobe_sysctl_mutex);
sysctl_kprobes_optimization = kprobes_allow_optimization ? 1 : 0;
ret = proc_dointvec_minmax(table, write, buffer, length, ppos);
@@ -854,7 +861,7 @@
optimize_all_kprobes();
else
unoptimize_all_kprobes();
- mutex_unlock(&kprobe_mutex);
+ mutex_unlock(&kprobe_sysctl_mutex);
return ret;
}
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 691dc2e..9eb7fed 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -124,12 +124,12 @@
static void __kthread_parkme(struct kthread *self)
{
- __set_current_state(TASK_INTERRUPTIBLE);
+ __set_current_state(TASK_PARKED);
while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
complete(&self->parked);
schedule();
- __set_current_state(TASK_INTERRUPTIBLE);
+ __set_current_state(TASK_PARKED);
}
clear_bit(KTHREAD_IS_PARKED, &self->flags);
__set_current_state(TASK_RUNNING);
@@ -256,8 +256,13 @@
}
EXPORT_SYMBOL(kthread_create_on_node);
-static void __kthread_bind(struct task_struct *p, unsigned int cpu)
+static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state)
{
+ /* Must have done schedule() in kthread() before we set_task_cpu */
+ if (!wait_task_inactive(p, state)) {
+ WARN_ON(1);
+ return;
+ }
/* It's safe because the task is inactive. */
do_set_cpus_allowed(p, cpumask_of(cpu));
p->flags |= PF_THREAD_BOUND;
@@ -274,12 +279,7 @@
*/
void kthread_bind(struct task_struct *p, unsigned int cpu)
{
- /* Must have done schedule() in kthread() before we set_task_cpu */
- if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) {
- WARN_ON(1);
- return;
- }
- __kthread_bind(p, cpu);
+ __kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(kthread_bind);
@@ -324,6 +324,22 @@
return NULL;
}
+static void __kthread_unpark(struct task_struct *k, struct kthread *kthread)
+{
+ clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+ /*
+ * We clear the IS_PARKED bit here as we don't wait
+ * until the task has left the park code. So if we'd
+ * park before that happens we'd see the IS_PARKED bit
+ * which might be about to be cleared.
+ */
+ if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
+ if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
+ __kthread_bind(k, kthread->cpu, TASK_PARKED);
+ wake_up_state(k, TASK_PARKED);
+ }
+}
+
/**
* kthread_unpark - unpark a thread created by kthread_create().
* @k: thread created by kthread_create().
@@ -336,20 +352,8 @@
{
struct kthread *kthread = task_get_live_kthread(k);
- if (kthread) {
- clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
- /*
- * We clear the IS_PARKED bit here as we don't wait
- * until the task has left the park code. So if we'd
- * park before that happens we'd see the IS_PARKED bit
- * which might be about to be cleared.
- */
- if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) {
- if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags))
- __kthread_bind(k, kthread->cpu);
- wake_up_process(k);
- }
- }
+ if (kthread)
+ __kthread_unpark(k, kthread);
put_task_struct(k);
}
@@ -407,7 +411,7 @@
trace_sched_kthread_stop(k);
if (kthread) {
set_bit(KTHREAD_SHOULD_STOP, &kthread->flags);
- clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags);
+ __kthread_unpark(k, kthread);
wake_up_process(k);
wait_for_completion(&kthread->exited);
}
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 8a0efac..6a3bccb 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -380,6 +380,13 @@
unsigned long nr_stack_trace_entries;
static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES];
+static void print_lockdep_off(const char *bug_msg)
+{
+ printk(KERN_DEBUG "%s\n", bug_msg);
+ printk(KERN_DEBUG "turning off the locking correctness validator.\n");
+ printk(KERN_DEBUG "Please attach the output of /proc/lock_stat to the bug report\n");
+}
+
static int save_trace(struct stack_trace *trace)
{
trace->nr_entries = 0;
@@ -409,8 +416,7 @@
if (!debug_locks_off_graph_unlock())
return 0;
- printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n");
- printk("turning off the locking correctness validator.\n");
+ print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!");
dump_stack();
return 0;
@@ -763,8 +769,7 @@
}
raw_local_irq_restore(flags);
- printk("BUG: MAX_LOCKDEP_KEYS too low!\n");
- printk("turning off the locking correctness validator.\n");
+ print_lockdep_off("BUG: MAX_LOCKDEP_KEYS too low!");
dump_stack();
return NULL;
}
@@ -834,8 +839,7 @@
if (!debug_locks_off_graph_unlock())
return NULL;
- printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n");
- printk("turning off the locking correctness validator.\n");
+ print_lockdep_off("BUG: MAX_LOCKDEP_ENTRIES too low!");
dump_stack();
return NULL;
}
@@ -2000,7 +2004,7 @@
struct lock_class *class = hlock_class(hlock);
struct list_head *hash_head = chainhashentry(chain_key);
struct lock_chain *chain;
- struct held_lock *hlock_curr, *hlock_next;
+ struct held_lock *hlock_curr;
int i, j;
/*
@@ -2048,8 +2052,7 @@
if (!debug_locks_off_graph_unlock())
return 0;
- printk("BUG: MAX_LOCKDEP_CHAINS too low!\n");
- printk("turning off the locking correctness validator.\n");
+ print_lockdep_off("BUG: MAX_LOCKDEP_CHAINS too low!");
dump_stack();
return 0;
}
@@ -2057,12 +2060,10 @@
chain->chain_key = chain_key;
chain->irq_context = hlock->irq_context;
/* Find the first held_lock of current chain */
- hlock_next = hlock;
for (i = curr->lockdep_depth - 1; i >= 0; i--) {
hlock_curr = curr->held_locks + i;
- if (hlock_curr->irq_context != hlock_next->irq_context)
+ if (hlock_curr->irq_context != hlock->irq_context)
break;
- hlock_next = hlock;
}
i++;
chain->depth = curr->lockdep_depth + 1 - i;
@@ -3190,9 +3191,9 @@
#endif
if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) {
debug_locks_off();
- printk("BUG: MAX_LOCK_DEPTH too low, depth: %i max: %lu!\n",
+ print_lockdep_off("BUG: MAX_LOCK_DEPTH too low!");
+ printk(KERN_DEBUG "depth: %i max: %lu!\n",
curr->lockdep_depth, MAX_LOCK_DEPTH);
- printk("turning off the locking correctness validator.\n");
lockdep_print_held_locks(current);
debug_show_all_locks();
diff --git a/kernel/mutex.c b/kernel/mutex.c
index 52f2301..ad53a66 100644
--- a/kernel/mutex.c
+++ b/kernel/mutex.c
@@ -37,6 +37,12 @@
# include <asm/mutex.h>
#endif
+/*
+ * A negative mutex count indicates that waiters are sleeping waiting for the
+ * mutex.
+ */
+#define MUTEX_SHOW_NO_WAITER(mutex) (atomic_read(&(mutex)->count) >= 0)
+
void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{
@@ -44,6 +50,9 @@
spin_lock_init(&lock->wait_lock);
INIT_LIST_HEAD(&lock->wait_list);
mutex_clear_owner(lock);
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+ lock->spin_mlock = NULL;
+#endif
debug_mutex_init(lock, name, key);
}
@@ -95,6 +104,124 @@
EXPORT_SYMBOL(mutex_lock);
#endif
+#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
+/*
+ * In order to avoid a stampede of mutex spinners from acquiring the mutex
+ * more or less simultaneously, the spinners need to acquire a MCS lock
+ * first before spinning on the owner field.
+ *
+ * We don't inline mspin_lock() so that perf can correctly account for the
+ * time spent in this lock function.
+ */
+struct mspin_node {
+ struct mspin_node *next ;
+ int locked; /* 1 if lock acquired */
+};
+#define MLOCK(mutex) ((struct mspin_node **)&((mutex)->spin_mlock))
+
+static noinline
+void mspin_lock(struct mspin_node **lock, struct mspin_node *node)
+{
+ struct mspin_node *prev;
+
+ /* Init node */
+ node->locked = 0;
+ node->next = NULL;
+
+ prev = xchg(lock, node);
+ if (likely(prev == NULL)) {
+ /* Lock acquired */
+ node->locked = 1;
+ return;
+ }
+ ACCESS_ONCE(prev->next) = node;
+ smp_wmb();
+ /* Wait until the lock holder passes the lock down */
+ while (!ACCESS_ONCE(node->locked))
+ arch_mutex_cpu_relax();
+}
+
+static void mspin_unlock(struct mspin_node **lock, struct mspin_node *node)
+{
+ struct mspin_node *next = ACCESS_ONCE(node->next);
+
+ if (likely(!next)) {
+ /*
+ * Release the lock by setting it to NULL
+ */
+ if (cmpxchg(lock, node, NULL) == node)
+ return;
+ /* Wait until the next pointer is set */
+ while (!(next = ACCESS_ONCE(node->next)))
+ arch_mutex_cpu_relax();
+ }
+ ACCESS_ONCE(next->locked) = 1;
+ smp_wmb();
+}
+
+/*
+ * Mutex spinning code migrated from kernel/sched/core.c
+ */
+
+static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
+{
+ if (lock->owner != owner)
+ return false;
+
+ /*
+ * Ensure we emit the owner->on_cpu, dereference _after_ checking
+ * lock->owner still matches owner, if that fails, owner might
+ * point to free()d memory, if it still matches, the rcu_read_lock()
+ * ensures the memory stays valid.
+ */
+ barrier();
+
+ return owner->on_cpu;
+}
+
+/*
+ * Look out! "owner" is an entirely speculative pointer
+ * access and not reliable.
+ */
+static noinline
+int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
+{
+ rcu_read_lock();
+ while (owner_running(lock, owner)) {
+ if (need_resched())
+ break;
+
+ arch_mutex_cpu_relax();
+ }
+ rcu_read_unlock();
+
+ /*
+ * We break out the loop above on need_resched() and when the
+ * owner changed, which is a sign for heavy contention. Return
+ * success only when lock->owner is NULL.
+ */
+ return lock->owner == NULL;
+}
+
+/*
+ * Initial check for entering the mutex spinning loop
+ */
+static inline int mutex_can_spin_on_owner(struct mutex *lock)
+{
+ int retval = 1;
+
+ rcu_read_lock();
+ if (lock->owner)
+ retval = lock->owner->on_cpu;
+ rcu_read_unlock();
+ /*
+ * if lock->owner is not set, the mutex owner may have just acquired
+ * it and not set the owner yet or the mutex has been released.
+ */
+ return retval;
+}
+#endif
+
static __used noinline void __sched __mutex_unlock_slowpath(atomic_t *lock_count);
/**
@@ -158,25 +285,39 @@
*
* We can't do this for DEBUG_MUTEXES because that relies on wait_lock
* to serialize everything.
+ *
+ * The mutex spinners are queued up using MCS lock so that only one
+ * spinner can compete for the mutex. However, if mutex spinning isn't
+ * going to happen, there is no point in going through the lock/unlock
+ * overhead.
*/
+ if (!mutex_can_spin_on_owner(lock))
+ goto slowpath;
for (;;) {
struct task_struct *owner;
+ struct mspin_node node;
/*
* If there's an owner, wait for it to either
* release the lock or go to sleep.
*/
+ mspin_lock(MLOCK(lock), &node);
owner = ACCESS_ONCE(lock->owner);
- if (owner && !mutex_spin_on_owner(lock, owner))
+ if (owner && !mutex_spin_on_owner(lock, owner)) {
+ mspin_unlock(MLOCK(lock), &node);
break;
+ }
- if (atomic_cmpxchg(&lock->count, 1, 0) == 1) {
+ if ((atomic_read(&lock->count) == 1) &&
+ (atomic_cmpxchg(&lock->count, 1, 0) == 1)) {
lock_acquired(&lock->dep_map, ip);
mutex_set_owner(lock);
+ mspin_unlock(MLOCK(lock), &node);
preempt_enable();
return 0;
}
+ mspin_unlock(MLOCK(lock), &node);
/*
* When there's no owner, we might have preempted between the
@@ -195,6 +336,7 @@
*/
arch_mutex_cpu_relax();
}
+slowpath:
#endif
spin_lock_mutex(&lock->wait_lock, flags);
@@ -205,7 +347,7 @@
list_add_tail(&waiter.list, &lock->wait_list);
waiter.task = task;
- if (atomic_xchg(&lock->count, -1) == 1)
+ if (MUTEX_SHOW_NO_WAITER(lock) && (atomic_xchg(&lock->count, -1) == 1))
goto done;
lock_contended(&lock->dep_map, ip);
@@ -220,7 +362,8 @@
* that when we release the lock, we properly wake up the
* other waiters:
*/
- if (atomic_xchg(&lock->count, -1) == 1)
+ if (MUTEX_SHOW_NO_WAITER(lock) &&
+ (atomic_xchg(&lock->count, -1) == 1))
break;
/*
diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
index 7890b10..1d96dd0 100644
--- a/kernel/rtmutex-tester.c
+++ b/kernel/rtmutex-tester.c
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/freezer.h>
+#include <linux/stat.h>
#include "rtmutex.h"
@@ -366,8 +367,8 @@
return curr - buf;
}
-static DEVICE_ATTR(status, 0600, sysfs_test_status, NULL);
-static DEVICE_ATTR(command, 0600, NULL, sysfs_test_command);
+static DEVICE_ATTR(status, S_IRUSR, sysfs_test_status, NULL);
+static DEVICE_ATTR(command, S_IWUSR, NULL, sysfs_test_command);
static struct bus_type rttest_subsys = {
.name = "rttest",
diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c
index c685e31..c3ae144 100644
--- a/kernel/sched/clock.c
+++ b/kernel/sched/clock.c
@@ -176,10 +176,36 @@
u64 this_clock, remote_clock;
u64 *ptr, old_val, val;
+#if BITS_PER_LONG != 64
+again:
+ /*
+ * Careful here: The local and the remote clock values need to
+ * be read out atomic as we need to compare the values and
+ * then update either the local or the remote side. So the
+ * cmpxchg64 below only protects one readout.
+ *
+ * We must reread via sched_clock_local() in the retry case on
+ * 32bit as an NMI could use sched_clock_local() via the
+ * tracer and hit between the readout of
+ * the low32bit and the high 32bit portion.
+ */
+ this_clock = sched_clock_local(my_scd);
+ /*
+ * We must enforce atomic readout on 32bit, otherwise the
+ * update on the remote cpu can hit inbetween the readout of
+ * the low32bit and the high 32bit portion.
+ */
+ remote_clock = cmpxchg64(&scd->clock, 0, 0);
+#else
+ /*
+ * On 64bit the read of [my]scd->clock is atomic versus the
+ * update, so we can avoid the above 32bit dance.
+ */
sched_clock_local(my_scd);
again:
this_clock = my_scd->clock;
remote_clock = scd->clock;
+#endif
/*
* Use the opportunity that we have both locks
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 7f12624..4205354 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1498,8 +1498,10 @@
{
struct rq *rq = task_rq(p);
- BUG_ON(rq != this_rq());
- BUG_ON(p == current);
+ if (WARN_ON_ONCE(rq != this_rq()) ||
+ WARN_ON_ONCE(p == current))
+ return;
+
lockdep_assert_held(&rq->lock);
if (!raw_spin_trylock(&p->pi_lock)) {
@@ -2997,51 +2999,6 @@
preempt_disable();
}
-#ifdef CONFIG_MUTEX_SPIN_ON_OWNER
-
-static inline bool owner_running(struct mutex *lock, struct task_struct *owner)
-{
- if (lock->owner != owner)
- return false;
-
- /*
- * Ensure we emit the owner->on_cpu, dereference _after_ checking
- * lock->owner still matches owner, if that fails, owner might
- * point to free()d memory, if it still matches, the rcu_read_lock()
- * ensures the memory stays valid.
- */
- barrier();
-
- return owner->on_cpu;
-}
-
-/*
- * Look out! "owner" is an entirely speculative pointer
- * access and not reliable.
- */
-int mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner)
-{
- if (!sched_feat(OWNER_SPIN))
- return 0;
-
- rcu_read_lock();
- while (owner_running(lock, owner)) {
- if (need_resched())
- break;
-
- arch_mutex_cpu_relax();
- }
- rcu_read_unlock();
-
- /*
- * We break out the loop above on need_resched() and when the
- * owner changed, which is a sign for heavy contention. Return
- * success only when lock->owner is NULL.
- */
- return lock->owner == NULL;
-}
-#endif
-
#ifdef CONFIG_PREEMPT
/*
* this is the entry point to schedule() from in-kernel preemption
@@ -4999,7 +4956,7 @@
}
static int min_load_idx = 0;
-static int max_load_idx = CPU_LOAD_IDX_MAX;
+static int max_load_idx = CPU_LOAD_IDX_MAX-1;
static void
set_table_entry(struct ctl_table *entry,
diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
index ed12cbb..e93cca9 100644
--- a/kernel/sched/cputime.c
+++ b/kernel/sched/cputime.c
@@ -310,7 +310,7 @@
t = tsk;
do {
- task_cputime(tsk, &utime, &stime);
+ task_cputime(t, &utime, &stime);
times->utime += utime;
times->stime += stime;
times->sum_exec_runtime += task_sched_runtime(t);
diff --git a/kernel/sched/features.h b/kernel/sched/features.h
index 1ad1d2b..99399f8 100644
--- a/kernel/sched/features.h
+++ b/kernel/sched/features.h
@@ -46,13 +46,6 @@
SCHED_FEAT(LB_BIAS, true)
/*
- * Spin-wait on mutex acquisition when the mutex owner is running on
- * another cpu -- assumes that when the owner is running, it will soon
- * release the lock. Decreases scheduling overhead.
- */
-SCHED_FEAT(OWNER_SPIN, true)
-
-/*
* Decrement CPU power based on time not spent running tasks
*/
SCHED_FEAT(NONTASK_POWER, true)
diff --git a/kernel/signal.c b/kernel/signal.c
index dd72567..598dc06 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2948,7 +2948,7 @@
static int do_tkill(pid_t tgid, pid_t pid, int sig)
{
- struct siginfo info;
+ struct siginfo info = {};
info.si_signo = sig;
info.si_errno = 0;
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
index 8eaed9a..02fc5c9 100644
--- a/kernel/smpboot.c
+++ b/kernel/smpboot.c
@@ -185,8 +185,18 @@
}
get_task_struct(tsk);
*per_cpu_ptr(ht->store, cpu) = tsk;
- if (ht->create)
- ht->create(cpu);
+ if (ht->create) {
+ /*
+ * Make sure that the task has actually scheduled out
+ * into park position, before calling the create
+ * callback. At least the migration thread callback
+ * requires that the task is off the runqueue.
+ */
+ if (!wait_task_inactive(tsk, TASK_PARKED))
+ WARN_ON(1);
+ else
+ ht->create(cpu);
+ }
return 0;
}
diff --git a/kernel/sys.c b/kernel/sys.c
index 39c9c4a..0da73cf 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -324,7 +324,6 @@
system_state = SYSTEM_RESTART;
usermodehelper_disable();
device_shutdown();
- syscore_shutdown();
}
/**
@@ -370,6 +369,7 @@
{
kernel_restart_prepare(cmd);
disable_nonboot_cpus();
+ syscore_shutdown();
if (!cmd)
printk(KERN_EMERG "Restarting system.\n");
else
@@ -395,6 +395,7 @@
void kernel_halt(void)
{
kernel_shutdown_prepare(SYSTEM_HALT);
+ disable_nonboot_cpus();
syscore_shutdown();
printk(KERN_EMERG "System halted.\n");
kmsg_dump(KMSG_DUMP_HALT);
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 9e5b8c2..5a0f781 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -739,12 +739,6 @@
struct request_queue *q,
struct request *rq)
{
- struct blk_trace *bt = q->blk_trace;
-
- /* if control ever passes through here, it's a request based driver */
- if (unlikely(bt && !bt->rq_based))
- bt->rq_based = true;
-
blk_add_trace_rq(q, rq, BLK_TA_COMPLETE);
}
@@ -780,24 +774,10 @@
blk_add_trace_bio(q, bio, BLK_TA_BOUNCE, 0);
}
-static void blk_add_trace_bio_complete(void *ignore, struct bio *bio, int error)
+static void blk_add_trace_bio_complete(void *ignore,
+ struct request_queue *q, struct bio *bio,
+ int error)
{
- struct request_queue *q;
- struct blk_trace *bt;
-
- if (!bio->bi_bdev)
- return;
-
- q = bdev_get_queue(bio->bi_bdev);
- bt = q->blk_trace;
-
- /*
- * Request based drivers will generate both rq and bio completions.
- * Ignore bio ones.
- */
- if (likely(!bt) || bt->rq_based)
- return;
-
blk_add_trace_bio(q, bio, BLK_TA_COMPLETE, error);
}
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 6893d5a..b3fde6d 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -66,7 +66,7 @@
static struct ftrace_ops ftrace_list_end __read_mostly = {
.func = ftrace_stub,
- .flags = FTRACE_OPS_FL_RECURSION_SAFE,
+ .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
};
/* ftrace_enabled is a method to turn ftrace on or off */
@@ -694,7 +694,6 @@
free_page(tmp);
}
- free_page((unsigned long)stat->pages);
stat->pages = NULL;
stat->start = NULL;
@@ -1053,6 +1052,19 @@
static struct pid * const ftrace_swapper_pid = &init_struct_pid;
+loff_t
+ftrace_filter_lseek(struct file *file, loff_t offset, int whence)
+{
+ loff_t ret;
+
+ if (file->f_mode & FMODE_READ)
+ ret = seq_lseek(file, offset, whence);
+ else
+ file->f_pos = ret = 1;
+
+ return ret;
+}
+
#ifdef CONFIG_DYNAMIC_FTRACE
#ifndef CONFIG_FTRACE_MCOUNT_RECORD
@@ -2613,7 +2625,7 @@
* routine, you can use ftrace_filter_write() for the write
* routine if @flag has FTRACE_ITER_FILTER set, or
* ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set.
- * ftrace_regex_lseek() should be used as the lseek routine, and
+ * ftrace_filter_lseek() should be used as the lseek routine, and
* release must call ftrace_regex_release().
*/
int
@@ -2697,19 +2709,6 @@
inode, file);
}
-loff_t
-ftrace_regex_lseek(struct file *file, loff_t offset, int whence)
-{
- loff_t ret;
-
- if (file->f_mode & FMODE_READ)
- ret = seq_lseek(file, offset, whence);
- else
- file->f_pos = ret = 1;
-
- return ret;
-}
-
static int ftrace_match(char *str, char *regex, int len, int type)
{
int matched = 0;
@@ -3441,14 +3440,14 @@
static int __init set_ftrace_notrace(char *str)
{
- strncpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
+ strlcpy(ftrace_notrace_buf, str, FTRACE_FILTER_SIZE);
return 1;
}
__setup("ftrace_notrace=", set_ftrace_notrace);
static int __init set_ftrace_filter(char *str)
{
- strncpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
+ strlcpy(ftrace_filter_buf, str, FTRACE_FILTER_SIZE);
return 1;
}
__setup("ftrace_filter=", set_ftrace_filter);
@@ -3571,7 +3570,7 @@
.open = ftrace_filter_open,
.read = seq_read,
.write = ftrace_filter_write,
- .llseek = ftrace_regex_lseek,
+ .llseek = ftrace_filter_lseek,
.release = ftrace_regex_release,
};
@@ -3579,7 +3578,7 @@
.open = ftrace_notrace_open,
.read = seq_read,
.write = ftrace_notrace_write,
- .llseek = ftrace_regex_lseek,
+ .llseek = ftrace_filter_lseek,
.release = ftrace_regex_release,
};
@@ -3784,8 +3783,8 @@
.open = ftrace_graph_open,
.read = seq_read,
.write = ftrace_graph_write,
+ .llseek = ftrace_filter_lseek,
.release = ftrace_graph_release,
- .llseek = seq_lseek,
};
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
@@ -4131,7 +4130,8 @@
preempt_disable_notrace();
trace_recursion_set(TRACE_CONTROL_BIT);
do_for_each_ftrace_op(op, ftrace_control_list) {
- if (!ftrace_function_local_disabled(op) &&
+ if (!(op->flags & FTRACE_OPS_FL_STUB) &&
+ !ftrace_function_local_disabled(op) &&
ftrace_ops_test(op, ip))
op->func(ip, parent_ip, op, regs);
} while_for_each_ftrace_op(op);
@@ -4439,7 +4439,7 @@
.open = ftrace_pid_open,
.write = ftrace_pid_write,
.read = seq_read,
- .llseek = seq_lseek,
+ .llseek = ftrace_filter_lseek,
.release = ftrace_pid_release,
};
@@ -4555,12 +4555,8 @@
ftrace_startup_sysctl();
/* we are starting ftrace again */
- if (ftrace_ops_list != &ftrace_list_end) {
- if (ftrace_ops_list->next == &ftrace_list_end)
- ftrace_trace_function = ftrace_ops_list->func;
- else
- ftrace_trace_function = ftrace_ops_list_func;
- }
+ if (ftrace_ops_list != &ftrace_list_end)
+ update_ftrace_function();
} else {
/* stopping ftrace calls (just send to ftrace_stub) */
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 4f1dade..66338c4 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -132,7 +132,7 @@
static int __init set_cmdline_ftrace(char *str)
{
- strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
+ strlcpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
default_bootup_tracer = bootup_tracer_buf;
/* We are using ftrace early, expand it */
ring_buffer_expanded = 1;
@@ -162,7 +162,7 @@
static int __init set_trace_boot_options(char *str)
{
- strncpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
+ strlcpy(trace_boot_options_buf, str, MAX_TRACER_SIZE);
trace_boot_options = trace_boot_options_buf;
return 0;
}
@@ -744,8 +744,11 @@
return;
WARN_ON_ONCE(!irqs_disabled());
- if (WARN_ON_ONCE(!current_trace->allocated_snapshot))
+ if (!current_trace->allocated_snapshot) {
+ /* Only the nop tracer should hit this when disabling */
+ WARN_ON_ONCE(current_trace != &nop_trace);
return;
+ }
arch_spin_lock(&ftrace_max_lock);
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 42ca822..83a8b5b 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -322,7 +322,7 @@
.open = stack_trace_filter_open,
.read = seq_read,
.write = ftrace_filter_write,
- .llseek = ftrace_regex_lseek,
+ .llseek = ftrace_filter_lseek,
.release = ftrace_regex_release,
};
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index a54f26f..e134d8f 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -25,7 +25,8 @@
static struct kmem_cache *user_ns_cachep __read_mostly;
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file,
+ struct user_namespace *ns, int cap_setid,
struct uid_gid_map *map);
static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns)
@@ -612,10 +613,10 @@
if (map->nr_extents != 0)
goto out;
- /* Require the appropriate privilege CAP_SETUID or CAP_SETGID
- * over the user namespace in order to set the id mapping.
+ /*
+ * Adjusting namespace settings requires capabilities on the target.
*/
- if (cap_valid(cap_setid) && !ns_capable(ns, cap_setid))
+ if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN))
goto out;
/* Get a buffer */
@@ -700,7 +701,7 @@
ret = -EPERM;
/* Validate the user is allowed to use user id's mapped to. */
- if (!new_idmap_permitted(ns, cap_setid, &new_map))
+ if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
goto out;
/* Map the lower ids from the parent user namespace to the
@@ -787,7 +788,8 @@
&ns->projid_map, &ns->parent->projid_map);
}
-static bool new_idmap_permitted(struct user_namespace *ns, int cap_setid,
+static bool new_idmap_permitted(const struct file *file,
+ struct user_namespace *ns, int cap_setid,
struct uid_gid_map *new_map)
{
/* Allow mapping to your own filesystem ids */
@@ -795,12 +797,12 @@
u32 id = new_map->extent[0].lower_first;
if (cap_setid == CAP_SETUID) {
kuid_t uid = make_kuid(ns->parent, id);
- if (uid_eq(uid, current_fsuid()))
+ if (uid_eq(uid, file->f_cred->fsuid))
return true;
}
else if (cap_setid == CAP_SETGID) {
kgid_t gid = make_kgid(ns->parent, id);
- if (gid_eq(gid, current_fsgid()))
+ if (gid_eq(gid, file->f_cred->fsgid))
return true;
}
}
@@ -811,8 +813,10 @@
/* Allow the specified ids if we have the appropriate capability
* (CAP_SETUID or CAP_SETGID) over the parent user namespace.
+ * And the opener of the id file also had the approprpiate capability.
*/
- if (ns_capable(ns->parent, cap_setid))
+ if (ns_capable(ns->parent, cap_setid) &&
+ file_ns_capable(file, ns->parent, cap_setid))
return true;
return false;
diff --git a/lib/Kconfig b/lib/Kconfig
index 3958dc4..fe01d41 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -404,4 +404,7 @@
help
Enable fast lookup object identifier registry.
+config UCS2_STRING
+ tristate
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index d7946ff..6e2cc56 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -174,3 +174,5 @@
cmd_build_OID_registry = perl $(srctree)/$(src)/build_OID_registry $< $@
clean-files += oid_registry_data.c
+
+obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
diff --git a/lib/kobject.c b/lib/kobject.c
index e07ee1f..a654866 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -529,6 +529,13 @@
return kobj;
}
+static struct kobject *kobject_get_unless_zero(struct kobject *kobj)
+{
+ if (!kref_get_unless_zero(&kobj->kref))
+ kobj = NULL;
+ return kobj;
+}
+
/*
* kobject_cleanup - free kobject resources.
* @kobj: object to cleanup
@@ -751,7 +758,7 @@
list_for_each_entry(k, &kset->list, entry) {
if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
- ret = kobject_get(k);
+ ret = kobject_get_unless_zero(k);
break;
}
}
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index bfe02b8..d23762e 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -105,9 +105,9 @@
if (!strcmp(str, "force"))
swiotlb_force = 1;
- return 1;
+ return 0;
}
-__setup("swiotlb=", setup_io_tlb_npages);
+early_param("swiotlb", setup_io_tlb_npages);
/* make io_tlb_overflow tunable too? */
unsigned long swiotlb_nr_tbl(void)
@@ -115,6 +115,18 @@
return io_tlb_nslabs;
}
EXPORT_SYMBOL_GPL(swiotlb_nr_tbl);
+
+/* default to 64MB */
+#define IO_TLB_DEFAULT_SIZE (64UL<<20)
+unsigned long swiotlb_size_or_default(void)
+{
+ unsigned long size;
+
+ size = io_tlb_nslabs << IO_TLB_SHIFT;
+
+ return size ? size : (IO_TLB_DEFAULT_SIZE);
+}
+
/* Note that this doesn't work with highmem page */
static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
volatile void *address)
@@ -188,8 +200,7 @@
void __init
swiotlb_init(int verbose)
{
- /* default to 64MB */
- size_t default_size = 64UL<<20;
+ size_t default_size = IO_TLB_DEFAULT_SIZE;
unsigned char *vstart;
unsigned long bytes;
diff --git a/lib/ucs2_string.c b/lib/ucs2_string.c
new file mode 100644
index 0000000..6f500ef
--- /dev/null
+++ b/lib/ucs2_string.c
@@ -0,0 +1,51 @@
+#include <linux/ucs2_string.h>
+#include <linux/module.h>
+
+/* Return the number of unicode characters in data */
+unsigned long
+ucs2_strnlen(const ucs2_char_t *s, size_t maxlength)
+{
+ unsigned long length = 0;
+
+ while (*s++ != 0 && length < maxlength)
+ length++;
+ return length;
+}
+EXPORT_SYMBOL(ucs2_strnlen);
+
+unsigned long
+ucs2_strlen(const ucs2_char_t *s)
+{
+ return ucs2_strnlen(s, ~0UL);
+}
+EXPORT_SYMBOL(ucs2_strlen);
+
+/*
+ * Return the number of bytes is the length of this string
+ * Note: this is NOT the same as the number of unicode characters
+ */
+unsigned long
+ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
+{
+ return ucs2_strnlen(data, maxlength/sizeof(ucs2_char_t)) * sizeof(ucs2_char_t);
+}
+EXPORT_SYMBOL(ucs2_strsize);
+
+int
+ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
+{
+ while (1) {
+ if (len == 0)
+ return 0;
+ if (*a < *b)
+ return -1;
+ if (*a > *b)
+ return 1;
+ if (*a == 0) /* implies *b == 0 */
+ return 0;
+ a++;
+ b++;
+ len--;
+ }
+}
+EXPORT_SYMBOL(ucs2_strncmp);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ca9a7c6..1a12f5b 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2961,7 +2961,17 @@
break;
}
- if (absent ||
+ /*
+ * We need call hugetlb_fault for both hugepages under migration
+ * (in which case hugetlb_fault waits for the migration,) and
+ * hwpoisoned hugepages (in which case we need to prevent the
+ * caller from accessing to them.) In order to do this, we use
+ * here is_swap_pte instead of is_hugetlb_entry_migration and
+ * is_hugetlb_entry_hwpoisoned. This is because it simply covers
+ * both cases, and because we can't follow correct pages
+ * directly from any kind of swap entries.
+ */
+ if (absent || is_swap_pte(huge_ptep_get(pte)) ||
((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) {
int ret;
diff --git a/mm/memory.c b/mm/memory.c
index 494526a..ba94dec 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -216,6 +216,7 @@
tlb->mm = mm;
tlb->fullmm = fullmm;
+ tlb->need_flush_all = 0;
tlb->start = -1UL;
tlb->end = 0;
tlb->need_flush = 0;
@@ -2392,6 +2393,53 @@
}
EXPORT_SYMBOL(remap_pfn_range);
+/**
+ * vm_iomap_memory - remap memory to userspace
+ * @vma: user vma to map to
+ * @start: start of area
+ * @len: size of area
+ *
+ * This is a simplified io_remap_pfn_range() for common driver use. The
+ * driver just needs to give us the physical memory range to be mapped,
+ * we'll figure out the rest from the vma information.
+ *
+ * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get
+ * whatever write-combining details or similar.
+ */
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
+{
+ unsigned long vm_len, pfn, pages;
+
+ /* Check that the physical memory area passed in looks valid */
+ if (start + len < start)
+ return -EINVAL;
+ /*
+ * You *really* shouldn't map things that aren't page-aligned,
+ * but we've historically allowed it because IO memory might
+ * just have smaller alignment.
+ */
+ len += start & ~PAGE_MASK;
+ pfn = start >> PAGE_SHIFT;
+ pages = (len + ~PAGE_MASK) >> PAGE_SHIFT;
+ if (pfn + pages < pfn)
+ return -EINVAL;
+
+ /* We start the mapping 'vm_pgoff' pages into the area */
+ if (vma->vm_pgoff > pages)
+ return -EINVAL;
+ pfn += vma->vm_pgoff;
+ pages -= vma->vm_pgoff;
+
+ /* Can we fit all of the mapping? */
+ vm_len = vma->vm_end - vma->vm_start;
+ if (vm_len >> PAGE_SHIFT > pages)
+ return -EINVAL;
+
+ /* Ok, let it rip */
+ return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_iomap_memory);
+
static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
unsigned long addr, unsigned long end,
pte_fn_t fn, void *data)
diff --git a/mm/nommu.c b/mm/nommu.c
index 2f3ea74..e001768 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1838,6 +1838,16 @@
}
EXPORT_SYMBOL(remap_pfn_range);
+int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len)
+{
+ unsigned long pfn = start >> PAGE_SHIFT;
+ unsigned long vm_len = vma->vm_end - vma->vm_start;
+
+ pfn += vma->vm_pgoff;
+ return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot);
+}
+EXPORT_SYMBOL(vm_iomap_memory);
+
int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
unsigned long pgoff)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 88c5fed..669fba3 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3188,9 +3188,9 @@
if (IS_ERR(pgdat->kswapd)) {
/* failure at boot is fatal */
BUG_ON(system_state == SYSTEM_BOOTING);
- pgdat->kswapd = NULL;
pr_err("Failed to start kswapd on node %d\n", nid);
ret = PTR_ERR(pgdat->kswapd);
+ pgdat->kswapd = NULL;
}
return ret;
}
diff --git a/net/802/mrp.c b/net/802/mrp.c
index a4cc322..e085bcc 100644
--- a/net/802/mrp.c
+++ b/net/802/mrp.c
@@ -870,8 +870,12 @@
* all pending messages before the applicant is gone.
*/
del_timer_sync(&app->join_timer);
+
+ spin_lock(&app->lock);
mrp_mad_event(app, MRP_EVENT_TX);
mrp_pdu_queue(app);
+ spin_unlock(&app->lock);
+
mrp_queue_xmit(app);
dev_mc_del(dev, appl->group_address);
diff --git a/net/atm/common.c b/net/atm/common.c
index 7b49100..737bef5 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -531,6 +531,8 @@
struct sk_buff *skb;
int copied, error = -EINVAL;
+ msg->msg_namelen = 0;
+
if (sock->state != SS_CONNECTED)
return -ENOTCONN;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 7b11f8b..e277e38 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1642,6 +1642,7 @@
ax25_address src;
const unsigned char *mac = skb_mac_header(skb);
+ memset(sax, 0, sizeof(struct full_sockaddr_ax25));
ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
&digi, NULL, NULL);
sax->sax25_family = AF_AX25;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 0488d70..fa563e4 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -169,7 +169,7 @@
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
}
-int batadv_is_my_mac(const uint8_t *addr)
+int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr)
{
const struct batadv_hard_iface *hard_iface;
@@ -178,6 +178,9 @@
if (hard_iface->if_status != BATADV_IF_ACTIVE)
continue;
+ if (hard_iface->soft_iface != bat_priv->soft_iface)
+ continue;
+
if (batadv_compare_eth(hard_iface->net_dev->dev_addr, addr)) {
rcu_read_unlock();
return 1;
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index ced08b9..d40910d 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -162,7 +162,7 @@
int batadv_mesh_init(struct net_device *soft_iface);
void batadv_mesh_free(struct net_device *soft_iface);
-int batadv_is_my_mac(const uint8_t *addr);
+int batadv_is_my_mac(struct batadv_priv *bat_priv, const uint8_t *addr);
struct batadv_hard_iface *
batadv_seq_print_text_primary_if_get(struct seq_file *seq);
int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 5ee21ce..319f290 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -402,7 +402,7 @@
goto out;
/* not for me */
- if (!batadv_is_my_mac(ethhdr->h_dest))
+ if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
goto out;
icmp_packet = (struct batadv_icmp_packet_rr *)skb->data;
@@ -416,7 +416,7 @@
}
/* packet for me */
- if (batadv_is_my_mac(icmp_packet->dst))
+ if (batadv_is_my_mac(bat_priv, icmp_packet->dst))
return batadv_recv_my_icmp_packet(bat_priv, skb, hdr_size);
/* TTL exceeded */
@@ -548,7 +548,8 @@
return router;
}
-static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size)
+static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
+ struct sk_buff *skb, int hdr_size)
{
struct ethhdr *ethhdr;
@@ -567,7 +568,7 @@
return -1;
/* not for me */
- if (!batadv_is_my_mac(ethhdr->h_dest))
+ if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
return -1;
return 0;
@@ -582,7 +583,7 @@
char tt_flag;
size_t packet_size;
- if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+ if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;
/* I could need to modify it */
@@ -614,7 +615,7 @@
case BATADV_TT_RESPONSE:
batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_RX);
- if (batadv_is_my_mac(tt_query->dst)) {
+ if (batadv_is_my_mac(bat_priv, tt_query->dst)) {
/* packet needs to be linearized to access the TT
* changes
*/
@@ -657,14 +658,15 @@
struct batadv_roam_adv_packet *roam_adv_packet;
struct batadv_orig_node *orig_node;
- if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
+ if (batadv_check_unicast_packet(bat_priv, skb,
+ sizeof(*roam_adv_packet)) < 0)
goto out;
batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
roam_adv_packet = (struct batadv_roam_adv_packet *)skb->data;
- if (!batadv_is_my_mac(roam_adv_packet->dst))
+ if (!batadv_is_my_mac(bat_priv, roam_adv_packet->dst))
return batadv_route_unicast_packet(skb, recv_if);
/* check if it is a backbone gateway. we don't accept
@@ -967,7 +969,7 @@
* last time) the packet had an updated information or not
*/
curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
- if (!batadv_is_my_mac(unicast_packet->dest)) {
+ if (!batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
orig_node = batadv_orig_hash_find(bat_priv,
unicast_packet->dest);
/* if it is not possible to find the orig_node representing the
@@ -1044,14 +1046,14 @@
if (is4addr)
hdr_size = sizeof(*unicast_4addr_packet);
- if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+ if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;
if (!batadv_check_unicast_ttvn(bat_priv, skb))
return NET_RX_DROP;
/* packet for me */
- if (batadv_is_my_mac(unicast_packet->dest)) {
+ if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
if (is4addr) {
batadv_dat_inc_counter(bat_priv,
unicast_4addr_packet->subtype);
@@ -1088,7 +1090,7 @@
struct sk_buff *new_skb = NULL;
int ret;
- if (batadv_check_unicast_packet(skb, hdr_size) < 0)
+ if (batadv_check_unicast_packet(bat_priv, skb, hdr_size) < 0)
return NET_RX_DROP;
if (!batadv_check_unicast_ttvn(bat_priv, skb))
@@ -1097,7 +1099,7 @@
unicast_packet = (struct batadv_unicast_frag_packet *)skb->data;
/* packet for me */
- if (batadv_is_my_mac(unicast_packet->dest)) {
+ if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
ret = batadv_frag_reassemble_skb(skb, bat_priv, &new_skb);
if (ret == NET_RX_DROP)
@@ -1151,13 +1153,13 @@
goto out;
/* ignore broadcasts sent by myself */
- if (batadv_is_my_mac(ethhdr->h_source))
+ if (batadv_is_my_mac(bat_priv, ethhdr->h_source))
goto out;
bcast_packet = (struct batadv_bcast_packet *)skb->data;
/* ignore broadcasts originated by myself */
- if (batadv_is_my_mac(bcast_packet->orig))
+ if (batadv_is_my_mac(bat_priv, bcast_packet->orig))
goto out;
if (bcast_packet->header.ttl < 2)
@@ -1243,14 +1245,14 @@
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* not for me */
- if (!batadv_is_my_mac(ethhdr->h_dest))
+ if (!batadv_is_my_mac(bat_priv, ethhdr->h_dest))
return NET_RX_DROP;
/* ignore own packets */
- if (batadv_is_my_mac(vis_packet->vis_orig))
+ if (batadv_is_my_mac(bat_priv, vis_packet->vis_orig))
return NET_RX_DROP;
- if (batadv_is_my_mac(vis_packet->sender_orig))
+ if (batadv_is_my_mac(bat_priv, vis_packet->sender_orig))
return NET_RX_DROP;
switch (vis_packet->vis_type) {
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 98a66a0..7abee19 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -1953,7 +1953,7 @@
bool batadv_send_tt_response(struct batadv_priv *bat_priv,
struct batadv_tt_query_packet *tt_request)
{
- if (batadv_is_my_mac(tt_request->dst)) {
+ if (batadv_is_my_mac(bat_priv, tt_request->dst)) {
/* don't answer backbone gws! */
if (batadv_bla_is_backbone_gw_orig(bat_priv, tt_request->src))
return true;
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c
index c053244..6a1e646 100644
--- a/net/batman-adv/vis.c
+++ b/net/batman-adv/vis.c
@@ -477,7 +477,7 @@
/* Are we the target for this VIS packet? */
if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC &&
- batadv_is_my_mac(vis_packet->target_orig))
+ batadv_is_my_mac(bat_priv, vis_packet->target_orig))
are_target = 1;
spin_lock_bh(&bat_priv->vis.hash_lock);
@@ -496,7 +496,7 @@
batadv_send_list_add(bat_priv, info);
/* ... we're not the recipient (and thus need to forward). */
- } else if (!batadv_is_my_mac(packet->target_orig)) {
+ } else if (!batadv_is_my_mac(bat_priv, packet->target_orig)) {
batadv_send_list_add(bat_priv, info);
}
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index d3ee69b..0d1b08c 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -230,6 +230,8 @@
if (flags & (MSG_OOB))
return -EOPNOTSUPP;
+ msg->msg_namelen = 0;
+
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb) {
if (sk->sk_shutdown & RCV_SHUTDOWN)
@@ -237,8 +239,6 @@
return err;
}
- msg->msg_namelen = 0;
-
copied = skb->len;
if (len < copied) {
msg->msg_flags |= MSG_TRUNC;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index c23bae8..7c9224b 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -608,6 +608,7 @@
if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
rfcomm_dlc_accept(d);
+ msg->msg_namelen = 0;
return 0;
}
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index fad0302..fb6192c 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -665,6 +665,7 @@
test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
hci_conn_accept(pi->conn->hcon, 0);
sk->sk_state = BT_CONFIG;
+ msg->msg_namelen = 0;
release_sock(sk);
return 0;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index ef1b914..459dab2 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -67,7 +67,8 @@
struct net_device *dev = p->dev;
struct net_bridge *br = p->br;
- if (netif_running(dev) && netif_oper_up(dev))
+ if (!(p->flags & BR_ADMIN_COST) &&
+ netif_running(dev) && netif_oper_up(dev))
p->path_cost = port_cost(dev);
if (!netif_running(br->dev))
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 3cbf5be..d2c043a 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -156,6 +156,7 @@
#define BR_BPDU_GUARD 0x00000002
#define BR_ROOT_BLOCK 0x00000004
#define BR_MULTICAST_FAST_LEAVE 0x00000008
+#define BR_ADMIN_COST 0x00000010
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
u32 multicast_startup_queries_sent;
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index 0bdb4eb..d45e760 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -288,6 +288,7 @@
path_cost > BR_MAX_PATH_COST)
return -ERANGE;
+ p->flags |= BR_ADMIN_COST;
p->path_cost = path_cost;
br_configuration_update(p->br);
br_port_state_selection(p->br);
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 095259f..ff2ff3c 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -286,6 +286,8 @@
if (m->msg_flags&MSG_OOB)
goto read_error;
+ m->msg_namelen = 0;
+
skb = skb_recv_datagram(sk, flags, 0 , &ret);
if (!skb)
goto read_error;
diff --git a/net/can/gw.c b/net/can/gw.c
index 2d117dc..117814a 100644
--- a/net/can/gw.c
+++ b/net/can/gw.c
@@ -466,7 +466,7 @@
if (gwj->src.dev == dev || gwj->dst.dev == dev) {
hlist_del(&gwj->list);
cgw_unregister_filter(gwj);
- kfree(gwj);
+ kmem_cache_free(cgw_cache, gwj);
}
}
}
@@ -864,7 +864,7 @@
hlist_for_each_entry_safe(gwj, nx, &cgw_list, list) {
hlist_del(&gwj->list);
cgw_unregister_filter(gwj);
- kfree(gwj);
+ kmem_cache_free(cgw_cache, gwj);
}
}
@@ -920,7 +920,7 @@
hlist_del(&gwj->list);
cgw_unregister_filter(gwj);
- kfree(gwj);
+ kmem_cache_free(cgw_cache, gwj);
err = 0;
break;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index e7d68ed..b24ab0e9 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2148,6 +2148,9 @@
struct net_device *dev = skb->dev;
const char *driver = "";
+ if (!net_ratelimit())
+ return;
+
if (dev && dev->dev.parent)
driver = dev_driver_string(dev->dev.parent);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index b65441d..23854b5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1072,7 +1072,7 @@
rcu_read_lock();
cb->seq = net->dev_base_seq;
- if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+ if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
ifla_policy) >= 0) {
if (tb[IFLA_EXT_MASK])
@@ -1922,7 +1922,7 @@
u32 ext_filter_mask = 0;
u16 min_ifinfo_dump_size = 0;
- if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX,
+ if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX,
ifla_policy) >= 0) {
if (tb[IFLA_EXT_MASK])
ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 96083b7..c6287cd 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -587,13 +587,16 @@
{
unsigned long now, next, next_sec, next_sched;
struct in_ifaddr *ifa;
+ struct hlist_node *n;
int i;
now = jiffies;
next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY);
- rcu_read_lock();
for (i = 0; i < IN4_ADDR_HSIZE; i++) {
+ bool change_needed = false;
+
+ rcu_read_lock();
hlist_for_each_entry_rcu(ifa, &inet_addr_lst[i], hash) {
unsigned long age;
@@ -606,16 +609,7 @@
if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
age >= ifa->ifa_valid_lft) {
- struct in_ifaddr **ifap ;
-
- rtnl_lock();
- for (ifap = &ifa->ifa_dev->ifa_list;
- *ifap != NULL; ifap = &ifa->ifa_next) {
- if (*ifap == ifa)
- inet_del_ifa(ifa->ifa_dev,
- ifap, 1);
- }
- rtnl_unlock();
+ change_needed = true;
} else if (ifa->ifa_preferred_lft ==
INFINITY_LIFE_TIME) {
continue;
@@ -625,10 +619,8 @@
next = ifa->ifa_tstamp +
ifa->ifa_valid_lft * HZ;
- if (!(ifa->ifa_flags & IFA_F_DEPRECATED)) {
- ifa->ifa_flags |= IFA_F_DEPRECATED;
- rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
- }
+ if (!(ifa->ifa_flags & IFA_F_DEPRECATED))
+ change_needed = true;
} else if (time_before(ifa->ifa_tstamp +
ifa->ifa_preferred_lft * HZ,
next)) {
@@ -636,8 +628,42 @@
ifa->ifa_preferred_lft * HZ;
}
}
+ rcu_read_unlock();
+ if (!change_needed)
+ continue;
+ rtnl_lock();
+ hlist_for_each_entry_safe(ifa, n, &inet_addr_lst[i], hash) {
+ unsigned long age;
+
+ if (ifa->ifa_flags & IFA_F_PERMANENT)
+ continue;
+
+ /* We try to batch several events at once. */
+ age = (now - ifa->ifa_tstamp +
+ ADDRCONF_TIMER_FUZZ_MINUS) / HZ;
+
+ if (ifa->ifa_valid_lft != INFINITY_LIFE_TIME &&
+ age >= ifa->ifa_valid_lft) {
+ struct in_ifaddr **ifap;
+
+ for (ifap = &ifa->ifa_dev->ifa_list;
+ *ifap != NULL; ifap = &(*ifap)->ifa_next) {
+ if (*ifap == ifa) {
+ inet_del_ifa(ifa->ifa_dev,
+ ifap, 1);
+ break;
+ }
+ }
+ } else if (ifa->ifa_preferred_lft !=
+ INFINITY_LIFE_TIME &&
+ age >= ifa->ifa_preferred_lft &&
+ !(ifa->ifa_flags & IFA_F_DEPRECATED)) {
+ ifa->ifa_flags |= IFA_F_DEPRECATED;
+ rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
+ }
+ }
+ rtnl_unlock();
}
- rcu_read_unlock();
next_sec = round_jiffies_up(next);
next_sched = next;
@@ -804,6 +830,8 @@
return -EEXIST;
ifa = ifa_existing;
set_ifa_lifetime(ifa, valid_lft, prefered_lft);
+ cancel_delayed_work(&check_lifetime_work);
+ schedule_delayed_work(&check_lifetime_work, 0);
rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
}
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 3b4f0cd..4cfe34d 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -139,8 +139,6 @@
/* skb is pure payload to encrypt */
- err = -ENOMEM;
-
esp = x->data;
aead = esp->aead;
alen = crypto_aead_authsize(aead);
@@ -176,8 +174,10 @@
}
tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
- if (!tmp)
+ if (!tmp) {
+ err = -ENOMEM;
goto error;
+ }
seqhi = esp_tmp_seqhi(tmp);
iv = esp_tmp_iv(aead, tmp, seqhilen);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a6445b8..52c273e 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -248,8 +248,7 @@
if (!head->dev)
goto out_rcu_unlock;
- /* skb dst is stale, drop it, and perform route lookup again */
- skb_dst_drop(head);
+ /* skb has no dst, perform route lookup again */
iph = ip_hdr(head);
err = ip_route_input_noref(head, iph->daddr, iph->saddr,
iph->tos, head->dev);
@@ -523,9 +522,16 @@
qp->q.max_size = skb->len + ihl;
if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
- qp->q.meat == qp->q.len)
- return ip_frag_reasm(qp, prev, dev);
+ qp->q.meat == qp->q.len) {
+ unsigned long orefdst = skb->_skb_refdst;
+ skb->_skb_refdst = 0UL;
+ err = ip_frag_reasm(qp, prev, dev);
+ skb->_skb_refdst = orefdst;
+ return err;
+ }
+
+ skb_dst_drop(skb);
inet_frag_lru_move(&qp->q);
return -EINPROGRESS;
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
index c301300..c49dcd0 100644
--- a/net/ipv4/netfilter/ipt_rpfilter.c
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -66,6 +66,12 @@
return dev_match;
}
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+ const struct rtable *rt = skb_rtable(skb);
+ return rt && (rt->rt_flags & RTCF_LOCAL);
+}
+
static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_rpfilter_info *info;
@@ -76,7 +82,7 @@
info = par->matchinfo;
invert = info->flags & XT_RPFILTER_INVERT;
- if (par->in->flags & IFF_LOOPBACK)
+ if (rpfilter_is_local(skb))
return true ^ invert;
iph = ip_hdr(skb);
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index ef54377..397e0f6 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -349,8 +349,8 @@
* hasn't changed since we received the original syn, but I see
* no easy way to do this.
*/
- flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
- RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+ flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark,
+ RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP,
inet_sk_flowi_flags(sk),
(opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
ireq->loc_addr, th->source, th->dest);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3bd55ba..13b9c08 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -113,6 +113,7 @@
#define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */
#define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */
#define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */
+#define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */
#define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
#define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
@@ -3564,6 +3565,27 @@
}
}
+static void tcp_store_ts_recent(struct tcp_sock *tp)
+{
+ tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
+ tp->rx_opt.ts_recent_stamp = get_seconds();
+}
+
+static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
+{
+ if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
+ /* PAWS bug workaround wrt. ACK frames, the PAWS discard
+ * extra check below makes sure this can only happen
+ * for pure ACK frames. -DaveM
+ *
+ * Not only, also it occurs for expired timestamps.
+ */
+
+ if (tcp_paws_check(&tp->rx_opt, 0))
+ tcp_store_ts_recent(tp);
+ }
+}
+
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
@@ -3607,6 +3629,12 @@
prior_fackets = tp->fackets_out;
prior_in_flight = tcp_packets_in_flight(tp);
+ /* ts_recent update must be made after we are sure that the packet
+ * is in window.
+ */
+ if (flag & FLAG_UPDATE_TS_RECENT)
+ tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
/* Window is constant, pure forward advance.
* No more checks are required.
@@ -3927,27 +3955,6 @@
EXPORT_SYMBOL(tcp_parse_md5sig_option);
#endif
-static inline void tcp_store_ts_recent(struct tcp_sock *tp)
-{
- tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval;
- tp->rx_opt.ts_recent_stamp = get_seconds();
-}
-
-static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq)
-{
- if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) {
- /* PAWS bug workaround wrt. ACK frames, the PAWS discard
- * extra check below makes sure this can only happen
- * for pure ACK frames. -DaveM
- *
- * Not only, also it occurs for expired timestamps.
- */
-
- if (tcp_paws_check(&tp->rx_opt, 0))
- tcp_store_ts_recent(tp);
- }
-}
-
/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM
*
* It is not fatal. If this ACK does _not_ change critical state (seqs, window)
@@ -5543,14 +5550,9 @@
return 0;
step5:
- if (tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
+ if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
goto discard;
- /* ts_recent update must be made after we are sure that the packet
- * is in window.
- */
- tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
tcp_rcv_rtt_measure_ts(sk, skb);
/* Process urgent data. */
@@ -5986,7 +5988,8 @@
/* step 5: check the ACK field */
if (true) {
- int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0;
+ int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
+ FLAG_UPDATE_TS_RECENT) > 0;
switch (sk->sk_state) {
case TCP_SYN_RECV:
@@ -6137,11 +6140,6 @@
}
}
- /* ts_recent update must be made after we are sure that the packet
- * is in window.
- */
- tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
/* step 6: check the URG bit */
tcp_urg(sk, skb, th);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5d0b438..509912a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2388,8 +2388,12 @@
*/
TCP_SKB_CB(skb)->when = tcp_time_stamp;
- /* make sure skb->data is aligned on arches that require it */
- if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) {
+ /* make sure skb->data is aligned on arches that require it
+ * and check if ack-trimming & collapsing extended the headroom
+ * beyond what csum_start can cover.
+ */
+ if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) ||
+ skb_headroom(skb) >= 0xFFFF)) {
struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER,
GFP_ATOMIC);
return nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
@@ -2709,6 +2713,7 @@
skb_reserve(skb, MAX_TCP_HEADER);
skb_dst_set(skb, dst);
+ security_skb_owned_by(skb, sk);
mss = dst_metric_advmss(dst);
if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a459c4f..dae802c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -168,8 +168,6 @@
static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
struct net_device *dev);
-static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
-
static struct ipv6_devconf ipv6_devconf __read_mostly = {
.forwarding = 0,
.hop_limit = IPV6_DEFAULT_HOPLIMIT,
@@ -837,7 +835,7 @@
rcu_read_unlock_bh();
if (likely(err == 0))
- atomic_notifier_call_chain(&inet6addr_chain, NETDEV_UP, ifa);
+ inet6addr_notifier_call_chain(NETDEV_UP, ifa);
else {
kfree(ifa);
ifa = ERR_PTR(err);
@@ -927,7 +925,7 @@
ipv6_ifa_notify(RTM_DELADDR, ifp);
- atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifp);
+ inet6addr_notifier_call_chain(NETDEV_DOWN, ifp);
/*
* Purge or update corresponding prefix
@@ -2988,7 +2986,7 @@
if (state != INET6_IFADDR_STATE_DEAD) {
__ipv6_ifa_notify(RTM_DELADDR, ifa);
- atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa);
+ inet6addr_notifier_call_chain(NETDEV_DOWN, ifa);
}
in6_ifa_put(ifa);
@@ -4869,22 +4867,6 @@
.exit = addrconf_exit_net,
};
-/*
- * Device notifier
- */
-
-int register_inet6addr_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&inet6addr_chain, nb);
-}
-EXPORT_SYMBOL(register_inet6addr_notifier);
-
-int unregister_inet6addr_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
-}
-EXPORT_SYMBOL(unregister_inet6addr_notifier);
-
static struct rtnl_af_ops inet6_ops = {
.family = AF_INET6,
.fill_link_af = inet6_fill_link_af,
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c
index d051e5f..7210456 100644
--- a/net/ipv6/addrconf_core.c
+++ b/net/ipv6/addrconf_core.c
@@ -78,3 +78,22 @@
}
EXPORT_SYMBOL(__ipv6_addr_type);
+static ATOMIC_NOTIFIER_HEAD(inet6addr_chain);
+
+int register_inet6addr_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&inet6addr_chain, nb);
+}
+EXPORT_SYMBOL(register_inet6addr_notifier);
+
+int unregister_inet6addr_notifier(struct notifier_block *nb)
+{
+ return atomic_notifier_chain_unregister(&inet6addr_chain, nb);
+}
+EXPORT_SYMBOL(unregister_inet6addr_notifier);
+
+int inet6addr_notifier_call_chain(unsigned long val, void *v)
+{
+ return atomic_notifier_call_chain(&inet6addr_chain, val, v);
+}
+EXPORT_SYMBOL(inet6addr_notifier_call_chain);
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
index 5060d54..e0983f3 100644
--- a/net/ipv6/netfilter/ip6t_rpfilter.c
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -71,6 +71,12 @@
return ret;
}
+static bool rpfilter_is_local(const struct sk_buff *skb)
+{
+ const struct rt6_info *rt = (const void *) skb_dst(skb);
+ return rt && (rt->rt6i_flags & RTF_LOCAL);
+}
+
static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
{
const struct xt_rpfilter_info *info = par->matchinfo;
@@ -78,7 +84,7 @@
struct ipv6hdr *iph;
bool invert = info->flags & XT_RPFILTER_INVERT;
- if (par->in->flags & IFF_LOOPBACK)
+ if (rpfilter_is_local(skb))
return true ^ invert;
iph = ipv6_hdr(skb);
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 196ab93..0ba10e5 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -330,9 +330,17 @@
}
if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
- fq->q.meat == fq->q.len)
- return ip6_frag_reasm(fq, prev, dev);
+ fq->q.meat == fq->q.len) {
+ int res;
+ unsigned long orefdst = skb->_skb_refdst;
+ skb->_skb_refdst = 0UL;
+ res = ip6_frag_reasm(fq, prev, dev);
+ skb->_skb_refdst = orefdst;
+ return res;
+ }
+
+ skb_dst_drop(skb);
inet_frag_lru_move(&fq->q);
return -1;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f6d629f..46a5be8 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -386,6 +386,7 @@
if (dst)
dst->ops->redirect(dst, sk, skb);
+ goto out;
}
if (type == ICMPV6_PKT_TOOBIG) {
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index d28e7f0..e493b33 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -1386,6 +1386,8 @@
IRDA_DEBUG(4, "%s()\n", __func__);
+ msg->msg_namelen = 0;
+
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
if (!skb)
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
index 29340a9..e1b37f5 100644
--- a/net/irda/iriap.c
+++ b/net/irda/iriap.c
@@ -303,7 +303,8 @@
{
struct iriap_cb *self;
- IRDA_DEBUG(4, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+ IRDA_DEBUG(4, "%s(), reason=%s [%d]\n", __func__,
+ irlmp_reason_str(reason), reason);
self = instance;
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c
index 6115a44..1064621 100644
--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -66,8 +66,15 @@
"LM_LAP_RESET",
"LM_INIT_DISCONNECT",
"ERROR, NOT USED",
+ "UNKNOWN",
};
+const char *irlmp_reason_str(LM_REASON reason)
+{
+ reason = min_t(size_t, reason, ARRAY_SIZE(irlmp_reasons) - 1);
+ return irlmp_reasons[reason];
+}
+
/*
* Function irlmp_init (void)
*
@@ -747,7 +754,8 @@
{
struct lsap_cb *lsap;
- IRDA_DEBUG(1, "%s(), reason=%s\n", __func__, irlmp_reasons[reason]);
+ IRDA_DEBUG(1, "%s(), reason=%s [%d]\n", __func__,
+ irlmp_reason_str(reason), reason);
IRDA_ASSERT(self != NULL, return;);
IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index a7d11ffe..206ce6d 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -49,12 +49,6 @@
#define TRGCLS_SIZE (sizeof(((struct iucv_message *)0)->class))
-/* macros to set/get socket control buffer at correct offset */
-#define CB_TAG(skb) ((skb)->cb) /* iucv message tag */
-#define CB_TAG_LEN (sizeof(((struct iucv_message *) 0)->tag))
-#define CB_TRGCLS(skb) ((skb)->cb + CB_TAG_LEN) /* iucv msg target class */
-#define CB_TRGCLS_LEN (TRGCLS_SIZE)
-
#define __iucv_sock_wait(sk, condition, timeo, ret) \
do { \
DEFINE_WAIT(__wait); \
@@ -1141,7 +1135,7 @@
/* increment and save iucv message tag for msg_completion cbk */
txmsg.tag = iucv->send_tag++;
- memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN);
+ IUCV_SKB_CB(skb)->tag = txmsg.tag;
if (iucv->transport == AF_IUCV_TRANS_HIPER) {
atomic_inc(&iucv->msg_sent);
@@ -1224,7 +1218,7 @@
return -ENOMEM;
/* copy target class to control buffer of new skb */
- memcpy(CB_TRGCLS(nskb), CB_TRGCLS(skb), CB_TRGCLS_LEN);
+ IUCV_SKB_CB(nskb)->class = IUCV_SKB_CB(skb)->class;
/* copy data fragment */
memcpy(nskb->data, skb->data + copied, size);
@@ -1256,7 +1250,7 @@
/* store msg target class in the second 4 bytes of skb ctrl buffer */
/* Note: the first 4 bytes are reserved for msg tag */
- memcpy(CB_TRGCLS(skb), &msg->class, CB_TRGCLS_LEN);
+ IUCV_SKB_CB(skb)->class = msg->class;
/* check for special IPRM messages (e.g. iucv_sock_shutdown) */
if ((msg->flags & IUCV_IPRMDATA) && len > 7) {
@@ -1292,6 +1286,7 @@
}
}
+ IUCV_SKB_CB(skb)->offset = 0;
if (sock_queue_rcv_skb(sk, skb))
skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
}
@@ -1327,6 +1322,9 @@
unsigned int copied, rlen;
struct sk_buff *skb, *rskb, *cskb;
int err = 0;
+ u32 offset;
+
+ msg->msg_namelen = 0;
if ((sk->sk_state == IUCV_DISCONN) &&
skb_queue_empty(&iucv->backlog_skb_q) &&
@@ -1346,13 +1344,14 @@
return err;
}
- rlen = skb->len; /* real length of skb */
+ offset = IUCV_SKB_CB(skb)->offset;
+ rlen = skb->len - offset; /* real length of skb */
copied = min_t(unsigned int, rlen, len);
if (!rlen)
sk->sk_shutdown = sk->sk_shutdown | RCV_SHUTDOWN;
cskb = skb;
- if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
+ if (skb_copy_datagram_iovec(cskb, offset, msg->msg_iov, copied)) {
if (!(flags & MSG_PEEK))
skb_queue_head(&sk->sk_receive_queue, skb);
return -EFAULT;
@@ -1370,7 +1369,8 @@
* get the trgcls from the control buffer of the skb due to
* fragmentation of original iucv message. */
err = put_cmsg(msg, SOL_IUCV, SCM_IUCV_TRGCLS,
- CB_TRGCLS_LEN, CB_TRGCLS(skb));
+ sizeof(IUCV_SKB_CB(skb)->class),
+ (void *)&IUCV_SKB_CB(skb)->class);
if (err) {
if (!(flags & MSG_PEEK))
skb_queue_head(&sk->sk_receive_queue, skb);
@@ -1382,9 +1382,8 @@
/* SOCK_STREAM: re-queue skb if it contains unreceived data */
if (sk->sk_type == SOCK_STREAM) {
- skb_pull(skb, copied);
- if (skb->len) {
- skb_queue_head(&sk->sk_receive_queue, skb);
+ if (copied < rlen) {
+ IUCV_SKB_CB(skb)->offset = offset + copied;
goto done;
}
}
@@ -1403,6 +1402,7 @@
spin_lock_bh(&iucv->message_q.lock);
rskb = skb_dequeue(&iucv->backlog_skb_q);
while (rskb) {
+ IUCV_SKB_CB(rskb)->offset = 0;
if (sock_queue_rcv_skb(sk, rskb)) {
skb_queue_head(&iucv->backlog_skb_q,
rskb);
@@ -1830,7 +1830,7 @@
spin_lock_irqsave(&list->lock, flags);
while (list_skb != (struct sk_buff *)list) {
- if (!memcmp(&msg->tag, CB_TAG(list_skb), CB_TAG_LEN)) {
+ if (msg->tag != IUCV_SKB_CB(list_skb)->tag) {
this = list_skb;
break;
}
@@ -2091,6 +2091,7 @@
skb_pull(skb, sizeof(struct af_iucv_trans_hdr));
skb_reset_transport_header(skb);
skb_reset_network_header(skb);
+ IUCV_SKB_CB(skb)->offset = 0;
spin_lock(&iucv->message_q.lock);
if (skb_queue_empty(&iucv->backlog_skb_q)) {
if (sock_queue_rcv_skb(sk, skb)) {
@@ -2195,8 +2196,7 @@
/* fall through and receive zero length data */
case 0:
/* plain data frame */
- memcpy(CB_TRGCLS(skb), &trans_hdr->iucv_hdr.class,
- CB_TRGCLS_LEN);
+ IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class;
err = afiucv_hs_callback_rx(sk, skb);
break;
default:
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index c74f5a9..b8a6039 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -690,6 +690,7 @@
lsa->l2tp_addr = ipv6_hdr(skb)->saddr;
lsa->l2tp_flowinfo = 0;
lsa->l2tp_scope_id = 0;
+ lsa->l2tp_conn_id = 0;
if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL)
lsa->l2tp_scope_id = IP6CB(skb)->iif;
}
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 8870988..48aaa89 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -720,6 +720,8 @@
int target; /* Read at least this many bytes */
long timeo;
+ msg->msg_namelen = 0;
+
lock_sock(sk);
copied = -ENOTCONN;
if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 58150f8..9ed49ad 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -78,7 +78,7 @@
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
}
-u32 ieee80211_idle_off(struct ieee80211_local *local)
+static u32 __ieee80211_idle_off(struct ieee80211_local *local)
{
if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
return 0;
@@ -87,7 +87,7 @@
return IEEE80211_CONF_CHANGE_IDLE;
}
-static u32 ieee80211_idle_on(struct ieee80211_local *local)
+static u32 __ieee80211_idle_on(struct ieee80211_local *local)
{
if (local->hw.conf.flags & IEEE80211_CONF_IDLE)
return 0;
@@ -98,16 +98,18 @@
return IEEE80211_CONF_CHANGE_IDLE;
}
-void ieee80211_recalc_idle(struct ieee80211_local *local)
+static u32 __ieee80211_recalc_idle(struct ieee80211_local *local,
+ bool force_active)
{
bool working = false, scanning, active;
unsigned int led_trig_start = 0, led_trig_stop = 0;
struct ieee80211_roc_work *roc;
- u32 change;
lockdep_assert_held(&local->mtx);
- active = !list_empty(&local->chanctx_list) || local->monitors;
+ active = force_active ||
+ !list_empty(&local->chanctx_list) ||
+ local->monitors;
if (!local->ops->remain_on_channel) {
list_for_each_entry(roc, &local->roc_list, list) {
@@ -132,9 +134,18 @@
ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
if (working || scanning || active)
- change = ieee80211_idle_off(local);
- else
- change = ieee80211_idle_on(local);
+ return __ieee80211_idle_off(local);
+ return __ieee80211_idle_on(local);
+}
+
+u32 ieee80211_idle_off(struct ieee80211_local *local)
+{
+ return __ieee80211_recalc_idle(local, true);
+}
+
+void ieee80211_recalc_idle(struct ieee80211_local *local)
+{
+ u32 change = __ieee80211_recalc_idle(local, false);
if (change)
ieee80211_hw_config(local, change);
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 82cc303..346ad4c 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3964,8 +3964,16 @@
/* prep auth_data so we don't go into idle on disassoc */
ifmgd->auth_data = auth_data;
- if (ifmgd->associated)
- ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+ if (ifmgd->associated) {
+ u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_UNSPECIFIED,
+ false, frame_buf);
+
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
+ }
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4025,8 +4033,16 @@
mutex_lock(&ifmgd->mtx);
- if (ifmgd->associated)
- ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+ if (ifmgd->associated) {
+ u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+
+ ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
+ WLAN_REASON_UNSPECIFIED,
+ false, frame_buf);
+
+ __cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
+ }
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
err = -EBUSY;
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index 0f92dc2..d7df6ac 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -339,7 +339,11 @@
nla_put_failure:
nla_nest_cancel(skb, nested);
ipset_nest_end(skb, atd);
- return -EMSGSIZE;
+ if (unlikely(id == first)) {
+ cb->args[2] = 0;
+ return -EMSGSIZE;
+ }
+ return 0;
}
static int
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index f262722..10a30b4 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -104,6 +104,15 @@
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
+static inline void
+hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
+}
+
static inline int
hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
{
@@ -414,6 +423,15 @@
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
+static inline void
+hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
+}
+
static inline int
hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
{
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 4b677cf..d6a5915 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -87,7 +87,16 @@
static inline void
hash_net4_data_flags(struct hash_net4_elem *dst, u32 flags)
{
- dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+ dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_net4_data_reset_flags(struct hash_net4_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
}
static inline int
@@ -308,7 +317,16 @@
static inline void
hash_net6_data_flags(struct hash_net6_elem *dst, u32 flags)
{
- dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+ dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_net6_data_reset_flags(struct hash_net6_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
}
static inline int
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 6ba985f..f2b0a3c 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -198,7 +198,16 @@
static inline void
hash_netiface4_data_flags(struct hash_netiface4_elem *dst, u32 flags)
{
- dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+ dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
+}
+
+static inline void
+hash_netiface4_data_reset_flags(struct hash_netiface4_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
}
static inline int
@@ -494,7 +503,7 @@
static inline void
hash_netiface6_data_flags(struct hash_netiface6_elem *dst, u32 flags)
{
- dst->nomatch = flags & IPSET_FLAG_NOMATCH;
+ dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
static inline int
@@ -504,6 +513,15 @@
}
static inline void
+hash_netiface6_data_reset_flags(struct hash_netiface6_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
+}
+
+static inline void
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
{
elem->elem = 0;
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index af20c0c..349deb6 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -104,6 +104,15 @@
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
+static inline void
+hash_netport4_data_reset_flags(struct hash_netport4_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
+}
+
static inline int
hash_netport4_data_match(const struct hash_netport4_elem *elem)
{
@@ -375,6 +384,15 @@
dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
}
+static inline void
+hash_netport6_data_reset_flags(struct hash_netport6_elem *dst, u32 *flags)
+{
+ if (dst->nomatch) {
+ *flags = IPSET_FLAG_NOMATCH;
+ dst->nomatch = 0;
+ }
+}
+
static inline int
hash_netport6_data_match(const struct hash_netport6_elem *elem)
{
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 8371c2b..09c744a 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -174,9 +174,13 @@
{
const struct set_elem *e = list_set_elem(map, i);
- if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
- /* Last element replaced: e.g. add new,before,last */
- ip_set_put_byindex(e->id);
+ if (e->id != IPSET_INVALID_ID) {
+ const struct set_elem *x = list_set_elem(map, map->size - 1);
+
+ /* Last element replaced or pushed off */
+ if (x->id != IPSET_INVALID_ID)
+ ip_set_put_byindex(x->id);
+ }
if (with_timeout(map->timeout))
list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
else
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 0e7d423..e0c4373 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -1593,10 +1593,8 @@
end += strlen("\r\n\r\n") + clen;
msglen = origlen = end - dptr;
- if (msglen > datalen) {
- nf_ct_helper_log(skb, ct, "incomplete/bad SIP message");
- return NF_DROP;
- }
+ if (msglen > datalen)
+ return NF_ACCEPT;
ret = process_sip_msg(skb, ct, protoff, dataoff,
&dptr, &msglen);
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 8d5769c..ad24be0 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -467,33 +467,22 @@
struct nf_nat_proto_clean {
u8 l3proto;
u8 l4proto;
- bool hash;
};
-/* Clear NAT section of all conntracks, in case we're loaded again. */
-static int nf_nat_proto_clean(struct nf_conn *i, void *data)
+/* kill conntracks with affected NAT section */
+static int nf_nat_proto_remove(struct nf_conn *i, void *data)
{
const struct nf_nat_proto_clean *clean = data;
struct nf_conn_nat *nat = nfct_nat(i);
if (!nat)
return 0;
- if (!(i->status & IPS_SRC_NAT_DONE))
- return 0;
+
if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) ||
(clean->l4proto && nf_ct_protonum(i) != clean->l4proto))
return 0;
- if (clean->hash) {
- spin_lock_bh(&nf_nat_lock);
- hlist_del_rcu(&nat->bysource);
- spin_unlock_bh(&nf_nat_lock);
- } else {
- memset(nat, 0, sizeof(*nat));
- i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK |
- IPS_SEQ_ADJUST);
- }
- return 0;
+ return i->status & IPS_NAT_MASK ? 1 : 0;
}
static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
@@ -505,16 +494,8 @@
struct net *net;
rtnl_lock();
- /* Step 1 - remove from bysource hash */
- clean.hash = true;
for_each_net(net)
- nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
- synchronize_rcu();
-
- /* Step 2 - clean NAT section */
- clean.hash = false;
- for_each_net(net)
- nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+ nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
rtnl_unlock();
}
@@ -526,16 +507,9 @@
struct net *net;
rtnl_lock();
- /* Step 1 - remove from bysource hash */
- clean.hash = true;
- for_each_net(net)
- nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
- synchronize_rcu();
- /* Step 2 - clean NAT section */
- clean.hash = false;
for_each_net(net)
- nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
+ nf_ct_iterate_cleanup(net, nf_nat_proto_remove, &clean);
rtnl_unlock();
}
@@ -773,7 +747,7 @@
{
struct nf_nat_proto_clean clean = {};
- nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean);
+ nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
synchronize_rcu();
nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
}
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index d1fa1d9..103bd70 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1173,6 +1173,7 @@
}
if (sax != NULL) {
+ memset(sax, 0, sizeof(*sax));
sax->sax25_family = AF_NETROM;
skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
AX25_ADDR_LEN);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index 8f02574..6c94447 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -646,6 +646,8 @@
pr_debug("%p %zu\n", sk, len);
+ msg->msg_namelen = 0;
+
lock_sock(sk);
if (sk->sk_state == LLCP_CLOSED &&
@@ -691,6 +693,7 @@
pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap);
+ memset(sockaddr, 0, sizeof(*sockaddr));
sockaddr->sa_family = AF_NFC;
sockaddr->nfc_protocol = NFC_PROTO_NFC_DEP;
sockaddr->dsap = ui_cb->dsap;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index a4b7247..6980c3e6 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1593,10 +1593,8 @@
return ERR_PTR(-ENOMEM);
retval = ovs_vport_cmd_fill_info(vport, skb, portid, seq, 0, cmd);
- if (retval < 0) {
- kfree_skb(skb);
- return ERR_PTR(retval);
- }
+ BUG_ON(retval < 0);
+
return skb;
}
@@ -1726,24 +1724,32 @@
nla_get_u32(a[OVS_VPORT_ATTR_TYPE]) != vport->ops->type)
err = -EINVAL;
+ reply = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!reply) {
+ err = -ENOMEM;
+ goto exit_unlock;
+ }
+
if (!err && a[OVS_VPORT_ATTR_OPTIONS])
err = ovs_vport_set_options(vport, a[OVS_VPORT_ATTR_OPTIONS]);
if (err)
- goto exit_unlock;
+ goto exit_free;
+
if (a[OVS_VPORT_ATTR_UPCALL_PID])
vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]);
- reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq,
- OVS_VPORT_CMD_NEW);
- if (IS_ERR(reply)) {
- netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
- ovs_dp_vport_multicast_group.id, PTR_ERR(reply));
- goto exit_unlock;
- }
+ err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid,
+ info->snd_seq, 0, OVS_VPORT_CMD_NEW);
+ BUG_ON(err < 0);
genl_notify(reply, genl_info_net(info), info->snd_portid,
ovs_dp_vport_multicast_group.id, info->nlhdr, GFP_KERNEL);
+ rtnl_unlock();
+ return 0;
+
+exit_free:
+ kfree_skb(reply);
exit_unlock:
rtnl_unlock();
return err;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index fe0e421..67a2b78 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -795,9 +795,9 @@
void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
{
+ BUG_ON(table->count == 0);
hlist_del_rcu(&flow->hash_node[table->node_ver]);
table->count--;
- BUG_ON(table->count < 0);
}
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index cf68e6e..9c83474 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1253,6 +1253,7 @@
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (srose != NULL) {
+ memset(srose, 0, msg->msg_namelen);
srose->srose_family = AF_ROSE;
srose->srose_addr = rose->dest_addr;
srose->srose_call = rose->dest_call;
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 1135d82..9b97172 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -204,7 +204,6 @@
if (err < 0)
return err;
- err = -EINVAL;
if (tb[TCA_FW_CLASSID]) {
f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
tcf_bind_filter(tp, &f->res, base);
@@ -218,6 +217,7 @@
}
#endif /* CONFIG_NET_CLS_IND */
+ err = -EINVAL;
if (tb[TCA_FW_MASK]) {
mask = nla_get_u32(tb[TCA_FW_MASK]);
if (mask != head->mask)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index dcc446e..d5f35f1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -304,10 +304,8 @@
err = rpciod_up();
if (err)
goto out_no_rpciod;
- err = -EINVAL;
- if (!xprt)
- goto out_no_xprt;
+ err = -EINVAL;
if (args->version >= program->nrvers)
goto out_err;
version = program->version[args->version];
@@ -382,10 +380,9 @@
out_no_stats:
kfree(clnt);
out_err:
- xprt_put(xprt);
-out_no_xprt:
rpciod_down();
out_no_rpciod:
+ xprt_put(xprt);
return ERR_PTR(err);
}
@@ -512,7 +509,7 @@
new = rpc_new_client(args, xprt);
if (IS_ERR(new)) {
err = PTR_ERR(new);
- goto out_put;
+ goto out_err;
}
atomic_inc(&clnt->cl_count);
@@ -525,8 +522,6 @@
new->cl_chatty = clnt->cl_chatty;
return new;
-out_put:
- xprt_put(xprt);
out_err:
dprintk("RPC: %s: returned error %d\n", __func__, err);
return ERR_PTR(err);
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index a9622b6..515ce38 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -790,6 +790,7 @@
if (addr) {
addr->family = AF_TIPC;
addr->addrtype = TIPC_ADDR_ID;
+ memset(&addr->addr, 0, sizeof(addr->addr));
addr->addr.id.ref = msg_origport(msg);
addr->addr.id.node = msg_orignode(msg);
addr->addr.name.domain = 0; /* could leave uninitialized */
@@ -904,6 +905,9 @@
goto exit;
}
+ /* will be updated in set_orig_addr() if needed */
+ m->msg_namelen = 0;
+
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart:
@@ -1013,6 +1017,9 @@
goto exit;
}
+ /* will be updated in set_orig_addr() if needed */
+ m->msg_namelen = 0;
+
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index d8079da..7f93e2a 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1670,6 +1670,8 @@
vsk = vsock_sk(sk);
err = 0;
+ msg->msg_namelen = 0;
+
lock_sock(sk);
if (sk->sk_state != SS_CONNECTED) {
diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
index 1f6508e..5e04d3d 100644
--- a/net/vmw_vsock/vmci_transport.c
+++ b/net/vmw_vsock/vmci_transport.c
@@ -1736,6 +1736,8 @@
if (flags & MSG_OOB || flags & MSG_ERRQUEUE)
return -EOPNOTSUPP;
+ msg->msg_namelen = 0;
+
/* Retrieve the head sk_buff from the socket's receive queue. */
err = 0;
skb = skb_recv_datagram(&vsk->sk, flags, noblock, &err);
@@ -1768,7 +1770,6 @@
if (err)
goto out;
- msg->msg_namelen = 0;
if (msg->msg_name) {
struct sockaddr_vm *vm_addr;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 09d994d..482c70e 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -224,6 +224,7 @@
rtnl_lock();
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
+ mutex_lock(&rdev->sched_scan_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
@@ -248,6 +249,7 @@
wdev_unlock(wdev);
}
+ mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
rtnl_unlock();
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index b28cc38..4de4bc4 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3016,6 +3016,7 @@
$dstat !~ /^'X'$/ && # character constants
$dstat !~ /$exceptions/ &&
$dstat !~ /^\.$Ident\s*=/ && # .foo =
+ $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo
$dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...)
$dstat !~ /^for\s*$Constant$/ && # for (...)
$dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar()
diff --git a/security/capability.c b/security/capability.c
index 5797750..6783c3e 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -737,6 +737,11 @@
{
return 0;
}
+
+static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+}
+
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -1071,6 +1076,7 @@
set_to_cap_if_null(ops, tun_dev_open);
set_to_cap_if_null(ops, tun_dev_attach_queue);
set_to_cap_if_null(ops, tun_dev_attach);
+ set_to_cap_if_null(ops, skb_owned_by);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
set_to_cap_if_null(ops, xfrm_policy_alloc_security);
diff --git a/security/security.c b/security/security.c
index 7b88c6a..03f248b 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1290,6 +1290,11 @@
}
EXPORT_SYMBOL(security_tun_dev_open);
+void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+ security_ops->skb_owned_by(skb, sk);
+}
+
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2fa28c8..7171a95 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -51,6 +51,7 @@
#include <linux/tty.h>
#include <net/icmp.h>
#include <net/ip.h> /* for local_port_range[] */
+#include <net/sock.h>
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/net_namespace.h>
#include <net/netlabel.h>
@@ -4363,6 +4364,11 @@
selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
}
+static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
+{
+ skb_set_owner_w(skb, sk);
+}
+
static int selinux_secmark_relabel_packet(u32 sid)
{
const struct task_security_struct *__tsec;
@@ -5664,6 +5670,7 @@
.tun_dev_attach_queue = selinux_tun_dev_attach_queue,
.tun_dev_attach = selinux_tun_dev_attach,
.tun_dev_open = selinux_tun_dev_open,
+ .skb_owned_by = selinux_skb_owned_by,
#ifdef CONFIG_SECURITY_NETWORK_XFRM
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 71ae86c..eb560fa 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3222,18 +3222,10 @@
int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
struct vm_area_struct *area)
{
- long size;
- unsigned long offset;
+ struct snd_pcm_runtime *runtime = substream->runtime;;
area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
- area->vm_flags |= VM_IO;
- size = area->vm_end - area->vm_start;
- offset = area->vm_pgoff << PAGE_SHIFT;
- if (io_remap_pfn_range(area, area->vm_start,
- (substream->runtime->dma_addr + offset) >> PAGE_SHIFT,
- size, area->vm_page_prot))
- return -EAGAIN;
- return 0;
+ return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes);
}
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index b82bbf5..34d0201 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -584,7 +584,7 @@
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- struct arizona *arizona = dev_get_drvdata(codec->dev);
+ struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
struct regmap *regmap = codec->control_data;
const struct reg_default *patch = NULL;
int i, patch_size;
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 134e41c..f8a31ad 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1083,6 +1083,8 @@
{ "ROP", NULL, "Right Speaker PGA" },
{ "RON", NULL, "Right Speaker PGA" },
+ { "Charge Pump", NULL, "CLK_DSP" },
+
{ "Left Headphone Output PGA", NULL, "Charge Pump" },
{ "Right Headphone Output PGA", NULL, "Charge Pump" },
{ "Left Line Output PGA", NULL, "Charge Pump" },
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index d7231e3..6bbeb0b 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -972,6 +972,7 @@
static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
{
struct i2s_dai *i2s;
+ int ret;
i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
if (i2s == NULL)
@@ -996,15 +997,17 @@
i2s->i2s_dai_drv.capture.channels_max = 2;
i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
+ dev_set_drvdata(&i2s->pdev->dev, i2s);
} else { /* Create a new platform_device for Secondary */
- i2s->pdev = platform_device_register_resndata(NULL,
- "samsung-i2s-sec", -1, NULL, 0, NULL, 0);
+ i2s->pdev = platform_device_alloc("samsung-i2s-sec", -1);
if (IS_ERR(i2s->pdev))
return NULL;
- }
- /* Pre-assign snd_soc_dai_set_drvdata */
- dev_set_drvdata(&i2s->pdev->dev, i2s);
+ platform_set_drvdata(i2s->pdev, i2s);
+ ret = platform_device_add(i2s->pdev);
+ if (ret < 0)
+ return NULL;
+ }
return i2s;
}
@@ -1107,6 +1110,10 @@
if (samsung_dai_type == TYPE_SEC) {
sec_dai = dev_get_drvdata(&pdev->dev);
+ if (!sec_dai) {
+ dev_err(&pdev->dev, "Unable to get drvdata\n");
+ return -EFAULT;
+ }
snd_soc_register_dai(&sec_dai->pdev->dev,
&sec_dai->i2s_dai_drv);
asoc_dma_platform_register(&pdev->dev);
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b5b3db7..ed0bfb0 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -211,19 +211,27 @@
if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
ret = platform->driver->compr_ops->set_params(cstream, params);
if (ret < 0)
- goto out;
+ goto err;
}
if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
ret = rtd->dai_link->compr_ops->set_params(cstream);
if (ret < 0)
- goto out;
+ goto err;
}
snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
SND_SOC_DAPM_STREAM_START);
-out:
+ /* cancel any delayed stream shutdown that is pending */
+ rtd->pop_wait = 0;
+ mutex_unlock(&rtd->pcm_mutex);
+
+ cancel_delayed_work_sync(&rtd->delayed_work);
+
+ return ret;
+
+err:
mutex_unlock(&rtd->pcm_mutex);
return ret;
}
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 507d251..ff4b45a5 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2963,7 +2963,7 @@
val = val << shift;
ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
- if (ret != 0)
+ if (ret < 0)
return ret;
if (snd_soc_volsw_is_stereo(mc)) {
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c925ab0..5e2c55c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -43,8 +43,6 @@
static const struct snd_pcm_hardware tegra_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_PAUSE |
- SNDRV_PCM_INFO_RESUME |
SNDRV_PCM_INFO_INTERLEAVED,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 2,
@@ -127,26 +125,6 @@
return 0;
}
-static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- return snd_dmaengine_pcm_trigger(substream,
- SNDRV_PCM_TRIGGER_START);
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- return snd_dmaengine_pcm_trigger(substream,
- SNDRV_PCM_TRIGGER_STOP);
- default:
- return -EINVAL;
- }
- return 0;
-}
-
static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
@@ -164,7 +142,7 @@
.ioctl = snd_pcm_lib_ioctl,
.hw_params = tegra_pcm_hw_params,
.hw_free = tegra_pcm_hw_free,
- .trigger = tegra_pcm_trigger,
+ .trigger = snd_dmaengine_pcm_trigger,
.pointer = snd_dmaengine_pcm_pointer,
.mmap = tegra_pcm_mmap,
};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 497d274..ebe9144 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -509,7 +509,7 @@
else
ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
- 0, cpu_to_le16(wIndex),
+ 0, wIndex,
&tmp, sizeof(tmp), 1000);
up_read(&mixer->chip->shutdown_rwsem);
@@ -540,7 +540,7 @@
else
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
- cpu_to_le16(wValue), cpu_to_le16(wIndex),
+ wValue, wIndex,
NULL, 0, 1000);
up_read(&mixer->chip->shutdown_rwsem);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 5325a38..9c5ab22 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -486,7 +486,7 @@
{
int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- cpu_to_le16(1), 0, NULL, 0, 1000);
+ 1, 0, NULL, 0, 1000);
if (ret < 0)
return ret;
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 6f3214e..321e066 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1421,6 +1421,7 @@
case 0x3C: /* HSW */
case 0x3F: /* HSW */
case 0x45: /* HSW */
+ case 0x46: /* HSW */
return 1;
case 0x2E: /* Nehalem-EX Xeon - Beckton */
case 0x2F: /* Westmere-EX Xeon - Eagleton */
@@ -1515,6 +1516,7 @@
case 0x3C: /* HSW */
case 0x3F: /* HSW */
case 0x45: /* HSW */
+ case 0x46: /* HSW */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_GFX;
break;
case 0x2D:
@@ -1754,6 +1756,7 @@
case 0x3C: /* HSW */
case 0x3F: /* HSW */
case 0x45: /* HSW */
+ case 0x46: /* HSW */
return 1;
}
return 0;
@@ -2276,7 +2279,7 @@
cmdline(argc, argv);
if (verbose)
- fprintf(stderr, "turbostat v3.2 February 11, 2013"
+ fprintf(stderr, "turbostat v3.3 March 15, 2013"
" - Len Brown <lenb@kernel.org>\n");
turbostat_init();