diff options
571 files changed, 11686 insertions, 3367 deletions
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index 3a268127b054..bc50899e0c81 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt | |||
@@ -81,7 +81,8 @@ PA31 TXD4 | |||
81 | Required properties for pin configuration node: | 81 | Required properties for pin configuration node: |
82 | - atmel,pins: 4 integers array, represents a group of pins mux and config | 82 | - atmel,pins: 4 integers array, represents a group of pins mux and config |
83 | setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>. | 83 | setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>. |
84 | The PERIPH 0 means gpio. | 84 | The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B... |
85 | PIN_BANK 0 is pioA, PIN_BANK 1 is pioB... | ||
85 | 86 | ||
86 | Bits used for CONFIG: | 87 | Bits used for CONFIG: |
87 | PULL_UP (1 << 0): indicate this pin need a pull up. | 88 | PULL_UP (1 << 0): indicate this pin need a pull up. |
@@ -126,7 +127,7 @@ pinctrl@fffff400 { | |||
126 | pinctrl_dbgu: dbgu-0 { | 127 | pinctrl_dbgu: dbgu-0 { |
127 | atmel,pins = | 128 | atmel,pins = |
128 | <1 14 0x1 0x0 /* PB14 periph A */ | 129 | <1 14 0x1 0x0 /* PB14 periph A */ |
129 | 1 15 0x1 0x1>; /* PB15 periph with pullup */ | 130 | 1 15 0x1 0x1>; /* PB15 periph A with pullup */ |
130 | }; | 131 | }; |
131 | }; | 132 | }; |
132 | }; | 133 | }; |
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt index 8fbd8b46ee34..dcf338e62b71 100644 --- a/Documentation/filesystems/f2fs.txt +++ b/Documentation/filesystems/f2fs.txt | |||
@@ -175,9 +175,9 @@ consists of multiple segments as described below. | |||
175 | align with the zone size <-| | 175 | align with the zone size <-| |
176 | |-> align with the segment size | 176 | |-> align with the segment size |
177 | _________________________________________________________________________ | 177 | _________________________________________________________________________ |
178 | | | | Node | Segment | Segment | | | 178 | | | | Segment | Node | Segment | | |
179 | | Superblock | Checkpoint | Address | Info. | Summary | Main | | 179 | | Superblock | Checkpoint | Info. | Address | Summary | Main | |
180 | | (SB) | (CP) | Table (NAT) | Table (SIT) | Area (SSA) | | | 180 | | (SB) | (CP) | Table (SIT) | Table (NAT) | Area (SSA) | | |
181 | |____________|_____2______|______N______|______N______|______N_____|__N___| | 181 | |____________|_____2______|______N______|______N______|______N_____|__N___| |
182 | . . | 182 | . . |
183 | . . | 183 | . . |
@@ -200,14 +200,14 @@ consists of multiple segments as described below. | |||
200 | : It contains file system information, bitmaps for valid NAT/SIT sets, orphan | 200 | : It contains file system information, bitmaps for valid NAT/SIT sets, orphan |
201 | inode lists, and summary entries of current active segments. | 201 | inode lists, and summary entries of current active segments. |
202 | 202 | ||
203 | - Node Address Table (NAT) | ||
204 | : It is composed of a block address table for all the node blocks stored in | ||
205 | Main area. | ||
206 | |||
207 | - Segment Information Table (SIT) | 203 | - Segment Information Table (SIT) |
208 | : It contains segment information such as valid block count and bitmap for the | 204 | : It contains segment information such as valid block count and bitmap for the |
209 | validity of all the blocks. | 205 | validity of all the blocks. |
210 | 206 | ||
207 | - Node Address Table (NAT) | ||
208 | : It is composed of a block address table for all the node blocks stored in | ||
209 | Main area. | ||
210 | |||
211 | - Segment Summary Area (SSA) | 211 | - Segment Summary Area (SSA) |
212 | : It contains summary entries which contains the owner information of all the | 212 | : It contains summary entries which contains the owner information of all the |
213 | data and node blocks stored in Main area. | 213 | data and node blocks stored in Main area. |
@@ -236,13 +236,13 @@ For file system consistency, each CP points to which NAT and SIT copies are | |||
236 | valid, as shown as below. | 236 | valid, as shown as below. |
237 | 237 | ||
238 | +--------+----------+---------+ | 238 | +--------+----------+---------+ |
239 | | CP | NAT | SIT | | 239 | | CP | SIT | NAT | |
240 | +--------+----------+---------+ | 240 | +--------+----------+---------+ |
241 | . . . . | 241 | . . . . |
242 | . . . . | 242 | . . . . |
243 | . . . . | 243 | . . . . |
244 | +-------+-------+--------+--------+--------+--------+ | 244 | +-------+-------+--------+--------+--------+--------+ |
245 | | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 | | 245 | | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 | |
246 | +-------+-------+--------+--------+--------+--------+ | 246 | +-------+-------+--------+--------+--------+--------+ |
247 | | ^ ^ | 247 | | ^ ^ |
248 | | | | | 248 | | | | |
diff --git a/MAINTAINERS b/MAINTAINERS index 915564eda145..ff60aac83dca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -228,7 +228,7 @@ S: Maintained | |||
228 | F: drivers/platform/x86/acerhdf.c | 228 | F: drivers/platform/x86/acerhdf.c |
229 | 229 | ||
230 | ACER WMI LAPTOP EXTRAS | 230 | ACER WMI LAPTOP EXTRAS |
231 | M: Joey Lee <jlee@novell.com> | 231 | M: "Lee, Chun-Yi" <jlee@suse.com> |
232 | L: platform-driver-x86@vger.kernel.org | 232 | L: platform-driver-x86@vger.kernel.org |
233 | S: Maintained | 233 | S: Maintained |
234 | F: drivers/platform/x86/acer-wmi.c | 234 | F: drivers/platform/x86/acer-wmi.c |
@@ -648,7 +648,7 @@ F: arch/arm/ | |||
648 | 648 | ||
649 | ARM SUB-ARCHITECTURES | 649 | ARM SUB-ARCHITECTURES |
650 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) | 650 | L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) |
651 | S: MAINTAINED | 651 | S: Maintained |
652 | F: arch/arm/mach-*/ | 652 | F: arch/arm/mach-*/ |
653 | F: arch/arm/plat-*/ | 653 | F: arch/arm/plat-*/ |
654 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git | 654 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git |
@@ -1351,6 +1351,14 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k | |||
1351 | S: Supported | 1351 | S: Supported |
1352 | F: drivers/net/wireless/ath/ath9k/ | 1352 | F: drivers/net/wireless/ath/ath9k/ |
1353 | 1353 | ||
1354 | WILOCITY WIL6210 WIRELESS DRIVER | ||
1355 | M: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | ||
1356 | L: linux-wireless@vger.kernel.org | ||
1357 | L: wil6210@qca.qualcomm.com | ||
1358 | S: Supported | ||
1359 | W: http://wireless.kernel.org/en/users/Drivers/wil6210 | ||
1360 | F: drivers/net/wireless/ath/wil6210/ | ||
1361 | |||
1354 | CARL9170 LINUX COMMUNITY WIRELESS DRIVER | 1362 | CARL9170 LINUX COMMUNITY WIRELESS DRIVER |
1355 | M: Christian Lamparter <chunkeey@googlemail.com> | 1363 | M: Christian Lamparter <chunkeey@googlemail.com> |
1356 | L: linux-wireless@vger.kernel.org | 1364 | L: linux-wireless@vger.kernel.org |
@@ -1964,9 +1972,9 @@ S: Maintained | |||
1964 | F: drivers/usb/host/ohci-ep93xx.c | 1972 | F: drivers/usb/host/ohci-ep93xx.c |
1965 | 1973 | ||
1966 | CIRRUS LOGIC CS4270 SOUND DRIVER | 1974 | CIRRUS LOGIC CS4270 SOUND DRIVER |
1967 | M: Timur Tabi <timur@freescale.com> | 1975 | M: Timur Tabi <timur@tabi.org> |
1968 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 1976 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
1969 | S: Supported | 1977 | S: Odd Fixes |
1970 | F: sound/soc/codecs/cs4270* | 1978 | F: sound/soc/codecs/cs4270* |
1971 | 1979 | ||
1972 | CLEANCACHE API | 1980 | CLEANCACHE API |
@@ -3183,9 +3191,9 @@ F: include/uapi/video/ | |||
3183 | F: include/uapi/linux/fb.h | 3191 | F: include/uapi/linux/fb.h |
3184 | 3192 | ||
3185 | FREESCALE DIU FRAMEBUFFER DRIVER | 3193 | FREESCALE DIU FRAMEBUFFER DRIVER |
3186 | M: Timur Tabi <timur@freescale.com> | 3194 | M: Timur Tabi <timur@tabi.org> |
3187 | L: linux-fbdev@vger.kernel.org | 3195 | L: linux-fbdev@vger.kernel.org |
3188 | S: Supported | 3196 | S: Maintained |
3189 | F: drivers/video/fsl-diu-fb.* | 3197 | F: drivers/video/fsl-diu-fb.* |
3190 | 3198 | ||
3191 | FREESCALE DMA DRIVER | 3199 | FREESCALE DMA DRIVER |
@@ -3220,9 +3228,8 @@ F: drivers/net/ethernet/freescale/fs_enet/ | |||
3220 | F: include/linux/fs_enet_pd.h | 3228 | F: include/linux/fs_enet_pd.h |
3221 | 3229 | ||
3222 | FREESCALE QUICC ENGINE LIBRARY | 3230 | FREESCALE QUICC ENGINE LIBRARY |
3223 | M: Timur Tabi <timur@freescale.com> | ||
3224 | L: linuxppc-dev@lists.ozlabs.org | 3231 | L: linuxppc-dev@lists.ozlabs.org |
3225 | S: Supported | 3232 | S: Orphan |
3226 | F: arch/powerpc/sysdev/qe_lib/ | 3233 | F: arch/powerpc/sysdev/qe_lib/ |
3227 | F: arch/powerpc/include/asm/*qe.h | 3234 | F: arch/powerpc/include/asm/*qe.h |
3228 | 3235 | ||
@@ -3241,16 +3248,16 @@ S: Maintained | |||
3241 | F: drivers/net/ethernet/freescale/ucc_geth* | 3248 | F: drivers/net/ethernet/freescale/ucc_geth* |
3242 | 3249 | ||
3243 | FREESCALE QUICC ENGINE UCC UART DRIVER | 3250 | FREESCALE QUICC ENGINE UCC UART DRIVER |
3244 | M: Timur Tabi <timur@freescale.com> | 3251 | M: Timur Tabi <timur@tabi.org> |
3245 | L: linuxppc-dev@lists.ozlabs.org | 3252 | L: linuxppc-dev@lists.ozlabs.org |
3246 | S: Supported | 3253 | S: Maintained |
3247 | F: drivers/tty/serial/ucc_uart.c | 3254 | F: drivers/tty/serial/ucc_uart.c |
3248 | 3255 | ||
3249 | FREESCALE SOC SOUND DRIVERS | 3256 | FREESCALE SOC SOUND DRIVERS |
3250 | M: Timur Tabi <timur@freescale.com> | 3257 | M: Timur Tabi <timur@tabi.org> |
3251 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 3258 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
3252 | L: linuxppc-dev@lists.ozlabs.org | 3259 | L: linuxppc-dev@lists.ozlabs.org |
3253 | S: Supported | 3260 | S: Maintained |
3254 | F: sound/soc/fsl/fsl* | 3261 | F: sound/soc/fsl/fsl* |
3255 | F: sound/soc/fsl/mpc8610_hpcd.c | 3262 | F: sound/soc/fsl/mpc8610_hpcd.c |
3256 | 3263 | ||
@@ -5077,7 +5084,7 @@ S: Maintained | |||
5077 | F: drivers/media/radio/radio-mr800.c | 5084 | F: drivers/media/radio/radio-mr800.c |
5078 | 5085 | ||
5079 | MSI LAPTOP SUPPORT | 5086 | MSI LAPTOP SUPPORT |
5080 | M: "Lee, Chun-Yi" <jlee@novell.com> | 5087 | M: "Lee, Chun-Yi" <jlee@suse.com> |
5081 | L: platform-driver-x86@vger.kernel.org | 5088 | L: platform-driver-x86@vger.kernel.org |
5082 | S: Maintained | 5089 | S: Maintained |
5083 | F: drivers/platform/x86/msi-laptop.c | 5090 | F: drivers/platform/x86/msi-laptop.c |
@@ -5507,8 +5514,7 @@ M: Benoît Cousson <b-cousson@ti.com> | |||
5507 | M: Paul Walmsley <paul@pwsan.com> | 5514 | M: Paul Walmsley <paul@pwsan.com> |
5508 | L: linux-omap@vger.kernel.org | 5515 | L: linux-omap@vger.kernel.org |
5509 | S: Maintained | 5516 | S: Maintained |
5510 | F: arch/arm/mach-omap2/omap_hwmod.c | 5517 | F: arch/arm/mach-omap2/omap_hwmod.* |
5511 | F: arch/arm/plat-omap/include/plat/omap_hwmod.h | ||
5512 | 5518 | ||
5513 | OMAP HWMOD DATA FOR OMAP4-BASED DEVICES | 5519 | OMAP HWMOD DATA FOR OMAP4-BASED DEVICES |
5514 | M: Benoît Cousson <b-cousson@ti.com> | 5520 | M: Benoît Cousson <b-cousson@ti.com> |
@@ -6579,7 +6585,7 @@ F: drivers/media/platform/s3c-camif/ | |||
6579 | F: include/media/s3c_camif.h | 6585 | F: include/media/s3c_camif.h |
6580 | 6586 | ||
6581 | SERIAL DRIVERS | 6587 | SERIAL DRIVERS |
6582 | M: Alan Cox <alan@linux.intel.com> | 6588 | M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
6583 | L: linux-serial@vger.kernel.org | 6589 | L: linux-serial@vger.kernel.org |
6584 | S: Maintained | 6590 | S: Maintained |
6585 | F: drivers/tty/serial | 6591 | F: drivers/tty/serial |
@@ -7082,7 +7088,7 @@ F: include/uapi/sound/ | |||
7082 | F: sound/ | 7088 | F: sound/ |
7083 | 7089 | ||
7084 | SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) | 7090 | SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) |
7085 | M: Liam Girdwood <lrg@ti.com> | 7091 | M: Liam Girdwood <lgirdwood@gmail.com> |
7086 | M: Mark Brown <broonie@opensource.wolfsonmicro.com> | 7092 | M: Mark Brown <broonie@opensource.wolfsonmicro.com> |
7087 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git | 7093 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git |
7088 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) | 7094 | L: alsa-devel@alsa-project.org (moderated for non-subscribers) |
@@ -7334,7 +7340,7 @@ S: Odd Fixes | |||
7334 | F: drivers/staging/speakup/ | 7340 | F: drivers/staging/speakup/ |
7335 | 7341 | ||
7336 | STAGING - TI DSP BRIDGE DRIVERS | 7342 | STAGING - TI DSP BRIDGE DRIVERS |
7337 | M: Omar Ramirez Luna <omar.ramirez@ti.com> | 7343 | M: Omar Ramirez Luna <omar.ramirez@copitl.com> |
7338 | S: Odd Fixes | 7344 | S: Odd Fixes |
7339 | F: drivers/staging/tidspbridge/ | 7345 | F: drivers/staging/tidspbridge/ |
7340 | 7346 | ||
@@ -8526,7 +8532,7 @@ F: Documentation/x86/ | |||
8526 | F: arch/x86/ | 8532 | F: arch/x86/ |
8527 | 8533 | ||
8528 | X86 PLATFORM DRIVERS | 8534 | X86 PLATFORM DRIVERS |
8529 | M: Matthew Garrett <mjg@redhat.com> | 8535 | M: Matthew Garrett <matthew.garrett@nebula.com> |
8530 | L: platform-driver-x86@vger.kernel.org | 8536 | L: platform-driver-x86@vger.kernel.org |
8531 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git | 8537 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git |
8532 | S: Maintained | 8538 | S: Maintained |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 3 | 1 | VERSION = 3 |
2 | PATCHLEVEL = 8 | 2 | PATCHLEVEL = 8 |
3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
4 | EXTRAVERSION = -rc3 | 4 | EXTRAVERSION = -rc5 |
5 | NAME = Terrified Chipmunk | 5 | NAME = Terrified Chipmunk |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
@@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |||
169 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 169 | -e s/arm.*/arm/ -e s/sa110/arm/ \ |
170 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 170 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ |
171 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | 171 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ |
172 | -e s/sh[234].*/sh/ ) | 172 | -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) |
173 | 173 | ||
174 | # Cross compiling and selecting different set of gcc/bin-utils | 174 | # Cross compiling and selecting different set of gcc/bin-utils |
175 | # --------------------------------------------------------------------------- | 175 | # --------------------------------------------------------------------------- |
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index e44da40d984f..5ebb44fe826a 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile | |||
@@ -155,6 +155,7 @@ dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \ | |||
155 | dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb | 155 | dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb |
156 | 156 | ||
157 | targets += dtbs | 157 | targets += dtbs |
158 | targets += $(dtb-y) | ||
158 | endif | 159 | endif |
159 | 160 | ||
160 | # *.dtb used to be generated in the directory above. Clean out the | 161 | # *.dtb used to be generated in the directory above. Clean out the |
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts index 00044026ef1f..9b82facb2561 100644 --- a/arch/arm/boot/dts/armada-370-db.dts +++ b/arch/arm/boot/dts/armada-370-db.dts | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | memory { | 27 | memory { |
28 | device_type = "memory"; | 28 | device_type = "memory"; |
29 | reg = <0x00000000 0x20000000>; /* 512 MB */ | 29 | reg = <0x00000000 0x40000000>; /* 1 GB */ |
30 | }; | 30 | }; |
31 | 31 | ||
32 | soc { | 32 | soc { |
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi index 271855a6e224..e041f42ed711 100644 --- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi | |||
@@ -50,27 +50,25 @@ | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | gpio0: gpio@d0018100 { | 52 | gpio0: gpio@d0018100 { |
53 | compatible = "marvell,armadaxp-gpio"; | 53 | compatible = "marvell,orion-gpio"; |
54 | reg = <0xd0018100 0x40>, | 54 | reg = <0xd0018100 0x40>; |
55 | <0xd0018800 0x30>; | ||
56 | ngpios = <32>; | 55 | ngpios = <32>; |
57 | gpio-controller; | 56 | gpio-controller; |
58 | #gpio-cells = <2>; | 57 | #gpio-cells = <2>; |
59 | interrupt-controller; | 58 | interrupt-controller; |
60 | #interrupts-cells = <2>; | 59 | #interrupts-cells = <2>; |
61 | interrupts = <16>, <17>, <18>, <19>; | 60 | interrupts = <82>, <83>, <84>, <85>; |
62 | }; | 61 | }; |
63 | 62 | ||
64 | gpio1: gpio@d0018140 { | 63 | gpio1: gpio@d0018140 { |
65 | compatible = "marvell,armadaxp-gpio"; | 64 | compatible = "marvell,orion-gpio"; |
66 | reg = <0xd0018140 0x40>, | 65 | reg = <0xd0018140 0x40>; |
67 | <0xd0018840 0x30>; | ||
68 | ngpios = <17>; | 66 | ngpios = <17>; |
69 | gpio-controller; | 67 | gpio-controller; |
70 | #gpio-cells = <2>; | 68 | #gpio-cells = <2>; |
71 | interrupt-controller; | 69 | interrupt-controller; |
72 | #interrupts-cells = <2>; | 70 | #interrupts-cells = <2>; |
73 | interrupts = <20>, <21>, <22>; | 71 | interrupts = <87>, <88>, <89>; |
74 | }; | 72 | }; |
75 | }; | 73 | }; |
76 | }; | 74 | }; |
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi index 1c1937dbce73..9e23bd8c9536 100644 --- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi | |||
@@ -51,39 +51,36 @@ | |||
51 | }; | 51 | }; |
52 | 52 | ||
53 | gpio0: gpio@d0018100 { | 53 | gpio0: gpio@d0018100 { |
54 | compatible = "marvell,armadaxp-gpio"; | 54 | compatible = "marvell,orion-gpio"; |
55 | reg = <0xd0018100 0x40>, | 55 | reg = <0xd0018100 0x40>; |
56 | <0xd0018800 0x30>; | ||
57 | ngpios = <32>; | 56 | ngpios = <32>; |
58 | gpio-controller; | 57 | gpio-controller; |
59 | #gpio-cells = <2>; | 58 | #gpio-cells = <2>; |
60 | interrupt-controller; | 59 | interrupt-controller; |
61 | #interrupts-cells = <2>; | 60 | #interrupts-cells = <2>; |
62 | interrupts = <16>, <17>, <18>, <19>; | 61 | interrupts = <82>, <83>, <84>, <85>; |
63 | }; | 62 | }; |
64 | 63 | ||
65 | gpio1: gpio@d0018140 { | 64 | gpio1: gpio@d0018140 { |
66 | compatible = "marvell,armadaxp-gpio"; | 65 | compatible = "marvell,orion-gpio"; |
67 | reg = <0xd0018140 0x40>, | 66 | reg = <0xd0018140 0x40>; |
68 | <0xd0018840 0x30>; | ||
69 | ngpios = <32>; | 67 | ngpios = <32>; |
70 | gpio-controller; | 68 | gpio-controller; |
71 | #gpio-cells = <2>; | 69 | #gpio-cells = <2>; |
72 | interrupt-controller; | 70 | interrupt-controller; |
73 | #interrupts-cells = <2>; | 71 | #interrupts-cells = <2>; |
74 | interrupts = <20>, <21>, <22>, <23>; | 72 | interrupts = <87>, <88>, <89>, <90>; |
75 | }; | 73 | }; |
76 | 74 | ||
77 | gpio2: gpio@d0018180 { | 75 | gpio2: gpio@d0018180 { |
78 | compatible = "marvell,armadaxp-gpio"; | 76 | compatible = "marvell,orion-gpio"; |
79 | reg = <0xd0018180 0x40>, | 77 | reg = <0xd0018180 0x40>; |
80 | <0xd0018870 0x30>; | ||
81 | ngpios = <3>; | 78 | ngpios = <3>; |
82 | gpio-controller; | 79 | gpio-controller; |
83 | #gpio-cells = <2>; | 80 | #gpio-cells = <2>; |
84 | interrupt-controller; | 81 | interrupt-controller; |
85 | #interrupts-cells = <2>; | 82 | #interrupts-cells = <2>; |
86 | interrupts = <24>; | 83 | interrupts = <91>; |
87 | }; | 84 | }; |
88 | 85 | ||
89 | ethernet@d0034000 { | 86 | ethernet@d0034000 { |
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi index 4905cf3a5ef8..965966110e38 100644 --- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi | |||
@@ -66,39 +66,36 @@ | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | gpio0: gpio@d0018100 { | 68 | gpio0: gpio@d0018100 { |
69 | compatible = "marvell,armadaxp-gpio"; | 69 | compatible = "marvell,orion-gpio"; |
70 | reg = <0xd0018100 0x40>, | 70 | reg = <0xd0018100 0x40>; |
71 | <0xd0018800 0x30>; | ||
72 | ngpios = <32>; | 71 | ngpios = <32>; |
73 | gpio-controller; | 72 | gpio-controller; |
74 | #gpio-cells = <2>; | 73 | #gpio-cells = <2>; |
75 | interrupt-controller; | 74 | interrupt-controller; |
76 | #interrupts-cells = <2>; | 75 | #interrupts-cells = <2>; |
77 | interrupts = <16>, <17>, <18>, <19>; | 76 | interrupts = <82>, <83>, <84>, <85>; |
78 | }; | 77 | }; |
79 | 78 | ||
80 | gpio1: gpio@d0018140 { | 79 | gpio1: gpio@d0018140 { |
81 | compatible = "marvell,armadaxp-gpio"; | 80 | compatible = "marvell,orion-gpio"; |
82 | reg = <0xd0018140 0x40>, | 81 | reg = <0xd0018140 0x40>; |
83 | <0xd0018840 0x30>; | ||
84 | ngpios = <32>; | 82 | ngpios = <32>; |
85 | gpio-controller; | 83 | gpio-controller; |
86 | #gpio-cells = <2>; | 84 | #gpio-cells = <2>; |
87 | interrupt-controller; | 85 | interrupt-controller; |
88 | #interrupts-cells = <2>; | 86 | #interrupts-cells = <2>; |
89 | interrupts = <20>, <21>, <22>, <23>; | 87 | interrupts = <87>, <88>, <89>, <90>; |
90 | }; | 88 | }; |
91 | 89 | ||
92 | gpio2: gpio@d0018180 { | 90 | gpio2: gpio@d0018180 { |
93 | compatible = "marvell,armadaxp-gpio"; | 91 | compatible = "marvell,orion-gpio"; |
94 | reg = <0xd0018180 0x40>, | 92 | reg = <0xd0018180 0x40>; |
95 | <0xd0018870 0x30>; | ||
96 | ngpios = <3>; | 93 | ngpios = <3>; |
97 | gpio-controller; | 94 | gpio-controller; |
98 | #gpio-cells = <2>; | 95 | #gpio-cells = <2>; |
99 | interrupt-controller; | 96 | interrupt-controller; |
100 | #interrupts-cells = <2>; | 97 | #interrupts-cells = <2>; |
101 | interrupts = <24>; | 98 | interrupts = <91>; |
102 | }; | 99 | }; |
103 | 100 | ||
104 | ethernet@d0034000 { | 101 | ethernet@d0034000 { |
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi index e154f242c680..222047f1ece9 100644 --- a/arch/arm/boot/dts/at91rm9200.dtsi +++ b/arch/arm/boot/dts/at91rm9200.dtsi | |||
@@ -336,8 +336,8 @@ | |||
336 | 336 | ||
337 | i2c@0 { | 337 | i2c@0 { |
338 | compatible = "i2c-gpio"; | 338 | compatible = "i2c-gpio"; |
339 | gpios = <&pioA 23 0 /* sda */ | 339 | gpios = <&pioA 25 0 /* sda */ |
340 | &pioA 24 0 /* scl */ | 340 | &pioA 26 0 /* scl */ |
341 | >; | 341 | >; |
342 | i2c-gpio,sda-open-drain; | 342 | i2c-gpio,sda-open-drain; |
343 | i2c-gpio,scl-open-drain; | 343 | i2c-gpio,scl-open-drain; |
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 3a47cf952146..8ecca6948d81 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi | |||
@@ -143,6 +143,11 @@ | |||
143 | atmel,pins = | 143 | atmel,pins = |
144 | <0 3 0x1 0x0>; /* PA3 periph A */ | 144 | <0 3 0x1 0x0>; /* PA3 periph A */ |
145 | }; | 145 | }; |
146 | |||
147 | pinctrl_usart0_sck: usart0_sck-0 { | ||
148 | atmel,pins = | ||
149 | <0 4 0x1 0x0>; /* PA4 periph A */ | ||
150 | }; | ||
146 | }; | 151 | }; |
147 | 152 | ||
148 | usart1 { | 153 | usart1 { |
@@ -154,12 +159,17 @@ | |||
154 | 159 | ||
155 | pinctrl_usart1_rts: usart1_rts-0 { | 160 | pinctrl_usart1_rts: usart1_rts-0 { |
156 | atmel,pins = | 161 | atmel,pins = |
157 | <3 27 0x3 0x0>; /* PC27 periph C */ | 162 | <2 27 0x3 0x0>; /* PC27 periph C */ |
158 | }; | 163 | }; |
159 | 164 | ||
160 | pinctrl_usart1_cts: usart1_cts-0 { | 165 | pinctrl_usart1_cts: usart1_cts-0 { |
161 | atmel,pins = | 166 | atmel,pins = |
162 | <3 28 0x3 0x0>; /* PC28 periph C */ | 167 | <2 28 0x3 0x0>; /* PC28 periph C */ |
168 | }; | ||
169 | |||
170 | pinctrl_usart1_sck: usart1_sck-0 { | ||
171 | atmel,pins = | ||
172 | <2 28 0x3 0x0>; /* PC29 periph C */ | ||
163 | }; | 173 | }; |
164 | }; | 174 | }; |
165 | 175 | ||
@@ -172,46 +182,56 @@ | |||
172 | 182 | ||
173 | pinctrl_uart2_rts: uart2_rts-0 { | 183 | pinctrl_uart2_rts: uart2_rts-0 { |
174 | atmel,pins = | 184 | atmel,pins = |
175 | <0 0 0x2 0x0>; /* PB0 periph B */ | 185 | <1 0 0x2 0x0>; /* PB0 periph B */ |
176 | }; | 186 | }; |
177 | 187 | ||
178 | pinctrl_uart2_cts: uart2_cts-0 { | 188 | pinctrl_uart2_cts: uart2_cts-0 { |
179 | atmel,pins = | 189 | atmel,pins = |
180 | <0 1 0x2 0x0>; /* PB1 periph B */ | 190 | <1 1 0x2 0x0>; /* PB1 periph B */ |
191 | }; | ||
192 | |||
193 | pinctrl_usart2_sck: usart2_sck-0 { | ||
194 | atmel,pins = | ||
195 | <1 2 0x2 0x0>; /* PB2 periph B */ | ||
181 | }; | 196 | }; |
182 | }; | 197 | }; |
183 | 198 | ||
184 | usart3 { | 199 | usart3 { |
185 | pinctrl_uart3: usart3-0 { | 200 | pinctrl_uart3: usart3-0 { |
186 | atmel,pins = | 201 | atmel,pins = |
187 | <3 23 0x2 0x1 /* PC22 periph B with pullup */ | 202 | <2 23 0x2 0x1 /* PC22 periph B with pullup */ |
188 | 3 23 0x2 0x0>; /* PC23 periph B */ | 203 | 2 23 0x2 0x0>; /* PC23 periph B */ |
189 | }; | 204 | }; |
190 | 205 | ||
191 | pinctrl_usart3_rts: usart3_rts-0 { | 206 | pinctrl_usart3_rts: usart3_rts-0 { |
192 | atmel,pins = | 207 | atmel,pins = |
193 | <3 24 0x2 0x0>; /* PC24 periph B */ | 208 | <2 24 0x2 0x0>; /* PC24 periph B */ |
194 | }; | 209 | }; |
195 | 210 | ||
196 | pinctrl_usart3_cts: usart3_cts-0 { | 211 | pinctrl_usart3_cts: usart3_cts-0 { |
197 | atmel,pins = | 212 | atmel,pins = |
198 | <3 25 0x2 0x0>; /* PC25 periph B */ | 213 | <2 25 0x2 0x0>; /* PC25 periph B */ |
214 | }; | ||
215 | |||
216 | pinctrl_usart3_sck: usart3_sck-0 { | ||
217 | atmel,pins = | ||
218 | <2 26 0x2 0x0>; /* PC26 periph B */ | ||
199 | }; | 219 | }; |
200 | }; | 220 | }; |
201 | 221 | ||
202 | uart0 { | 222 | uart0 { |
203 | pinctrl_uart0: uart0-0 { | 223 | pinctrl_uart0: uart0-0 { |
204 | atmel,pins = | 224 | atmel,pins = |
205 | <3 8 0x3 0x0 /* PC8 periph C */ | 225 | <2 8 0x3 0x0 /* PC8 periph C */ |
206 | 3 9 0x3 0x1>; /* PC9 periph C with pullup */ | 226 | 2 9 0x3 0x1>; /* PC9 periph C with pullup */ |
207 | }; | 227 | }; |
208 | }; | 228 | }; |
209 | 229 | ||
210 | uart1 { | 230 | uart1 { |
211 | pinctrl_uart1: uart1-0 { | 231 | pinctrl_uart1: uart1-0 { |
212 | atmel,pins = | 232 | atmel,pins = |
213 | <3 16 0x3 0x0 /* PC16 periph C */ | 233 | <2 16 0x3 0x0 /* PC16 periph C */ |
214 | 3 17 0x3 0x1>; /* PC17 periph C with pullup */ | 234 | 2 17 0x3 0x1>; /* PC17 periph C with pullup */ |
215 | }; | 235 | }; |
216 | }; | 236 | }; |
217 | 237 | ||
@@ -240,14 +260,14 @@ | |||
240 | 260 | ||
241 | pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 { | 261 | pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 { |
242 | atmel,pins = | 262 | atmel,pins = |
243 | <1 8 0x1 0x0 /* PA8 periph A */ | 263 | <1 8 0x1 0x0 /* PB8 periph A */ |
244 | 1 11 0x1 0x0 /* PA11 periph A */ | 264 | 1 11 0x1 0x0 /* PB11 periph A */ |
245 | 1 12 0x1 0x0 /* PA12 periph A */ | 265 | 1 12 0x1 0x0 /* PB12 periph A */ |
246 | 1 13 0x1 0x0 /* PA13 periph A */ | 266 | 1 13 0x1 0x0 /* PB13 periph A */ |
247 | 1 14 0x1 0x0 /* PA14 periph A */ | 267 | 1 14 0x1 0x0 /* PB14 periph A */ |
248 | 1 15 0x1 0x0 /* PA15 periph A */ | 268 | 1 15 0x1 0x0 /* PB15 periph A */ |
249 | 1 16 0x1 0x0 /* PA16 periph A */ | 269 | 1 16 0x1 0x0 /* PB16 periph A */ |
250 | 1 17 0x1 0x0>; /* PA17 periph A */ | 270 | 1 17 0x1 0x0>; /* PB17 periph A */ |
251 | }; | 271 | }; |
252 | }; | 272 | }; |
253 | 273 | ||
diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi index fddd17417433..46c098017036 100644 --- a/arch/arm/boot/dts/cros5250-common.dtsi +++ b/arch/arm/boot/dts/cros5250-common.dtsi | |||
@@ -96,8 +96,8 @@ | |||
96 | fifo-depth = <0x80>; | 96 | fifo-depth = <0x80>; |
97 | card-detect-delay = <200>; | 97 | card-detect-delay = <200>; |
98 | samsung,dw-mshc-ciu-div = <3>; | 98 | samsung,dw-mshc-ciu-div = <3>; |
99 | samsung,dw-mshc-sdr-timing = <2 3 3>; | 99 | samsung,dw-mshc-sdr-timing = <2 3>; |
100 | samsung,dw-mshc-ddr-timing = <1 2 3>; | 100 | samsung,dw-mshc-ddr-timing = <1 2>; |
101 | 101 | ||
102 | slot@0 { | 102 | slot@0 { |
103 | reg = <0>; | 103 | reg = <0>; |
@@ -120,8 +120,8 @@ | |||
120 | fifo-depth = <0x80>; | 120 | fifo-depth = <0x80>; |
121 | card-detect-delay = <200>; | 121 | card-detect-delay = <200>; |
122 | samsung,dw-mshc-ciu-div = <3>; | 122 | samsung,dw-mshc-ciu-div = <3>; |
123 | samsung,dw-mshc-sdr-timing = <2 3 3>; | 123 | samsung,dw-mshc-sdr-timing = <2 3>; |
124 | samsung,dw-mshc-ddr-timing = <1 2 3>; | 124 | samsung,dw-mshc-ddr-timing = <1 2>; |
125 | 125 | ||
126 | slot@0 { | 126 | slot@0 { |
127 | reg = <0>; | 127 | reg = <0>; |
@@ -141,8 +141,8 @@ | |||
141 | fifo-depth = <0x80>; | 141 | fifo-depth = <0x80>; |
142 | card-detect-delay = <200>; | 142 | card-detect-delay = <200>; |
143 | samsung,dw-mshc-ciu-div = <3>; | 143 | samsung,dw-mshc-ciu-div = <3>; |
144 | samsung,dw-mshc-sdr-timing = <2 3 3>; | 144 | samsung,dw-mshc-sdr-timing = <2 3>; |
145 | samsung,dw-mshc-ddr-timing = <1 2 3>; | 145 | samsung,dw-mshc-ddr-timing = <1 2>; |
146 | 146 | ||
147 | slot@0 { | 147 | slot@0 { |
148 | reg = <0>; | 148 | reg = <0>; |
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts index fed7d3f9f431..cdee96fca6e2 100644 --- a/arch/arm/boot/dts/dove-cubox.dts +++ b/arch/arm/boot/dts/dove-cubox.dts | |||
@@ -26,10 +26,15 @@ | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | &uart0 { status = "okay"; }; | 28 | &uart0 { status = "okay"; }; |
29 | &sdio0 { status = "okay"; }; | ||
30 | &sata0 { status = "okay"; }; | 29 | &sata0 { status = "okay"; }; |
31 | &i2c0 { status = "okay"; }; | 30 | &i2c0 { status = "okay"; }; |
32 | 31 | ||
32 | &sdio0 { | ||
33 | status = "okay"; | ||
34 | /* sdio0 card detect is connected to wrong pin on CuBox */ | ||
35 | cd-gpios = <&gpio0 12 1>; | ||
36 | }; | ||
37 | |||
33 | &spi0 { | 38 | &spi0 { |
34 | status = "okay"; | 39 | status = "okay"; |
35 | 40 | ||
@@ -42,9 +47,14 @@ | |||
42 | }; | 47 | }; |
43 | 48 | ||
44 | &pinctrl { | 49 | &pinctrl { |
45 | pinctrl-0 = <&pmx_gpio_18>; | 50 | pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>; |
46 | pinctrl-names = "default"; | 51 | pinctrl-names = "default"; |
47 | 52 | ||
53 | pmx_gpio_12: pmx-gpio-12 { | ||
54 | marvell,pins = "mpp12"; | ||
55 | marvell,function = "gpio"; | ||
56 | }; | ||
57 | |||
48 | pmx_gpio_18: pmx-gpio-18 { | 58 | pmx_gpio_18: pmx-gpio-18 { |
49 | marvell,pins = "mpp18"; | 59 | marvell,pins = "mpp18"; |
50 | marvell,function = "gpio"; | 60 | marvell,function = "gpio"; |
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 942d5761ca97..e05b18f3c33d 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts | |||
@@ -115,8 +115,8 @@ | |||
115 | fifo-depth = <0x80>; | 115 | fifo-depth = <0x80>; |
116 | card-detect-delay = <200>; | 116 | card-detect-delay = <200>; |
117 | samsung,dw-mshc-ciu-div = <3>; | 117 | samsung,dw-mshc-ciu-div = <3>; |
118 | samsung,dw-mshc-sdr-timing = <2 3 3>; | 118 | samsung,dw-mshc-sdr-timing = <2 3>; |
119 | samsung,dw-mshc-ddr-timing = <1 2 3>; | 119 | samsung,dw-mshc-ddr-timing = <1 2>; |
120 | 120 | ||
121 | slot@0 { | 121 | slot@0 { |
122 | reg = <0>; | 122 | reg = <0>; |
@@ -139,8 +139,8 @@ | |||
139 | fifo-depth = <0x80>; | 139 | fifo-depth = <0x80>; |
140 | card-detect-delay = <200>; | 140 | card-detect-delay = <200>; |
141 | samsung,dw-mshc-ciu-div = <3>; | 141 | samsung,dw-mshc-ciu-div = <3>; |
142 | samsung,dw-mshc-sdr-timing = <2 3 3>; | 142 | samsung,dw-mshc-sdr-timing = <2 3>; |
143 | samsung,dw-mshc-ddr-timing = <1 2 3>; | 143 | samsung,dw-mshc-ddr-timing = <1 2>; |
144 | 144 | ||
145 | slot@0 { | 145 | slot@0 { |
146 | reg = <0>; | 146 | reg = <0>; |
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi index 9bc6785ad228..77d21abfcdf7 100644 --- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi +++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi | |||
@@ -1,4 +1,5 @@ | |||
1 | /include/ "kirkwood.dtsi" | 1 | /include/ "kirkwood.dtsi" |
2 | /include/ "kirkwood-6281.dtsi" | ||
2 | 3 | ||
3 | / { | 4 | / { |
4 | chosen { | 5 | chosen { |
@@ -6,6 +7,21 @@ | |||
6 | }; | 7 | }; |
7 | 8 | ||
8 | ocp@f1000000 { | 9 | ocp@f1000000 { |
10 | pinctrl: pinctrl@10000 { | ||
11 | pinctrl-0 = < &pmx_spi &pmx_twsi0 &pmx_uart0 | ||
12 | &pmx_ns2_sata0 &pmx_ns2_sata1>; | ||
13 | pinctrl-names = "default"; | ||
14 | |||
15 | pmx_ns2_sata0: pmx-ns2-sata0 { | ||
16 | marvell,pins = "mpp21"; | ||
17 | marvell,function = "sata0"; | ||
18 | }; | ||
19 | pmx_ns2_sata1: pmx-ns2-sata1 { | ||
20 | marvell,pins = "mpp20"; | ||
21 | marvell,function = "sata1"; | ||
22 | }; | ||
23 | }; | ||
24 | |||
9 | serial@12000 { | 25 | serial@12000 { |
10 | clock-frequency = <166666667>; | 26 | clock-frequency = <166666667>; |
11 | status = "okay"; | 27 | status = "okay"; |
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi index 110d6cbb795b..d6ab442b7011 100644 --- a/arch/arm/boot/dts/kirkwood.dtsi +++ b/arch/arm/boot/dts/kirkwood.dtsi | |||
@@ -36,6 +36,7 @@ | |||
36 | reg = <0x10100 0x40>; | 36 | reg = <0x10100 0x40>; |
37 | ngpios = <32>; | 37 | ngpios = <32>; |
38 | interrupt-controller; | 38 | interrupt-controller; |
39 | #interrupt-cells = <2>; | ||
39 | interrupts = <35>, <36>, <37>, <38>; | 40 | interrupts = <35>, <36>, <37>, <38>; |
40 | }; | 41 | }; |
41 | 42 | ||
@@ -46,6 +47,7 @@ | |||
46 | reg = <0x10140 0x40>; | 47 | reg = <0x10140 0x40>; |
47 | ngpios = <18>; | 48 | ngpios = <18>; |
48 | interrupt-controller; | 49 | interrupt-controller; |
50 | #interrupt-cells = <2>; | ||
49 | interrupts = <39>, <40>, <41>; | 51 | interrupts = <39>, <40>, <41>; |
50 | }; | 52 | }; |
51 | 53 | ||
diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts index e8814fe0e277..b4dc3ed9a3ec 100644 --- a/arch/arm/boot/dts/kizbox.dts +++ b/arch/arm/boot/dts/kizbox.dts | |||
@@ -48,6 +48,8 @@ | |||
48 | 48 | ||
49 | macb0: ethernet@fffc4000 { | 49 | macb0: ethernet@fffc4000 { |
50 | phy-mode = "mii"; | 50 | phy-mode = "mii"; |
51 | pinctrl-0 = <&pinctrl_macb_rmii | ||
52 | &pinctrl_macb_rmii_mii_alt>; | ||
51 | status = "okay"; | 53 | status = "okay"; |
52 | }; | 54 | }; |
53 | 55 | ||
diff --git a/arch/arm/boot/dts/sunxi.dtsi b/arch/arm/boot/dts/sunxi.dtsi index 8bbc2bfef221..8b36abea9f2e 100644 --- a/arch/arm/boot/dts/sunxi.dtsi +++ b/arch/arm/boot/dts/sunxi.dtsi | |||
@@ -60,19 +60,21 @@ | |||
60 | }; | 60 | }; |
61 | 61 | ||
62 | uart0: uart@01c28000 { | 62 | uart0: uart@01c28000 { |
63 | compatible = "ns8250"; | 63 | compatible = "snps,dw-apb-uart"; |
64 | reg = <0x01c28000 0x400>; | 64 | reg = <0x01c28000 0x400>; |
65 | interrupts = <1>; | 65 | interrupts = <1>; |
66 | reg-shift = <2>; | 66 | reg-shift = <2>; |
67 | reg-io-width = <4>; | ||
67 | clock-frequency = <24000000>; | 68 | clock-frequency = <24000000>; |
68 | status = "disabled"; | 69 | status = "disabled"; |
69 | }; | 70 | }; |
70 | 71 | ||
71 | uart1: uart@01c28400 { | 72 | uart1: uart@01c28400 { |
72 | compatible = "ns8250"; | 73 | compatible = "snps,dw-apb-uart"; |
73 | reg = <0x01c28400 0x400>; | 74 | reg = <0x01c28400 0x400>; |
74 | interrupts = <2>; | 75 | interrupts = <2>; |
75 | reg-shift = <2>; | 76 | reg-shift = <2>; |
77 | reg-io-width = <4>; | ||
76 | clock-frequency = <24000000>; | 78 | clock-frequency = <24000000>; |
77 | status = "disabled"; | 79 | status = "disabled"; |
78 | }; | 80 | }; |
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts index 1fc405a9ecfb..cf8071ad22d5 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts | |||
@@ -45,7 +45,6 @@ | |||
45 | reg = <1>; | 45 | reg = <1>; |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* A7s disabled till big.LITTLE patches are available... | ||
49 | cpu2: cpu@2 { | 48 | cpu2: cpu@2 { |
50 | device_type = "cpu"; | 49 | device_type = "cpu"; |
51 | compatible = "arm,cortex-a7"; | 50 | compatible = "arm,cortex-a7"; |
@@ -63,7 +62,6 @@ | |||
63 | compatible = "arm,cortex-a7"; | 62 | compatible = "arm,cortex-a7"; |
64 | reg = <0x102>; | 63 | reg = <0x102>; |
65 | }; | 64 | }; |
66 | */ | ||
67 | }; | 65 | }; |
68 | 66 | ||
69 | memory@80000000 { | 67 | memory@80000000 { |
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig index b175577d7abb..1ea959019fcd 100644 --- a/arch/arm/configs/at91_dt_defconfig +++ b/arch/arm/configs/at91_dt_defconfig | |||
@@ -19,6 +19,7 @@ CONFIG_SOC_AT91SAM9260=y | |||
19 | CONFIG_SOC_AT91SAM9263=y | 19 | CONFIG_SOC_AT91SAM9263=y |
20 | CONFIG_SOC_AT91SAM9G45=y | 20 | CONFIG_SOC_AT91SAM9G45=y |
21 | CONFIG_SOC_AT91SAM9X5=y | 21 | CONFIG_SOC_AT91SAM9X5=y |
22 | CONFIG_SOC_AT91SAM9N12=y | ||
22 | CONFIG_MACH_AT91SAM_DT=y | 23 | CONFIG_MACH_AT91SAM_DT=y |
23 | CONFIG_AT91_PROGRAMMABLE_CLOCKS=y | 24 | CONFIG_AT91_PROGRAMMABLE_CLOCKS=y |
24 | CONFIG_AT91_TIMER_HZ=128 | 25 | CONFIG_AT91_TIMER_HZ=128 |
@@ -31,7 +32,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0 | |||
31 | CONFIG_ZBOOT_ROM_BSS=0x0 | 32 | CONFIG_ZBOOT_ROM_BSS=0x0 |
32 | CONFIG_ARM_APPENDED_DTB=y | 33 | CONFIG_ARM_APPENDED_DTB=y |
33 | CONFIG_ARM_ATAG_DTB_COMPAT=y | 34 | CONFIG_ARM_ATAG_DTB_COMPAT=y |
34 | CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw" | 35 | CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw" |
35 | CONFIG_KEXEC=y | 36 | CONFIG_KEXEC=y |
36 | CONFIG_AUTO_ZRELADDR=y | 37 | CONFIG_AUTO_ZRELADDR=y |
37 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | 38 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set |
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S index 6809200c31fb..14f7c3b14632 100644 --- a/arch/arm/kernel/debug.S +++ b/arch/arm/kernel/debug.S | |||
@@ -100,12 +100,14 @@ ENTRY(printch) | |||
100 | b 1b | 100 | b 1b |
101 | ENDPROC(printch) | 101 | ENDPROC(printch) |
102 | 102 | ||
103 | #ifdef CONFIG_MMU | ||
103 | ENTRY(debug_ll_addr) | 104 | ENTRY(debug_ll_addr) |
104 | addruart r2, r3, ip | 105 | addruart r2, r3, ip |
105 | str r2, [r0] | 106 | str r2, [r0] |
106 | str r3, [r1] | 107 | str r3, [r1] |
107 | mov pc, lr | 108 | mov pc, lr |
108 | ENDPROC(debug_ll_addr) | 109 | ENDPROC(debug_ll_addr) |
110 | #endif | ||
109 | 111 | ||
110 | #else | 112 | #else |
111 | 113 | ||
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 4eee351f4668..486a15ae9011 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -246,6 +246,7 @@ __create_page_tables: | |||
246 | 246 | ||
247 | /* | 247 | /* |
248 | * Then map boot params address in r2 if specified. | 248 | * Then map boot params address in r2 if specified. |
249 | * We map 2 sections in case the ATAGs/DTB crosses a section boundary. | ||
249 | */ | 250 | */ |
250 | mov r0, r2, lsr #SECTION_SHIFT | 251 | mov r0, r2, lsr #SECTION_SHIFT |
251 | movs r0, r0, lsl #SECTION_SHIFT | 252 | movs r0, r0, lsl #SECTION_SHIFT |
@@ -253,6 +254,8 @@ __create_page_tables: | |||
253 | addne r3, r3, #PAGE_OFFSET | 254 | addne r3, r3, #PAGE_OFFSET |
254 | addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) | 255 | addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) |
255 | orrne r6, r7, r0 | 256 | orrne r6, r7, r0 |
257 | strne r6, [r3], #1 << PMD_ORDER | ||
258 | addne r6, r6, #1 << SECTION_SHIFT | ||
256 | strne r6, [r3] | 259 | strne r6, [r3] |
257 | 260 | ||
258 | #ifdef CONFIG_DEBUG_LL | 261 | #ifdef CONFIG_DEBUG_LL |
@@ -331,7 +334,7 @@ ENTRY(secondary_startup) | |||
331 | * as it has already been validated by the primary processor. | 334 | * as it has already been validated by the primary processor. |
332 | */ | 335 | */ |
333 | #ifdef CONFIG_ARM_VIRT_EXT | 336 | #ifdef CONFIG_ARM_VIRT_EXT |
334 | bl __hyp_stub_install | 337 | bl __hyp_stub_install_secondary |
335 | #endif | 338 | #endif |
336 | safe_svcmode_maskall r9 | 339 | safe_svcmode_maskall r9 |
337 | 340 | ||
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index 65b2417aebce..1315c4ccfa56 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S | |||
@@ -99,7 +99,7 @@ ENTRY(__hyp_stub_install_secondary) | |||
99 | * immediately. | 99 | * immediately. |
100 | */ | 100 | */ |
101 | compare_cpu_mode_with_primary r4, r5, r6, r7 | 101 | compare_cpu_mode_with_primary r4, r5, r6, r7 |
102 | bxne lr | 102 | movne pc, lr |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * Once we have given up on one CPU, we do not try to install the | 105 | * Once we have given up on one CPU, we do not try to install the |
@@ -111,7 +111,7 @@ ENTRY(__hyp_stub_install_secondary) | |||
111 | */ | 111 | */ |
112 | 112 | ||
113 | cmp r4, #HYP_MODE | 113 | cmp r4, #HYP_MODE |
114 | bxne lr @ give up if the CPU is not in HYP mode | 114 | movne pc, lr @ give up if the CPU is not in HYP mode |
115 | 115 | ||
116 | /* | 116 | /* |
117 | * Configure HSCTLR to set correct exception endianness/instruction set | 117 | * Configure HSCTLR to set correct exception endianness/instruction set |
@@ -120,7 +120,8 @@ ENTRY(__hyp_stub_install_secondary) | |||
120 | * Eventually, CPU-specific code might be needed -- assume not for now | 120 | * Eventually, CPU-specific code might be needed -- assume not for now |
121 | * | 121 | * |
122 | * This code relies on the "eret" instruction to synchronize the | 122 | * This code relies on the "eret" instruction to synchronize the |
123 | * various coprocessor accesses. | 123 | * various coprocessor accesses. This is done when we switch to SVC |
124 | * (see safe_svcmode_maskall). | ||
124 | */ | 125 | */ |
125 | @ Now install the hypervisor stub: | 126 | @ Now install the hypervisor stub: |
126 | adr r7, __hyp_stub_vectors | 127 | adr r7, __hyp_stub_vectors |
@@ -155,14 +156,7 @@ THUMB( orr r7, #(1 << 30) ) @ HSCTLR.TE | |||
155 | 1: | 156 | 1: |
156 | #endif | 157 | #endif |
157 | 158 | ||
158 | bic r7, r4, #MODE_MASK | 159 | bx lr @ The boot CPU mode is left in r4. |
159 | orr r7, r7, #SVC_MODE | ||
160 | THUMB( orr r7, r7, #PSR_T_BIT ) | ||
161 | msr spsr_cxsf, r7 @ This is SPSR_hyp. | ||
162 | |||
163 | __MSR_ELR_HYP(14) @ msr elr_hyp, lr | ||
164 | __ERET @ return, switching to SVC mode | ||
165 | @ The boot CPU mode is left in r4. | ||
166 | ENDPROC(__hyp_stub_install_secondary) | 160 | ENDPROC(__hyp_stub_install_secondary) |
167 | 161 | ||
168 | __hyp_stub_do_trap: | 162 | __hyp_stub_do_trap: |
@@ -200,7 +194,7 @@ ENDPROC(__hyp_get_vectors) | |||
200 | @ fall through | 194 | @ fall through |
201 | ENTRY(__hyp_set_vectors) | 195 | ENTRY(__hyp_set_vectors) |
202 | __HVC(0) | 196 | __HVC(0) |
203 | bx lr | 197 | mov pc, lr |
204 | ENDPROC(__hyp_set_vectors) | 198 | ENDPROC(__hyp_set_vectors) |
205 | 199 | ||
206 | #ifndef ZIMAGE | 200 | #ifndef ZIMAGE |
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 9ee866ce0478..4b678478cf95 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c | |||
@@ -105,6 +105,8 @@ static void __init soc_detect(u32 dbgu_base) | |||
105 | switch (socid) { | 105 | switch (socid) { |
106 | case ARCH_ID_AT91RM9200: | 106 | case ARCH_ID_AT91RM9200: |
107 | at91_soc_initdata.type = AT91_SOC_RM9200; | 107 | at91_soc_initdata.type = AT91_SOC_RM9200; |
108 | if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE) | ||
109 | at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; | ||
108 | at91_boot_soc = at91rm9200_soc; | 110 | at91_boot_soc = at91rm9200_soc; |
109 | break; | 111 | break; |
110 | 112 | ||
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 3e628fd7a674..0a2349dc7018 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig | |||
@@ -851,6 +851,7 @@ config SOC_IMX6Q | |||
851 | select HAVE_CAN_FLEXCAN if CAN | 851 | select HAVE_CAN_FLEXCAN if CAN |
852 | select HAVE_IMX_GPC | 852 | select HAVE_IMX_GPC |
853 | select HAVE_IMX_MMDC | 853 | select HAVE_IMX_MMDC |
854 | select HAVE_IMX_SRC | ||
854 | select HAVE_SMP | 855 | select HAVE_SMP |
855 | select MFD_SYSCON | 856 | select MFD_SYSCON |
856 | select PINCTRL | 857 | select PINCTRL |
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c index b197aa73dc4b..2c570cdaae7b 100644 --- a/arch/arm/mach-imx/clk-imx25.c +++ b/arch/arm/mach-imx/clk-imx25.c | |||
@@ -254,9 +254,9 @@ int __init mx25_clocks_init(void) | |||
254 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); | 254 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); |
255 | clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2"); | 255 | clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2"); |
256 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); | 256 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); |
257 | clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); | 257 | clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); |
258 | clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc"); | 258 | clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27"); |
259 | clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); | 259 | clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); |
260 | clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0"); | 260 | clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0"); |
261 | /* i.mx25 has the i.mx35 type cspi */ | 261 | /* i.mx25 has the i.mx35 type cspi */ |
262 | clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0"); | 262 | clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0"); |
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c index 4c1d1e4efc74..1ffe3b534e51 100644 --- a/arch/arm/mach-imx/clk-imx27.c +++ b/arch/arm/mach-imx/clk-imx27.c | |||
@@ -236,9 +236,9 @@ int __init mx27_clocks_init(unsigned long fref) | |||
236 | clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0"); | 236 | clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0"); |
237 | clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0"); | 237 | clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0"); |
238 | clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0"); | 238 | clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0"); |
239 | clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); | 239 | clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); |
240 | clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc"); | 240 | clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27"); |
241 | clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc"); | 241 | clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27"); |
242 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0"); | 242 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0"); |
243 | clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0"); | 243 | clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0"); |
244 | clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0"); | 244 | clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0"); |
diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c index 8be64e0a4ace..16ccbd41dea9 100644 --- a/arch/arm/mach-imx/clk-imx31.c +++ b/arch/arm/mach-imx/clk-imx31.c | |||
@@ -139,9 +139,9 @@ int __init mx31_clocks_init(unsigned long fref) | |||
139 | clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2"); | 139 | clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2"); |
140 | clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2"); | 140 | clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2"); |
141 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); | 141 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); |
142 | clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc"); | 142 | clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27"); |
143 | clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc"); | 143 | clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27"); |
144 | clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); | 144 | clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); |
145 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); | 145 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); |
146 | /* i.mx31 has the i.mx21 type uart */ | 146 | /* i.mx31 has the i.mx21 type uart */ |
147 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); | 147 | clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0"); |
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index 66f3d65ea275..f0727e80815d 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c | |||
@@ -251,9 +251,9 @@ int __init mx35_clocks_init() | |||
251 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); | 251 | clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2"); |
252 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); | 252 | clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2"); |
253 | clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2"); | 253 | clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2"); |
254 | clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc"); | 254 | clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27"); |
255 | clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc"); | 255 | clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27"); |
256 | clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc"); | 256 | clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27"); |
257 | clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); | 257 | clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0"); |
258 | clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0"); | 258 | clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0"); |
259 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); | 259 | clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); |
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c index 579023f59dc1..fb7cb841b64c 100644 --- a/arch/arm/mach-imx/clk-imx51-imx53.c +++ b/arch/arm/mach-imx/clk-imx51-imx53.c | |||
@@ -269,9 +269,9 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil, | |||
269 | clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2"); | 269 | clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2"); |
270 | clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2"); | 270 | clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2"); |
271 | clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2"); | 271 | clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2"); |
272 | clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc"); | 272 | clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51"); |
273 | clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc"); | 273 | clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51"); |
274 | clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc"); | 274 | clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51"); |
275 | clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand"); | 275 | clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand"); |
276 | clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0"); | 276 | clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0"); |
277 | clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1"); | 277 | clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1"); |
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 7f2c10c7413a..c0c4e723b7f5 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c | |||
@@ -436,6 +436,9 @@ int __init mx6q_clocks_init(void) | |||
436 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | 436 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) |
437 | clk_prepare_enable(clk[clks_init_on[i]]); | 437 | clk_prepare_enable(clk[clks_init_on[i]]); |
438 | 438 | ||
439 | /* Set initial power mode */ | ||
440 | imx6q_set_lpm(WAIT_CLOCKED); | ||
441 | |||
439 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); | 442 | np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt"); |
440 | base = of_iomap(np, 0); | 443 | base = of_iomap(np, 0); |
441 | WARN_ON(!base); | 444 | WARN_ON(!base); |
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 7191ab4434e5..fa36fb84ab19 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h | |||
@@ -142,6 +142,7 @@ extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); | |||
142 | extern void imx6q_clock_map_io(void); | 142 | extern void imx6q_clock_map_io(void); |
143 | 143 | ||
144 | extern void imx_cpu_die(unsigned int cpu); | 144 | extern void imx_cpu_die(unsigned int cpu); |
145 | extern int imx_cpu_kill(unsigned int cpu); | ||
145 | 146 | ||
146 | #ifdef CONFIG_PM | 147 | #ifdef CONFIG_PM |
147 | extern void imx6q_pm_init(void); | 148 | extern void imx6q_pm_init(void); |
diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h index 6277baf1b7be..9bd5777ff0e7 100644 --- a/arch/arm/mach-imx/devices/devices-common.h +++ b/arch/arm/mach-imx/devices/devices-common.h | |||
@@ -63,6 +63,7 @@ struct platform_device *__init imx_add_flexcan( | |||
63 | 63 | ||
64 | #include <linux/fsl_devices.h> | 64 | #include <linux/fsl_devices.h> |
65 | struct imx_fsl_usb2_udc_data { | 65 | struct imx_fsl_usb2_udc_data { |
66 | const char *devid; | ||
66 | resource_size_t iobase; | 67 | resource_size_t iobase; |
67 | resource_size_t irq; | 68 | resource_size_t irq; |
68 | }; | 69 | }; |
diff --git a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c index 37e44398197b..3c06bd96e9cc 100644 --- a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c +++ b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c | |||
@@ -11,35 +11,36 @@ | |||
11 | #include "../hardware.h" | 11 | #include "../hardware.h" |
12 | #include "devices-common.h" | 12 | #include "devices-common.h" |
13 | 13 | ||
14 | #define imx_fsl_usb2_udc_data_entry_single(soc) \ | 14 | #define imx_fsl_usb2_udc_data_entry_single(soc, _devid) \ |
15 | { \ | 15 | { \ |
16 | .devid = _devid, \ | ||
16 | .iobase = soc ## _USB_OTG_BASE_ADDR, \ | 17 | .iobase = soc ## _USB_OTG_BASE_ADDR, \ |
17 | .irq = soc ## _INT_USB_OTG, \ | 18 | .irq = soc ## _INT_USB_OTG, \ |
18 | } | 19 | } |
19 | 20 | ||
20 | #ifdef CONFIG_SOC_IMX25 | 21 | #ifdef CONFIG_SOC_IMX25 |
21 | const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst = | 22 | const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst = |
22 | imx_fsl_usb2_udc_data_entry_single(MX25); | 23 | imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27"); |
23 | #endif /* ifdef CONFIG_SOC_IMX25 */ | 24 | #endif /* ifdef CONFIG_SOC_IMX25 */ |
24 | 25 | ||
25 | #ifdef CONFIG_SOC_IMX27 | 26 | #ifdef CONFIG_SOC_IMX27 |
26 | const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst = | 27 | const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst = |
27 | imx_fsl_usb2_udc_data_entry_single(MX27); | 28 | imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27"); |
28 | #endif /* ifdef CONFIG_SOC_IMX27 */ | 29 | #endif /* ifdef CONFIG_SOC_IMX27 */ |
29 | 30 | ||
30 | #ifdef CONFIG_SOC_IMX31 | 31 | #ifdef CONFIG_SOC_IMX31 |
31 | const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst = | 32 | const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst = |
32 | imx_fsl_usb2_udc_data_entry_single(MX31); | 33 | imx_fsl_usb2_udc_data_entry_single(MX31, "imx-udc-mx27"); |
33 | #endif /* ifdef CONFIG_SOC_IMX31 */ | 34 | #endif /* ifdef CONFIG_SOC_IMX31 */ |
34 | 35 | ||
35 | #ifdef CONFIG_SOC_IMX35 | 36 | #ifdef CONFIG_SOC_IMX35 |
36 | const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst = | 37 | const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst = |
37 | imx_fsl_usb2_udc_data_entry_single(MX35); | 38 | imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27"); |
38 | #endif /* ifdef CONFIG_SOC_IMX35 */ | 39 | #endif /* ifdef CONFIG_SOC_IMX35 */ |
39 | 40 | ||
40 | #ifdef CONFIG_SOC_IMX51 | 41 | #ifdef CONFIG_SOC_IMX51 |
41 | const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst = | 42 | const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst = |
42 | imx_fsl_usb2_udc_data_entry_single(MX51); | 43 | imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51"); |
43 | #endif | 44 | #endif |
44 | 45 | ||
45 | struct platform_device *__init imx_add_fsl_usb2_udc( | 46 | struct platform_device *__init imx_add_fsl_usb2_udc( |
@@ -57,7 +58,7 @@ struct platform_device *__init imx_add_fsl_usb2_udc( | |||
57 | .flags = IORESOURCE_IRQ, | 58 | .flags = IORESOURCE_IRQ, |
58 | }, | 59 | }, |
59 | }; | 60 | }; |
60 | return imx_add_platform_device_dmamask("fsl-usb2-udc", -1, | 61 | return imx_add_platform_device_dmamask(data->devid, -1, |
61 | res, ARRAY_SIZE(res), | 62 | res, ARRAY_SIZE(res), |
62 | pdata, sizeof(*pdata), DMA_BIT_MASK(32)); | 63 | pdata, sizeof(*pdata), DMA_BIT_MASK(32)); |
63 | } | 64 | } |
diff --git a/arch/arm/mach-imx/devices/platform-imx-fb.c b/arch/arm/mach-imx/devices/platform-imx-fb.c index 10b0ed39f07f..25a47c616b2d 100644 --- a/arch/arm/mach-imx/devices/platform-imx-fb.c +++ b/arch/arm/mach-imx/devices/platform-imx-fb.c | |||
@@ -54,7 +54,7 @@ struct platform_device *__init imx_add_imx_fb( | |||
54 | .flags = IORESOURCE_IRQ, | 54 | .flags = IORESOURCE_IRQ, |
55 | }, | 55 | }, |
56 | }; | 56 | }; |
57 | return imx_add_platform_device_dmamask("imx-fb", 0, | 57 | return imx_add_platform_device_dmamask(data->devid, 0, |
58 | res, ARRAY_SIZE(res), | 58 | res, ARRAY_SIZE(res), |
59 | pdata, sizeof(*pdata), DMA_BIT_MASK(32)); | 59 | pdata, sizeof(*pdata), DMA_BIT_MASK(32)); |
60 | } | 60 | } |
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 3dec962b0770..7bc5fe15dda2 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c | |||
@@ -46,9 +46,11 @@ static inline void cpu_enter_lowpower(void) | |||
46 | void imx_cpu_die(unsigned int cpu) | 46 | void imx_cpu_die(unsigned int cpu) |
47 | { | 47 | { |
48 | cpu_enter_lowpower(); | 48 | cpu_enter_lowpower(); |
49 | imx_enable_cpu(cpu, false); | 49 | cpu_do_idle(); |
50 | } | ||
50 | 51 | ||
51 | /* spin here until hardware takes it down */ | 52 | int imx_cpu_kill(unsigned int cpu) |
52 | while (1) | 53 | { |
53 | ; | 54 | imx_enable_cpu(cpu, false); |
55 | return 1; | ||
54 | } | 56 | } |
diff --git a/arch/arm/mach-imx/iram_alloc.c b/arch/arm/mach-imx/iram_alloc.c index 6c80424f678e..e05cf407db65 100644 --- a/arch/arm/mach-imx/iram_alloc.c +++ b/arch/arm/mach-imx/iram_alloc.c | |||
@@ -22,8 +22,7 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/genalloc.h> | 24 | #include <linux/genalloc.h> |
25 | 25 | #include "linux/platform_data/imx-iram.h" | |
26 | #include "iram.h" | ||
27 | 26 | ||
28 | static unsigned long iram_phys_base; | 27 | static unsigned long iram_phys_base; |
29 | static void __iomem *iram_virt_base; | 28 | static void __iomem *iram_virt_base; |
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index 3777b805b76b..66fae885c842 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c | |||
@@ -92,5 +92,6 @@ struct smp_operations imx_smp_ops __initdata = { | |||
92 | .smp_boot_secondary = imx_boot_secondary, | 92 | .smp_boot_secondary = imx_boot_secondary, |
93 | #ifdef CONFIG_HOTPLUG_CPU | 93 | #ifdef CONFIG_HOTPLUG_CPU |
94 | .cpu_die = imx_cpu_die, | 94 | .cpu_die = imx_cpu_die, |
95 | .cpu_kill = imx_cpu_kill, | ||
95 | #endif | 96 | #endif |
96 | }; | 97 | }; |
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c index a17543da602d..ee42d20cba19 100644 --- a/arch/arm/mach-imx/pm-imx6q.c +++ b/arch/arm/mach-imx/pm-imx6q.c | |||
@@ -41,6 +41,7 @@ static int imx6q_pm_enter(suspend_state_t state) | |||
41 | cpu_suspend(0, imx6q_suspend_finish); | 41 | cpu_suspend(0, imx6q_suspend_finish); |
42 | imx_smp_prepare(); | 42 | imx_smp_prepare(); |
43 | imx_gpc_post_resume(); | 43 | imx_gpc_post_resume(); |
44 | imx6q_set_lpm(WAIT_CLOCKED); | ||
44 | break; | 45 | break; |
45 | default: | 46 | default: |
46 | return -EINVAL; | 47 | return -EINVAL; |
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index be50e795536d..e7fcea7f3300 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c | |||
@@ -475,13 +475,12 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys) | |||
475 | { | 475 | { |
476 | int ret = 0; | 476 | int ret = 0; |
477 | 477 | ||
478 | if (!ap_syscon_base) | ||
479 | return -EINVAL; | ||
480 | |||
478 | if (nr == 0) { | 481 | if (nr == 0) { |
479 | sys->mem_offset = PHYS_PCI_MEM_BASE; | 482 | sys->mem_offset = PHYS_PCI_MEM_BASE; |
480 | ret = pci_v3_setup_resources(sys); | 483 | ret = pci_v3_setup_resources(sys); |
481 | /* Remap the Integrator system controller */ | ||
482 | ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100); | ||
483 | if (!ap_syscon_base) | ||
484 | return -EINVAL; | ||
485 | } | 484 | } |
486 | 485 | ||
487 | return ret; | 486 | return ret; |
@@ -497,6 +496,13 @@ void __init pci_v3_preinit(void) | |||
497 | unsigned int temp; | 496 | unsigned int temp; |
498 | int ret; | 497 | int ret; |
499 | 498 | ||
499 | /* Remap the Integrator system controller */ | ||
500 | ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100); | ||
501 | if (!ap_syscon_base) { | ||
502 | pr_err("unable to remap the AP syscon for PCIv3\n"); | ||
503 | return; | ||
504 | } | ||
505 | |||
500 | pcibios_min_mem = 0x00100000; | 506 | pcibios_min_mem = 0x00100000; |
501 | 507 | ||
502 | /* | 508 | /* |
diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c index 8821720ab5a4..f4632a809f68 100644 --- a/arch/arm/mach-kirkwood/board-ns2.c +++ b/arch/arm/mach-kirkwood/board-ns2.c | |||
@@ -18,47 +18,11 @@ | |||
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include "common.h" | 20 | #include "common.h" |
21 | #include "mpp.h" | ||
22 | 21 | ||
23 | static struct mv643xx_eth_platform_data ns2_ge00_data = { | 22 | static struct mv643xx_eth_platform_data ns2_ge00_data = { |
24 | .phy_addr = MV643XX_ETH_PHY_ADDR(8), | 23 | .phy_addr = MV643XX_ETH_PHY_ADDR(8), |
25 | }; | 24 | }; |
26 | 25 | ||
27 | static unsigned int ns2_mpp_config[] __initdata = { | ||
28 | MPP0_SPI_SCn, | ||
29 | MPP1_SPI_MOSI, | ||
30 | MPP2_SPI_SCK, | ||
31 | MPP3_SPI_MISO, | ||
32 | MPP4_NF_IO6, | ||
33 | MPP5_NF_IO7, | ||
34 | MPP6_SYSRST_OUTn, | ||
35 | MPP7_GPO, /* Fan speed (bit 1) */ | ||
36 | MPP8_TW0_SDA, | ||
37 | MPP9_TW0_SCK, | ||
38 | MPP10_UART0_TXD, | ||
39 | MPP11_UART0_RXD, | ||
40 | MPP12_GPO, /* Red led */ | ||
41 | MPP14_GPIO, /* USB fuse */ | ||
42 | MPP16_GPIO, /* SATA 0 power */ | ||
43 | MPP17_GPIO, /* SATA 1 power */ | ||
44 | MPP18_NF_IO0, | ||
45 | MPP19_NF_IO1, | ||
46 | MPP20_SATA1_ACTn, | ||
47 | MPP21_SATA0_ACTn, | ||
48 | MPP22_GPIO, /* Fan speed (bit 0) */ | ||
49 | MPP23_GPIO, /* Fan power */ | ||
50 | MPP24_GPIO, /* USB mode select */ | ||
51 | MPP25_GPIO, /* Fan rotation fail */ | ||
52 | MPP26_GPIO, /* USB device vbus */ | ||
53 | MPP28_GPIO, /* USB enable host vbus */ | ||
54 | MPP29_GPIO, /* Blue led (slow register) */ | ||
55 | MPP30_GPIO, /* Blue led (command register) */ | ||
56 | MPP31_GPIO, /* Board power off */ | ||
57 | MPP32_GPIO, /* Power button (0 = Released, 1 = Pushed) */ | ||
58 | MPP33_GPO, /* Fan speed (bit 2) */ | ||
59 | 0 | ||
60 | }; | ||
61 | |||
62 | #define NS2_GPIO_POWER_OFF 31 | 26 | #define NS2_GPIO_POWER_OFF 31 |
63 | 27 | ||
64 | static void ns2_power_off(void) | 28 | static void ns2_power_off(void) |
@@ -71,8 +35,6 @@ void __init ns2_init(void) | |||
71 | /* | 35 | /* |
72 | * Basic setup. Needs to be called early. | 36 | * Basic setup. Needs to be called early. |
73 | */ | 37 | */ |
74 | kirkwood_mpp_conf(ns2_mpp_config); | ||
75 | |||
76 | if (of_machine_is_compatible("lacie,netspace_lite_v2") || | 38 | if (of_machine_is_compatible("lacie,netspace_lite_v2") || |
77 | of_machine_is_compatible("lacie,netspace_mini_v2")) | 39 | of_machine_is_compatible("lacie,netspace_mini_v2")) |
78 | ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0); | 40 | ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0); |
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 5dcb369b58aa..99df4df680fd 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile | |||
@@ -1,6 +1,8 @@ | |||
1 | ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ | 1 | ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \ |
2 | -I$(srctree)/arch/arm/plat-orion/include | 2 | -I$(srctree)/arch/arm/plat-orion/include |
3 | 3 | ||
4 | AFLAGS_coherency_ll.o := -Wa,-march=armv7-a | ||
5 | |||
4 | obj-y += system-controller.o | 6 | obj-y += system-controller.o |
5 | obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o | 7 | obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o |
6 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 8 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c index 5c8e9cee2c2e..769c1feee1c4 100644 --- a/arch/arm/mach-omap2/board-omap4panda.c +++ b/arch/arm/mach-omap2/board-omap4panda.c | |||
@@ -397,6 +397,12 @@ static struct omap_board_mux board_mux[] __initdata = { | |||
397 | OMAP_PULL_ENA), | 397 | OMAP_PULL_ENA), |
398 | OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), | 398 | OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT), |
399 | 399 | ||
400 | /* UART2 - BT/FM/GPS shared transport */ | ||
401 | OMAP4_MUX(UART2_CTS, OMAP_PIN_INPUT | OMAP_MUX_MODE0), | ||
402 | OMAP4_MUX(UART2_RTS, OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), | ||
403 | OMAP4_MUX(UART2_RX, OMAP_PIN_INPUT | OMAP_MUX_MODE0), | ||
404 | OMAP4_MUX(UART2_TX, OMAP_PIN_OUTPUT | OMAP_MUX_MODE0), | ||
405 | |||
400 | { .reg_offset = OMAP_MUX_TERMINATOR }, | 406 | { .reg_offset = OMAP_MUX_TERMINATOR }, |
401 | }; | 407 | }; |
402 | 408 | ||
diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c index 7e5febe456d9..ab7e952d2070 100644 --- a/arch/arm/mach-omap2/cclock2420_data.c +++ b/arch/arm/mach-omap2/cclock2420_data.c | |||
@@ -1935,6 +1935,8 @@ int __init omap2420_clk_init(void) | |||
1935 | omap2_init_clk_hw_omap_clocks(c->lk.clk); | 1935 | omap2_init_clk_hw_omap_clocks(c->lk.clk); |
1936 | } | 1936 | } |
1937 | 1937 | ||
1938 | omap2xxx_clkt_vps_late_init(); | ||
1939 | |||
1938 | omap2_clk_disable_autoidle_all(); | 1940 | omap2_clk_disable_autoidle_all(); |
1939 | 1941 | ||
1940 | omap2_clk_enable_init_clocks(enable_init_clks, | 1942 | omap2_clk_enable_init_clocks(enable_init_clks, |
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c index eda079b96c6a..eb3dab68d536 100644 --- a/arch/arm/mach-omap2/cclock2430_data.c +++ b/arch/arm/mach-omap2/cclock2430_data.c | |||
@@ -2050,6 +2050,8 @@ int __init omap2430_clk_init(void) | |||
2050 | omap2_init_clk_hw_omap_clocks(c->lk.clk); | 2050 | omap2_init_clk_hw_omap_clocks(c->lk.clk); |
2051 | } | 2051 | } |
2052 | 2052 | ||
2053 | omap2xxx_clkt_vps_late_init(); | ||
2054 | |||
2053 | omap2_clk_disable_autoidle_all(); | 2055 | omap2_clk_disable_autoidle_all(); |
2054 | 2056 | ||
2055 | omap2_clk_enable_init_clocks(enable_init_clks, | 2057 | omap2_clk_enable_init_clocks(enable_init_clks, |
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c index 5789a5e25563..a2cc046b47f4 100644 --- a/arch/arm/mach-omap2/cclock44xx_data.c +++ b/arch/arm/mach-omap2/cclock44xx_data.c | |||
@@ -2026,14 +2026,13 @@ int __init omap4xxx_clk_init(void) | |||
2026 | * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power | 2026 | * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power |
2027 | * state when turning the ABE clock domain. Workaround this by | 2027 | * state when turning the ABE clock domain. Workaround this by |
2028 | * locking the ABE DPLL on boot. | 2028 | * locking the ABE DPLL on boot. |
2029 | * Lock the ABE DPLL in any case to avoid issues with audio. | ||
2029 | */ | 2030 | */ |
2030 | if (cpu_is_omap446x()) { | 2031 | rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck); |
2031 | rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck); | 2032 | if (!rc) |
2032 | if (!rc) | 2033 | rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ); |
2033 | rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ); | 2034 | if (rc) |
2034 | if (rc) | 2035 | pr_err("%s: failed to configure ABE DPLL!\n", __func__); |
2035 | pr_err("%s: failed to configure ABE DPLL!\n", __func__); | ||
2036 | } | ||
2037 | 2036 | ||
2038 | return 0; | 2037 | return 0; |
2039 | } | 2038 | } |
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 5e304d0719a2..626f3ea3142f 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c | |||
@@ -639,7 +639,7 @@ static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev) | |||
639 | return cnt; | 639 | return cnt; |
640 | } | 640 | } |
641 | 641 | ||
642 | static void omap_init_ocp2scp(void) | 642 | static void __init omap_init_ocp2scp(void) |
643 | { | 643 | { |
644 | struct omap_hwmod *oh; | 644 | struct omap_hwmod *oh; |
645 | struct platform_device *pdev; | 645 | struct platform_device *pdev; |
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c index 4c7566c7e24a..2a2cfa88ddbf 100644 --- a/arch/arm/mach-omap2/drm.c +++ b/arch/arm/mach-omap2/drm.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
26 | #include <linux/platform_data/omap_drm.h> | 26 | #include <linux/platform_data/omap_drm.h> |
27 | 27 | ||
28 | #include "soc.h" | ||
28 | #include "omap_device.h" | 29 | #include "omap_device.h" |
29 | #include "omap_hwmod.h" | 30 | #include "omap_hwmod.h" |
30 | 31 | ||
@@ -56,7 +57,7 @@ static int __init omap_init_drm(void) | |||
56 | oh->name); | 57 | oh->name); |
57 | } | 58 | } |
58 | 59 | ||
59 | platform_data.omaprev = GET_OMAP_REVISION(); | 60 | platform_data.omaprev = GET_OMAP_TYPE; |
60 | 61 | ||
61 | return platform_device_register(&omap_drm_device); | 62 | return platform_device_register(&omap_drm_device); |
62 | 63 | ||
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 129d5081ed15..793f54ac7d14 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | |||
@@ -2132,8 +2132,12 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = { | |||
2132 | * currently reset very early during boot, before I2C is | 2132 | * currently reset very early during boot, before I2C is |
2133 | * available, so it doesn't seem that we have any choice in | 2133 | * available, so it doesn't seem that we have any choice in |
2134 | * the kernel other than to avoid resetting it. | 2134 | * the kernel other than to avoid resetting it. |
2135 | * | ||
2136 | * Also, McPDM needs to be configured to NO_IDLE mode when it | ||
2137 | * is in used otherwise vital clocks will be gated which | ||
2138 | * results 'slow motion' audio playback. | ||
2135 | */ | 2139 | */ |
2136 | .flags = HWMOD_EXT_OPT_MAIN_CLK, | 2140 | .flags = HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE, |
2137 | .mpu_irqs = omap44xx_mcpdm_irqs, | 2141 | .mpu_irqs = omap44xx_mcpdm_irqs, |
2138 | .sdma_reqs = omap44xx_mcpdm_sdma_reqs, | 2142 | .sdma_reqs = omap44xx_mcpdm_sdma_reqs, |
2139 | .main_clk = "mcpdm_fck", | 2143 | .main_clk = "mcpdm_fck", |
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 691aa674665a..b8ad6e632bb8 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -165,15 +165,11 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match, | |||
165 | struct device_node *np; | 165 | struct device_node *np; |
166 | 166 | ||
167 | for_each_matching_node(np, match) { | 167 | for_each_matching_node(np, match) { |
168 | if (!of_device_is_available(np)) { | 168 | if (!of_device_is_available(np)) |
169 | of_node_put(np); | ||
170 | continue; | 169 | continue; |
171 | } | ||
172 | 170 | ||
173 | if (property && !of_get_property(np, property, NULL)) { | 171 | if (property && !of_get_property(np, property, NULL)) |
174 | of_node_put(np); | ||
175 | continue; | 172 | continue; |
176 | } | ||
177 | 173 | ||
178 | of_add_property(np, &device_disabled); | 174 | of_add_property(np, &device_disabled); |
179 | return np; | 175 | return np; |
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index 553059f51841..755c0bb119f4 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c | |||
@@ -47,7 +47,7 @@ static struct spi_board_info wm1253_devs[] = { | |||
47 | .bus_num = 0, | 47 | .bus_num = 0, |
48 | .chip_select = 0, | 48 | .chip_select = 0, |
49 | .mode = SPI_MODE_0, | 49 | .mode = SPI_MODE_0, |
50 | .irq = S3C_EINT(5), | 50 | .irq = S3C_EINT(4), |
51 | .controller_data = &wm0010_spi_csinfo, | 51 | .controller_data = &wm0010_spi_csinfo, |
52 | .platform_data = &wm0010_pdata, | 52 | .platform_data = &wm0010_pdata, |
53 | }, | 53 | }, |
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c index 7feb426fc202..d2e1a16690bd 100644 --- a/arch/arm/mach-s3c64xx/pm.c +++ b/arch/arm/mach-s3c64xx/pm.c | |||
@@ -338,8 +338,10 @@ int __init s3c64xx_pm_init(void) | |||
338 | for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++) | 338 | for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++) |
339 | pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false); | 339 | pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false); |
340 | 340 | ||
341 | #ifdef CONFIG_S3C_DEV_FB | ||
341 | if (dev_get_platdata(&s3c_device_fb.dev)) | 342 | if (dev_get_platdata(&s3c_device_fb.dev)) |
342 | pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev); | 343 | pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev); |
344 | #endif | ||
343 | 345 | ||
344 | return 0; | 346 | return 0; |
345 | } | 347 | } |
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 6b2fb87c8698..076c26d43864 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -774,25 +774,27 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, | |||
774 | size_t size, enum dma_data_direction dir, | 774 | size_t size, enum dma_data_direction dir, |
775 | void (*op)(const void *, size_t, int)) | 775 | void (*op)(const void *, size_t, int)) |
776 | { | 776 | { |
777 | unsigned long pfn; | ||
778 | size_t left = size; | ||
779 | |||
780 | pfn = page_to_pfn(page) + offset / PAGE_SIZE; | ||
781 | offset %= PAGE_SIZE; | ||
782 | |||
777 | /* | 783 | /* |
778 | * A single sg entry may refer to multiple physically contiguous | 784 | * A single sg entry may refer to multiple physically contiguous |
779 | * pages. But we still need to process highmem pages individually. | 785 | * pages. But we still need to process highmem pages individually. |
780 | * If highmem is not configured then the bulk of this loop gets | 786 | * If highmem is not configured then the bulk of this loop gets |
781 | * optimized out. | 787 | * optimized out. |
782 | */ | 788 | */ |
783 | size_t left = size; | ||
784 | do { | 789 | do { |
785 | size_t len = left; | 790 | size_t len = left; |
786 | void *vaddr; | 791 | void *vaddr; |
787 | 792 | ||
793 | page = pfn_to_page(pfn); | ||
794 | |||
788 | if (PageHighMem(page)) { | 795 | if (PageHighMem(page)) { |
789 | if (len + offset > PAGE_SIZE) { | 796 | if (len + offset > PAGE_SIZE) |
790 | if (offset >= PAGE_SIZE) { | ||
791 | page += offset / PAGE_SIZE; | ||
792 | offset %= PAGE_SIZE; | ||
793 | } | ||
794 | len = PAGE_SIZE - offset; | 797 | len = PAGE_SIZE - offset; |
795 | } | ||
796 | vaddr = kmap_high_get(page); | 798 | vaddr = kmap_high_get(page); |
797 | if (vaddr) { | 799 | if (vaddr) { |
798 | vaddr += offset; | 800 | vaddr += offset; |
@@ -809,7 +811,7 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset, | |||
809 | op(vaddr, len, dir); | 811 | op(vaddr, len, dir); |
810 | } | 812 | } |
811 | offset = 0; | 813 | offset = 0; |
812 | page++; | 814 | pfn++; |
813 | left -= len; | 815 | left -= len; |
814 | } while (left); | 816 | } while (left); |
815 | } | 817 | } |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 9f0610243bd6..ce328c7f5c94 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -283,7 +283,7 @@ static struct mem_type mem_types[] = { | |||
283 | }, | 283 | }, |
284 | [MT_MEMORY_SO] = { | 284 | [MT_MEMORY_SO] = { |
285 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | | 285 | .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY | |
286 | L_PTE_MT_UNCACHED, | 286 | L_PTE_MT_UNCACHED | L_PTE_XN, |
287 | .prot_l1 = PMD_TYPE_TABLE, | 287 | .prot_l1 = PMD_TYPE_TABLE, |
288 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S | | 288 | .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S | |
289 | PMD_SECT_UNCACHED | PMD_SECT_XN, | 289 | PMD_SECT_UNCACHED | PMD_SECT_XN, |
diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S index dd703ef09b8d..b178d44e9eaa 100644 --- a/arch/arm/plat-versatile/headsmp.S +++ b/arch/arm/plat-versatile/headsmp.S | |||
@@ -20,7 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | ENTRY(versatile_secondary_startup) | 21 | ENTRY(versatile_secondary_startup) |
22 | mrc p15, 0, r0, c0, c0, 5 | 22 | mrc p15, 0, r0, c0, c0, 5 |
23 | and r0, r0, #15 | 23 | bic r0, #0xff000000 |
24 | adr r4, 1f | 24 | adr r4, 1f |
25 | ldmia r4, {r5, r6} | 25 | ldmia r4, {r5, r6} |
26 | sub r4, r4, r5 | 26 | sub r4, r4, r5 |
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index cc926c985981..323ce1a62bbf 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S | |||
@@ -22,7 +22,7 @@ | |||
22 | @ IRQs disabled. | 22 | @ IRQs disabled. |
23 | @ | 23 | @ |
24 | ENTRY(do_vfp) | 24 | ENTRY(do_vfp) |
25 | #ifdef CONFIG_PREEMPT | 25 | #ifdef CONFIG_PREEMPT_COUNT |
26 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count | 26 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count |
27 | add r11, r4, #1 @ increment it | 27 | add r11, r4, #1 @ increment it |
28 | str r11, [r10, #TI_PREEMPT] | 28 | str r11, [r10, #TI_PREEMPT] |
@@ -35,7 +35,7 @@ ENTRY(do_vfp) | |||
35 | ENDPROC(do_vfp) | 35 | ENDPROC(do_vfp) |
36 | 36 | ||
37 | ENTRY(vfp_null_entry) | 37 | ENTRY(vfp_null_entry) |
38 | #ifdef CONFIG_PREEMPT | 38 | #ifdef CONFIG_PREEMPT_COUNT |
39 | get_thread_info r10 | 39 | get_thread_info r10 |
40 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count | 40 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count |
41 | sub r11, r4, #1 @ decrement it | 41 | sub r11, r4, #1 @ decrement it |
@@ -53,7 +53,7 @@ ENDPROC(vfp_null_entry) | |||
53 | 53 | ||
54 | __INIT | 54 | __INIT |
55 | ENTRY(vfp_testing_entry) | 55 | ENTRY(vfp_testing_entry) |
56 | #ifdef CONFIG_PREEMPT | 56 | #ifdef CONFIG_PREEMPT_COUNT |
57 | get_thread_info r10 | 57 | get_thread_info r10 |
58 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count | 58 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count |
59 | sub r11, r4, #1 @ decrement it | 59 | sub r11, r4, #1 @ decrement it |
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index ea0349f63586..dd5e56f95f3f 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S | |||
@@ -168,7 +168,7 @@ vfp_hw_state_valid: | |||
168 | @ else it's one 32-bit instruction, so | 168 | @ else it's one 32-bit instruction, so |
169 | @ always subtract 4 from the following | 169 | @ always subtract 4 from the following |
170 | @ instruction address. | 170 | @ instruction address. |
171 | #ifdef CONFIG_PREEMPT | 171 | #ifdef CONFIG_PREEMPT_COUNT |
172 | get_thread_info r10 | 172 | get_thread_info r10 |
173 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count | 173 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count |
174 | sub r11, r4, #1 @ decrement it | 174 | sub r11, r4, #1 @ decrement it |
@@ -192,7 +192,7 @@ look_for_VFP_exceptions: | |||
192 | @ not recognised by VFP | 192 | @ not recognised by VFP |
193 | 193 | ||
194 | DBGSTR "not VFP" | 194 | DBGSTR "not VFP" |
195 | #ifdef CONFIG_PREEMPT | 195 | #ifdef CONFIG_PREEMPT_COUNT |
196 | get_thread_info r10 | 196 | get_thread_info r10 |
197 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count | 197 | ldr r4, [r10, #TI_PREEMPT] @ get preempt count |
198 | sub r11, r4, #1 @ decrement it | 198 | sub r11, r4, #1 @ decrement it |
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 801e2d7fcbc6..32ac0aef0068 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | targets += dtbs | 1 | targets += dtbs |
2 | targets += $(dtb-y) | ||
2 | 3 | ||
3 | dtbs: $(addprefix $(obj)/, $(dtb-y)) | 4 | dtbs: $(addprefix $(obj)/, $(dtb-y)) |
4 | 5 | ||
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 07fea290d7c1..fe32c0e4ac01 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h | |||
@@ -26,7 +26,10 @@ | |||
26 | 26 | ||
27 | typedef unsigned long elf_greg_t; | 27 | typedef unsigned long elf_greg_t; |
28 | 28 | ||
29 | #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) | 29 | #define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t)) |
30 | #define ELF_CORE_COPY_REGS(dest, regs) \ | ||
31 | *(struct user_pt_regs *)&(dest) = (regs)->user_regs; | ||
32 | |||
30 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; | 33 | typedef elf_greg_t elf_gregset_t[ELF_NGREG]; |
31 | typedef struct user_fpsimd_state elf_fpregset_t; | 34 | typedef struct user_fpsimd_state elf_fpregset_t; |
32 | 35 | ||
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 64b133949502..e333a243bfcc 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h | |||
@@ -24,7 +24,8 @@ | |||
24 | /* | 24 | /* |
25 | * Software defined PTE bits definition. | 25 | * Software defined PTE bits definition. |
26 | */ | 26 | */ |
27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) /* pte_present() check */ | 27 | #define PTE_VALID (_AT(pteval_t, 1) << 0) |
28 | #define PTE_PROT_NONE (_AT(pteval_t, 1) << 1) /* only when !PTE_VALID */ | ||
28 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ | 29 | #define PTE_FILE (_AT(pteval_t, 1) << 2) /* only when !pte_present() */ |
29 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) | 30 | #define PTE_DIRTY (_AT(pteval_t, 1) << 55) |
30 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) | 31 | #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) |
@@ -60,9 +61,12 @@ extern void __pgd_error(const char *file, int line, unsigned long val); | |||
60 | 61 | ||
61 | extern pgprot_t pgprot_default; | 62 | extern pgprot_t pgprot_default; |
62 | 63 | ||
63 | #define _MOD_PROT(p, b) __pgprot(pgprot_val(p) | (b)) | 64 | #define __pgprot_modify(prot,mask,bits) \ |
65 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
66 | |||
67 | #define _MOD_PROT(p, b) __pgprot_modify(p, 0, b) | ||
64 | 68 | ||
65 | #define PAGE_NONE _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 69 | #define PAGE_NONE __pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE) |
66 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 70 | #define PAGE_SHARED _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
67 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) | 71 | #define PAGE_SHARED_EXEC _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN) |
68 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 72 | #define PAGE_COPY _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
@@ -72,7 +76,7 @@ extern pgprot_t pgprot_default; | |||
72 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) | 76 | #define PAGE_KERNEL _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY) |
73 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) | 77 | #define PAGE_KERNEL_EXEC _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY) |
74 | 78 | ||
75 | #define __PAGE_NONE __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 79 | #define __PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE) |
76 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) | 80 | #define __PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN) |
77 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) | 81 | #define __PAGE_SHARED_EXEC __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN) |
78 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) | 82 | #define __PAGE_COPY __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY) |
@@ -125,16 +129,15 @@ extern struct page *empty_zero_page; | |||
125 | /* | 129 | /* |
126 | * The following only work if pte_present(). Undefined behaviour otherwise. | 130 | * The following only work if pte_present(). Undefined behaviour otherwise. |
127 | */ | 131 | */ |
128 | #define pte_present(pte) (pte_val(pte) & PTE_VALID) | 132 | #define pte_present(pte) (pte_val(pte) & (PTE_VALID | PTE_PROT_NONE)) |
129 | #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) | 133 | #define pte_dirty(pte) (pte_val(pte) & PTE_DIRTY) |
130 | #define pte_young(pte) (pte_val(pte) & PTE_AF) | 134 | #define pte_young(pte) (pte_val(pte) & PTE_AF) |
131 | #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) | 135 | #define pte_special(pte) (pte_val(pte) & PTE_SPECIAL) |
132 | #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) | 136 | #define pte_write(pte) (!(pte_val(pte) & PTE_RDONLY)) |
133 | #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) | 137 | #define pte_exec(pte) (!(pte_val(pte) & PTE_UXN)) |
134 | 138 | ||
135 | #define pte_present_exec_user(pte) \ | 139 | #define pte_valid_user(pte) \ |
136 | ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \ | 140 | ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) |
137 | (PTE_VALID | PTE_USER)) | ||
138 | 141 | ||
139 | #define PTE_BIT_FUNC(fn,op) \ | 142 | #define PTE_BIT_FUNC(fn,op) \ |
140 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 143 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } |
@@ -157,10 +160,13 @@ extern void __sync_icache_dcache(pte_t pteval, unsigned long addr); | |||
157 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 160 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
158 | pte_t *ptep, pte_t pte) | 161 | pte_t *ptep, pte_t pte) |
159 | { | 162 | { |
160 | if (pte_present_exec_user(pte)) | 163 | if (pte_valid_user(pte)) { |
161 | __sync_icache_dcache(pte, addr); | 164 | if (pte_exec(pte)) |
162 | if (!pte_dirty(pte)) | 165 | __sync_icache_dcache(pte, addr); |
163 | pte = pte_wrprotect(pte); | 166 | if (!pte_dirty(pte)) |
167 | pte = pte_wrprotect(pte); | ||
168 | } | ||
169 | |||
164 | set_pte(ptep, pte); | 170 | set_pte(ptep, pte); |
165 | } | 171 | } |
166 | 172 | ||
@@ -170,9 +176,6 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
170 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) | 176 | #define pte_huge(pte) ((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE) |
171 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) | 177 | #define pte_mkhuge(pte) (__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE)) |
172 | 178 | ||
173 | #define __pgprot_modify(prot,mask,bits) \ | ||
174 | __pgprot((pgprot_val(prot) & ~(mask)) | (bits)) | ||
175 | |||
176 | #define __HAVE_ARCH_PTE_SPECIAL | 179 | #define __HAVE_ARCH_PTE_SPECIAL |
177 | 180 | ||
178 | /* | 181 | /* |
@@ -264,7 +267,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr) | |||
264 | 267 | ||
265 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | 268 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
266 | { | 269 | { |
267 | const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY; | 270 | const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY | |
271 | PTE_PROT_NONE | PTE_VALID; | ||
268 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); | 272 | pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask); |
269 | return pte; | 273 | return pte; |
270 | } | 274 | } |
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 58432625fdb3..5ef47ba3ed45 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h | |||
@@ -395,8 +395,13 @@ __SYSCALL(370, sys_name_to_handle_at) | |||
395 | __SYSCALL(371, compat_sys_open_by_handle_at) | 395 | __SYSCALL(371, compat_sys_open_by_handle_at) |
396 | __SYSCALL(372, compat_sys_clock_adjtime) | 396 | __SYSCALL(372, compat_sys_clock_adjtime) |
397 | __SYSCALL(373, sys_syncfs) | 397 | __SYSCALL(373, sys_syncfs) |
398 | __SYSCALL(374, compat_sys_sendmmsg) | ||
399 | __SYSCALL(375, sys_setns) | ||
400 | __SYSCALL(376, compat_sys_process_vm_readv) | ||
401 | __SYSCALL(377, compat_sys_process_vm_writev) | ||
402 | __SYSCALL(378, sys_ni_syscall) /* 378 for kcmp */ | ||
398 | 403 | ||
399 | #define __NR_compat_syscalls 374 | 404 | #define __NR_compat_syscalls 379 |
400 | 405 | ||
401 | /* | 406 | /* |
402 | * Compat syscall numbers used by the AArch64 kernel. | 407 | * Compat syscall numbers used by the AArch64 kernel. |
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index c958cb84d75f..6a389dc1bd49 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c | |||
@@ -252,10 +252,6 @@ void update_vsyscall(struct timekeeper *tk) | |||
252 | 252 | ||
253 | void update_vsyscall_tz(void) | 253 | void update_vsyscall_tz(void) |
254 | { | 254 | { |
255 | ++vdso_data->tb_seq_count; | ||
256 | smp_wmb(); | ||
257 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | 255 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; |
258 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; | 256 | vdso_data->tz_dsttime = sys_tz.tz_dsttime; |
259 | smp_wmb(); | ||
260 | ++vdso_data->tb_seq_count; | ||
261 | } | 257 | } |
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index 8bf658d974f9..f0a6d10b5211 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S | |||
@@ -73,8 +73,6 @@ ENTRY(__kernel_gettimeofday) | |||
73 | /* If tz is NULL, return 0. */ | 73 | /* If tz is NULL, return 0. */ |
74 | cbz x1, 3f | 74 | cbz x1, 3f |
75 | ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] | 75 | ldp w4, w5, [vdso_data, #VDSO_TZ_MINWEST] |
76 | seqcnt_read w9 | ||
77 | seqcnt_check w9, 1b | ||
78 | stp w4, w5, [x1, #TZ_MINWEST] | 76 | stp w4, w5, [x1, #TZ_MINWEST] |
79 | 3: | 77 | 3: |
80 | mov x0, xzr | 78 | mov x0, xzr |
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 4265ff64219b..b7a5fffe0924 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -672,33 +672,6 @@ ptrace_attach_sync_user_rbs (struct task_struct *child) | |||
672 | read_unlock(&tasklist_lock); | 672 | read_unlock(&tasklist_lock); |
673 | } | 673 | } |
674 | 674 | ||
675 | static inline int | ||
676 | thread_matches (struct task_struct *thread, unsigned long addr) | ||
677 | { | ||
678 | unsigned long thread_rbs_end; | ||
679 | struct pt_regs *thread_regs; | ||
680 | |||
681 | if (ptrace_check_attach(thread, 0) < 0) | ||
682 | /* | ||
683 | * If the thread is not in an attachable state, we'll | ||
684 | * ignore it. The net effect is that if ADDR happens | ||
685 | * to overlap with the portion of the thread's | ||
686 | * register backing store that is currently residing | ||
687 | * on the thread's kernel stack, then ptrace() may end | ||
688 | * up accessing a stale value. But if the thread | ||
689 | * isn't stopped, that's a problem anyhow, so we're | ||
690 | * doing as well as we can... | ||
691 | */ | ||
692 | return 0; | ||
693 | |||
694 | thread_regs = task_pt_regs(thread); | ||
695 | thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL); | ||
696 | if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end)) | ||
697 | return 0; | ||
698 | |||
699 | return 1; /* looks like we've got a winner */ | ||
700 | } | ||
701 | |||
702 | /* | 675 | /* |
703 | * Write f32-f127 back to task->thread.fph if it has been modified. | 676 | * Write f32-f127 back to task->thread.fph if it has been modified. |
704 | */ | 677 | */ |
diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h index 17f7a45948ea..3e6b8445af6a 100644 --- a/arch/m68k/include/asm/dma-mapping.h +++ b/arch/m68k/include/asm/dma-mapping.h | |||
@@ -21,6 +21,22 @@ extern void *dma_alloc_coherent(struct device *, size_t, | |||
21 | extern void dma_free_coherent(struct device *, size_t, | 21 | extern void dma_free_coherent(struct device *, size_t, |
22 | void *, dma_addr_t); | 22 | void *, dma_addr_t); |
23 | 23 | ||
24 | static inline void *dma_alloc_attrs(struct device *dev, size_t size, | ||
25 | dma_addr_t *dma_handle, gfp_t flag, | ||
26 | struct dma_attrs *attrs) | ||
27 | { | ||
28 | /* attrs is not supported and ignored */ | ||
29 | return dma_alloc_coherent(dev, size, dma_handle, flag); | ||
30 | } | ||
31 | |||
32 | static inline void dma_free_attrs(struct device *dev, size_t size, | ||
33 | void *cpu_addr, dma_addr_t dma_handle, | ||
34 | struct dma_attrs *attrs) | ||
35 | { | ||
36 | /* attrs is not supported and ignored */ | ||
37 | dma_free_coherent(dev, size, cpu_addr, dma_handle); | ||
38 | } | ||
39 | |||
24 | static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, | 40 | static inline void *dma_alloc_noncoherent(struct device *dev, size_t size, |
25 | dma_addr_t *handle, gfp_t flag) | 41 | dma_addr_t *handle, gfp_t flag) |
26 | { | 42 | { |
diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h index bf86b29fe64a..037028f4ab70 100644 --- a/arch/m68k/include/asm/pgtable_no.h +++ b/arch/m68k/include/asm/pgtable_no.h | |||
@@ -64,6 +64,8 @@ extern unsigned int kobjsize(const void *objp); | |||
64 | */ | 64 | */ |
65 | #define VMALLOC_START 0 | 65 | #define VMALLOC_START 0 |
66 | #define VMALLOC_END 0xffffffff | 66 | #define VMALLOC_END 0xffffffff |
67 | #define KMAP_START 0 | ||
68 | #define KMAP_END 0xffffffff | ||
67 | 69 | ||
68 | #include <asm-generic/pgtable.h> | 70 | #include <asm-generic/pgtable.h> |
69 | 71 | ||
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h index 847994ce6804..f9337f614660 100644 --- a/arch/m68k/include/asm/unistd.h +++ b/arch/m68k/include/asm/unistd.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <uapi/asm/unistd.h> | 4 | #include <uapi/asm/unistd.h> |
5 | 5 | ||
6 | 6 | ||
7 | #define NR_syscalls 348 | 7 | #define NR_syscalls 349 |
8 | 8 | ||
9 | #define __ARCH_WANT_OLD_READDIR | 9 | #define __ARCH_WANT_OLD_READDIR |
10 | #define __ARCH_WANT_OLD_STAT | 10 | #define __ARCH_WANT_OLD_STAT |
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h index b94bfbf90705..625f321001dc 100644 --- a/arch/m68k/include/uapi/asm/unistd.h +++ b/arch/m68k/include/uapi/asm/unistd.h | |||
@@ -353,5 +353,6 @@ | |||
353 | #define __NR_process_vm_readv 345 | 353 | #define __NR_process_vm_readv 345 |
354 | #define __NR_process_vm_writev 346 | 354 | #define __NR_process_vm_writev 346 |
355 | #define __NR_kcmp 347 | 355 | #define __NR_kcmp 347 |
356 | #define __NR_finit_module 348 | ||
356 | 357 | ||
357 | #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ | 358 | #endif /* _UAPI_ASM_M68K_UNISTD_H_ */ |
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S index c30da5b3f2db..3f04ea0ab802 100644 --- a/arch/m68k/kernel/syscalltable.S +++ b/arch/m68k/kernel/syscalltable.S | |||
@@ -368,4 +368,5 @@ ENTRY(sys_call_table) | |||
368 | .long sys_process_vm_readv /* 345 */ | 368 | .long sys_process_vm_readv /* 345 */ |
369 | .long sys_process_vm_writev | 369 | .long sys_process_vm_writev |
370 | .long sys_kcmp | 370 | .long sys_kcmp |
371 | .long sys_finit_module | ||
371 | 372 | ||
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c index f0e05bce92f2..afd8106fd83b 100644 --- a/arch/m68k/mm/init.c +++ b/arch/m68k/mm/init.c | |||
@@ -39,6 +39,11 @@ | |||
39 | void *empty_zero_page; | 39 | void *empty_zero_page; |
40 | EXPORT_SYMBOL(empty_zero_page); | 40 | EXPORT_SYMBOL(empty_zero_page); |
41 | 41 | ||
42 | #if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE) | ||
43 | extern void init_pointer_table(unsigned long ptable); | ||
44 | extern pmd_t *zero_pgtable; | ||
45 | #endif | ||
46 | |||
42 | #ifdef CONFIG_MMU | 47 | #ifdef CONFIG_MMU |
43 | 48 | ||
44 | pg_data_t pg_data_map[MAX_NUMNODES]; | 49 | pg_data_t pg_data_map[MAX_NUMNODES]; |
@@ -69,9 +74,6 @@ void __init m68k_setup_node(int node) | |||
69 | node_set_online(node); | 74 | node_set_online(node); |
70 | } | 75 | } |
71 | 76 | ||
72 | extern void init_pointer_table(unsigned long ptable); | ||
73 | extern pmd_t *zero_pgtable; | ||
74 | |||
75 | #else /* CONFIG_MMU */ | 77 | #else /* CONFIG_MMU */ |
76 | 78 | ||
77 | /* | 79 | /* |
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig index aa03f2e13385..e70001cfa05b 100644 --- a/arch/mn10300/Kconfig +++ b/arch/mn10300/Kconfig | |||
@@ -6,6 +6,7 @@ config MN10300 | |||
6 | select ARCH_WANT_IPC_PARSE_VERSION | 6 | select ARCH_WANT_IPC_PARSE_VERSION |
7 | select HAVE_ARCH_TRACEHOOK | 7 | select HAVE_ARCH_TRACEHOOK |
8 | select HAVE_ARCH_KGDB | 8 | select HAVE_ARCH_KGDB |
9 | select GENERIC_ATOMIC64 | ||
9 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER | 10 | select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER |
10 | select GENERIC_CLOCKEVENTS | 11 | select GENERIC_CLOCKEVENTS |
11 | select MODULES_USE_ELF_RELA | 12 | select MODULES_USE_ELF_RELA |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index bfb44247d7a7..eb7850b46c25 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
@@ -1865,7 +1865,7 @@ syscall_restore: | |||
1865 | 1865 | ||
1866 | /* Are we being ptraced? */ | 1866 | /* Are we being ptraced? */ |
1867 | ldw TASK_FLAGS(%r1),%r19 | 1867 | ldw TASK_FLAGS(%r1),%r19 |
1868 | ldi (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2 | 1868 | ldi _TIF_SYSCALL_TRACE_MASK,%r2 |
1869 | and,COND(=) %r19,%r2,%r0 | 1869 | and,COND(=) %r19,%r2,%r0 |
1870 | b,n syscall_restore_rfi | 1870 | b,n syscall_restore_rfi |
1871 | 1871 | ||
@@ -1978,15 +1978,23 @@ syscall_restore_rfi: | |||
1978 | /* sr2 should be set to zero for userspace syscalls */ | 1978 | /* sr2 should be set to zero for userspace syscalls */ |
1979 | STREG %r0,TASK_PT_SR2(%r1) | 1979 | STREG %r0,TASK_PT_SR2(%r1) |
1980 | 1980 | ||
1981 | pt_regs_ok: | ||
1982 | LDREG TASK_PT_GR31(%r1),%r2 | 1981 | LDREG TASK_PT_GR31(%r1),%r2 |
1983 | depi 3,31,2,%r2 /* ensure return to user mode. */ | 1982 | depi 3,31,2,%r2 /* ensure return to user mode. */ |
1984 | STREG %r2,TASK_PT_IAOQ0(%r1) | 1983 | STREG %r2,TASK_PT_IAOQ0(%r1) |
1985 | ldo 4(%r2),%r2 | 1984 | ldo 4(%r2),%r2 |
1986 | STREG %r2,TASK_PT_IAOQ1(%r1) | 1985 | STREG %r2,TASK_PT_IAOQ1(%r1) |
1986 | b intr_restore | ||
1987 | copy %r25,%r16 | 1987 | copy %r25,%r16 |
1988 | |||
1989 | pt_regs_ok: | ||
1990 | LDREG TASK_PT_IAOQ0(%r1),%r2 | ||
1991 | depi 3,31,2,%r2 /* ensure return to user mode. */ | ||
1992 | STREG %r2,TASK_PT_IAOQ0(%r1) | ||
1993 | LDREG TASK_PT_IAOQ1(%r1),%r2 | ||
1994 | depi 3,31,2,%r2 | ||
1995 | STREG %r2,TASK_PT_IAOQ1(%r1) | ||
1988 | b intr_restore | 1996 | b intr_restore |
1989 | nop | 1997 | copy %r25,%r16 |
1990 | 1998 | ||
1991 | .import schedule,code | 1999 | .import schedule,code |
1992 | syscall_do_resched: | 2000 | syscall_do_resched: |
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index c0b1affc06a8..0299d63cd112 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c | |||
@@ -410,11 +410,13 @@ void __init init_IRQ(void) | |||
410 | { | 410 | { |
411 | local_irq_disable(); /* PARANOID - should already be disabled */ | 411 | local_irq_disable(); /* PARANOID - should already be disabled */ |
412 | mtctl(~0UL, 23); /* EIRR : clear all pending external intr */ | 412 | mtctl(~0UL, 23); /* EIRR : clear all pending external intr */ |
413 | claim_cpu_irqs(); | ||
414 | #ifdef CONFIG_SMP | 413 | #ifdef CONFIG_SMP |
415 | if (!cpu_eiem) | 414 | if (!cpu_eiem) { |
415 | claim_cpu_irqs(); | ||
416 | cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ); | 416 | cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ); |
417 | } | ||
417 | #else | 418 | #else |
419 | claim_cpu_irqs(); | ||
418 | cpu_eiem = EIEM_MASK(TIMER_IRQ); | 420 | cpu_eiem = EIEM_MASK(TIMER_IRQ); |
419 | #endif | 421 | #endif |
420 | set_eiem(cpu_eiem); /* EIEM : enable all external intr */ | 422 | set_eiem(cpu_eiem); /* EIEM : enable all external intr */ |
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 857c2f545470..534abd4936e1 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <asm/asm-offsets.h> | 26 | #include <asm/asm-offsets.h> |
27 | 27 | ||
28 | /* PSW bits we allow the debugger to modify */ | 28 | /* PSW bits we allow the debugger to modify */ |
29 | #define USER_PSW_BITS (PSW_N | PSW_V | PSW_CB) | 29 | #define USER_PSW_BITS (PSW_N | PSW_B | PSW_V | PSW_CB) |
30 | 30 | ||
31 | /* | 31 | /* |
32 | * Called by kernel/ptrace.c when detaching.. | 32 | * Called by kernel/ptrace.c when detaching.. |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 537996955998..fd051705a407 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -190,8 +190,10 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | |||
190 | DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n", | 190 | DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n", |
191 | (unsigned long)ka, sp, frame_size); | 191 | (unsigned long)ka, sp, frame_size); |
192 | 192 | ||
193 | /* Align alternate stack and reserve 64 bytes for the signal | ||
194 | handler's frame marker. */ | ||
193 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) | 195 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) |
194 | sp = current->sas_ss_sp; /* Stacks grow up! */ | 196 | sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */ |
195 | 197 | ||
196 | DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp); | 198 | DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp); |
197 | return (void __user *) sp; /* Stacks grow up. Fun. */ | 199 | return (void __user *) sp; /* Stacks grow up. Fun. */ |
diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h index 9071e093164a..933423fa5144 100644 --- a/arch/parisc/math-emu/cnv_float.h +++ b/arch/parisc/math-emu/cnv_float.h | |||
@@ -347,16 +347,15 @@ | |||
347 | Sgl_isinexact_to_fix(sgl_value,exponent) | 347 | Sgl_isinexact_to_fix(sgl_value,exponent) |
348 | 348 | ||
349 | #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ | 349 | #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB) \ |
350 | {Sall(sgl_value) <<= SGL_EXP_LENGTH; /* left-justify */ \ | 350 | {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH; \ |
351 | if (exponent <= 31) { \ | 351 | if (exponent <= 31) { \ |
352 | Dintp1(dresultA) = 0; \ | 352 | Dintp1(dresultA) = 0; \ |
353 | Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \ | 353 | Dintp2(dresultB) = val >> (31 - exponent); \ |
354 | } \ | 354 | } \ |
355 | else { \ | 355 | else { \ |
356 | Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent); \ | 356 | Dintp1(dresultA) = val >> (63 - exponent); \ |
357 | Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31); \ | 357 | Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0; \ |
358 | } \ | 358 | } \ |
359 | Sall(sgl_value) >>= SGL_EXP_LENGTH; /* return to original */ \ | ||
360 | } | 359 | } |
361 | 360 | ||
362 | #define Duint_setzero(dresultA,dresultB) \ | 361 | #define Duint_setzero(dresultA,dresultB) \ |
diff --git a/arch/powerpc/include/uapi/asm/kvm_para.h b/arch/powerpc/include/uapi/asm/kvm_para.h index ed0e0254b47f..e3af3286a068 100644 --- a/arch/powerpc/include/uapi/asm/kvm_para.h +++ b/arch/powerpc/include/uapi/asm/kvm_para.h | |||
@@ -78,7 +78,7 @@ struct kvm_vcpu_arch_shared { | |||
78 | 78 | ||
79 | #define KVM_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num) | 79 | #define KVM_HCALL_TOKEN(num) _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num) |
80 | 80 | ||
81 | #include <uapi/asm/epapr_hcalls.h> | 81 | #include <asm/epapr_hcalls.h> |
82 | 82 | ||
83 | #define KVM_FEATURE_MAGIC_PAGE 1 | 83 | #define KVM_FEATURE_MAGIC_PAGE 1 |
84 | 84 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index 35f3cf0269b3..a353c485808c 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c | |||
@@ -79,7 +79,9 @@ static void flush_tlb_power7(struct kvm_vcpu *vcpu) | |||
79 | static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) | 79 | static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) |
80 | { | 80 | { |
81 | unsigned long srr1 = vcpu->arch.shregs.msr; | 81 | unsigned long srr1 = vcpu->arch.shregs.msr; |
82 | #ifdef CONFIG_PPC_POWERNV | ||
82 | struct opal_machine_check_event *opal_evt; | 83 | struct opal_machine_check_event *opal_evt; |
84 | #endif | ||
83 | long handled = 1; | 85 | long handled = 1; |
84 | 86 | ||
85 | if (srr1 & SRR1_MC_LDSTERR) { | 87 | if (srr1 & SRR1_MC_LDSTERR) { |
@@ -117,6 +119,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) | |||
117 | handled = 0; | 119 | handled = 0; |
118 | } | 120 | } |
119 | 121 | ||
122 | #ifdef CONFIG_PPC_POWERNV | ||
120 | /* | 123 | /* |
121 | * See if OPAL has already handled the condition. | 124 | * See if OPAL has already handled the condition. |
122 | * We assume that if the condition is recovered then OPAL | 125 | * We assume that if the condition is recovered then OPAL |
@@ -131,6 +134,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) | |||
131 | 134 | ||
132 | if (handled) | 135 | if (handled) |
133 | opal_evt->in_use = 0; | 136 | opal_evt->in_use = 0; |
137 | #endif | ||
134 | 138 | ||
135 | return handled; | 139 | return handled; |
136 | } | 140 | } |
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index b0855e5d8905..9d9cddc5b346 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #define OP_31_XOP_TRAP 4 | 39 | #define OP_31_XOP_TRAP 4 |
40 | #define OP_31_XOP_LWZX 23 | 40 | #define OP_31_XOP_LWZX 23 |
41 | #define OP_31_XOP_TRAP_64 68 | 41 | #define OP_31_XOP_TRAP_64 68 |
42 | #define OP_31_XOP_DCBF 86 | ||
42 | #define OP_31_XOP_LBZX 87 | 43 | #define OP_31_XOP_LBZX 87 |
43 | #define OP_31_XOP_STWX 151 | 44 | #define OP_31_XOP_STWX 151 |
44 | #define OP_31_XOP_STBX 215 | 45 | #define OP_31_XOP_STBX 215 |
@@ -374,6 +375,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
374 | emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); | 375 | emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); |
375 | break; | 376 | break; |
376 | 377 | ||
378 | case OP_31_XOP_DCBF: | ||
377 | case OP_31_XOP_DCBI: | 379 | case OP_31_XOP_DCBI: |
378 | /* Do nothing. The guest is performing dcbi because | 380 | /* Do nothing. The guest is performing dcbi because |
379 | * hardware DMA is not snooped by the dcache, but | 381 | * hardware DMA is not snooped by the dcache, but |
diff --git a/arch/s390/Makefile b/arch/s390/Makefile index 4b8e08b56f49..7e3ce78d4290 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile | |||
@@ -24,8 +24,8 @@ CHECKFLAGS += -D__s390__ -msize-long | |||
24 | else | 24 | else |
25 | LD_BFD := elf64-s390 | 25 | LD_BFD := elf64-s390 |
26 | LDFLAGS := -m elf64_s390 | 26 | LDFLAGS := -m elf64_s390 |
27 | KBUILD_AFLAGS_MODULE += -fpic -D__PIC__ | 27 | KBUILD_AFLAGS_MODULE += -fPIC |
28 | KBUILD_CFLAGS_MODULE += -fpic -D__PIC__ | 28 | KBUILD_CFLAGS_MODULE += -fPIC |
29 | KBUILD_CFLAGS += -m64 | 29 | KBUILD_CFLAGS += -m64 |
30 | KBUILD_AFLAGS += -m64 | 30 | KBUILD_AFLAGS += -m64 |
31 | UTS_MACHINE := s390x | 31 | UTS_MACHINE := s390x |
diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h index de015d85e3e5..bb9bdcd20864 100644 --- a/arch/s390/include/asm/dma.h +++ b/arch/s390/include/asm/dma.h | |||
@@ -10,4 +10,10 @@ | |||
10 | */ | 10 | */ |
11 | #define MAX_DMA_ADDRESS 0x80000000 | 11 | #define MAX_DMA_ADDRESS 0x80000000 |
12 | 12 | ||
13 | #ifdef CONFIG_PCI | ||
14 | extern int isa_dma_bridge_buggy; | ||
15 | #else | ||
16 | #define isa_dma_bridge_buggy (0) | ||
17 | #endif | ||
18 | |||
13 | #endif /* _ASM_S390_DMA_H */ | 19 | #endif /* _ASM_S390_DMA_H */ |
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index 16c3eb164f4f..27cb32185ce1 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h | |||
@@ -85,6 +85,11 @@ static inline void iounmap(volatile void __iomem *addr) | |||
85 | #define __raw_writel zpci_write_u32 | 85 | #define __raw_writel zpci_write_u32 |
86 | #define __raw_writeq zpci_write_u64 | 86 | #define __raw_writeq zpci_write_u64 |
87 | 87 | ||
88 | #define readb_relaxed readb | ||
89 | #define readw_relaxed readw | ||
90 | #define readl_relaxed readl | ||
91 | #define readq_relaxed readq | ||
92 | |||
88 | #endif /* CONFIG_PCI */ | 93 | #endif /* CONFIG_PCI */ |
89 | 94 | ||
90 | #include <asm-generic/io.h> | 95 | #include <asm-generic/io.h> |
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index e6972f85d2b0..7def77302d63 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -2,43 +2,61 @@ | |||
2 | #define _ASM_IRQ_H | 2 | #define _ASM_IRQ_H |
3 | 3 | ||
4 | #include <linux/hardirq.h> | 4 | #include <linux/hardirq.h> |
5 | #include <linux/percpu.h> | ||
6 | #include <linux/cache.h> | ||
5 | #include <linux/types.h> | 7 | #include <linux/types.h> |
6 | 8 | ||
7 | enum interruption_class { | 9 | enum interruption_main_class { |
8 | EXTERNAL_INTERRUPT, | 10 | EXTERNAL_INTERRUPT, |
9 | IO_INTERRUPT, | 11 | IO_INTERRUPT, |
10 | EXTINT_CLK, | 12 | NR_IRQS |
11 | EXTINT_EXC, | 13 | }; |
12 | EXTINT_EMS, | 14 | |
13 | EXTINT_TMR, | 15 | enum interruption_class { |
14 | EXTINT_TLA, | 16 | IRQEXT_CLK, |
15 | EXTINT_PFL, | 17 | IRQEXT_EXC, |
16 | EXTINT_DSD, | 18 | IRQEXT_EMS, |
17 | EXTINT_VRT, | 19 | IRQEXT_TMR, |
18 | EXTINT_SCP, | 20 | IRQEXT_TLA, |
19 | EXTINT_IUC, | 21 | IRQEXT_PFL, |
20 | EXTINT_CMS, | 22 | IRQEXT_DSD, |
21 | EXTINT_CMC, | 23 | IRQEXT_VRT, |
22 | EXTINT_CMR, | 24 | IRQEXT_SCP, |
23 | IOINT_CIO, | 25 | IRQEXT_IUC, |
24 | IOINT_QAI, | 26 | IRQEXT_CMS, |
25 | IOINT_DAS, | 27 | IRQEXT_CMC, |
26 | IOINT_C15, | 28 | IRQEXT_CMR, |
27 | IOINT_C70, | 29 | IRQIO_CIO, |
28 | IOINT_TAP, | 30 | IRQIO_QAI, |
29 | IOINT_VMR, | 31 | IRQIO_DAS, |
30 | IOINT_LCS, | 32 | IRQIO_C15, |
31 | IOINT_CLW, | 33 | IRQIO_C70, |
32 | IOINT_CTC, | 34 | IRQIO_TAP, |
33 | IOINT_APB, | 35 | IRQIO_VMR, |
34 | IOINT_ADM, | 36 | IRQIO_LCS, |
35 | IOINT_CSC, | 37 | IRQIO_CLW, |
36 | IOINT_PCI, | 38 | IRQIO_CTC, |
37 | IOINT_MSI, | 39 | IRQIO_APB, |
40 | IRQIO_ADM, | ||
41 | IRQIO_CSC, | ||
42 | IRQIO_PCI, | ||
43 | IRQIO_MSI, | ||
38 | NMI_NMI, | 44 | NMI_NMI, |
39 | NR_IRQS, | 45 | CPU_RST, |
46 | NR_ARCH_IRQS | ||
40 | }; | 47 | }; |
41 | 48 | ||
49 | struct irq_stat { | ||
50 | unsigned int irqs[NR_ARCH_IRQS]; | ||
51 | }; | ||
52 | |||
53 | DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); | ||
54 | |||
55 | static __always_inline void inc_irq_stat(enum interruption_class irq) | ||
56 | { | ||
57 | __get_cpu_var(irq_stat).irqs[irq]++; | ||
58 | } | ||
59 | |||
42 | struct ext_code { | 60 | struct ext_code { |
43 | unsigned short subcode; | 61 | unsigned short subcode; |
44 | unsigned short code; | 62 | unsigned short code; |
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index c928dc1938f2..c1d7930a82f4 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h | |||
@@ -1387,10 +1387,7 @@ static inline int has_transparent_hugepage(void) | |||
1387 | 1387 | ||
1388 | static inline unsigned long pmd_pfn(pmd_t pmd) | 1388 | static inline unsigned long pmd_pfn(pmd_t pmd) |
1389 | { | 1389 | { |
1390 | if (pmd_trans_huge(pmd)) | 1390 | return pmd_val(pmd) >> PAGE_SHIFT; |
1391 | return pmd_val(pmd) >> HPAGE_SHIFT; | ||
1392 | else | ||
1393 | return pmd_val(pmd) >> PAGE_SHIFT; | ||
1394 | } | 1391 | } |
1395 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 1392 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
1396 | 1393 | ||
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index fba4d66788a2..4c060bb5b8ea 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h | |||
@@ -128,4 +128,32 @@ static inline unsigned long long get_clock_monotonic(void) | |||
128 | return get_clock_xt() - sched_clock_base_cc; | 128 | return get_clock_xt() - sched_clock_base_cc; |
129 | } | 129 | } |
130 | 130 | ||
131 | /** | ||
132 | * tod_to_ns - convert a TOD format value to nanoseconds | ||
133 | * @todval: to be converted TOD format value | ||
134 | * Returns: number of nanoseconds that correspond to the TOD format value | ||
135 | * | ||
136 | * Converting a 64 Bit TOD format value to nanoseconds means that the value | ||
137 | * must be divided by 4.096. In order to achieve that we multiply with 125 | ||
138 | * and divide by 512: | ||
139 | * | ||
140 | * ns = (todval * 125) >> 9; | ||
141 | * | ||
142 | * In order to avoid an overflow with the multiplication we can rewrite this. | ||
143 | * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) | ||
144 | * we end up with | ||
145 | * | ||
146 | * ns = ((2^32 * th + tl) * 125 ) >> 9; | ||
147 | * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); | ||
148 | * | ||
149 | */ | ||
150 | static inline unsigned long long tod_to_ns(unsigned long long todval) | ||
151 | { | ||
152 | unsigned long long ns; | ||
153 | |||
154 | ns = ((todval >> 32) << 23) * 125; | ||
155 | ns += ((todval & 0xffffffff) * 125) >> 9; | ||
156 | return ns; | ||
157 | } | ||
158 | |||
131 | #endif | 159 | #endif |
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h index 63e6078699f1..864f693c237f 100644 --- a/arch/s390/include/uapi/asm/unistd.h +++ b/arch/s390/include/uapi/asm/unistd.h | |||
@@ -279,7 +279,8 @@ | |||
279 | #define __NR_process_vm_writev 341 | 279 | #define __NR_process_vm_writev 341 |
280 | #define __NR_s390_runtime_instr 342 | 280 | #define __NR_s390_runtime_instr 342 |
281 | #define __NR_kcmp 343 | 281 | #define __NR_kcmp 343 |
282 | #define NR_syscalls 344 | 282 | #define __NR_finit_module 344 |
283 | #define NR_syscalls 345 | ||
283 | 284 | ||
284 | /* | 285 | /* |
285 | * There are some system calls that are not present on 64 bit, some | 286 | * There are some system calls that are not present on 64 bit, some |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 827e094a2f49..9b9a805656b5 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -1659,3 +1659,9 @@ ENTRY(sys_kcmp_wrapper) | |||
1659 | llgfr %r5,%r5 # unsigned long | 1659 | llgfr %r5,%r5 # unsigned long |
1660 | llgfr %r6,%r6 # unsigned long | 1660 | llgfr %r6,%r6 # unsigned long |
1661 | jg sys_kcmp | 1661 | jg sys_kcmp |
1662 | |||
1663 | ENTRY(sys_finit_module_wrapper) | ||
1664 | lgfr %r2,%r2 # int | ||
1665 | llgtr %r3,%r3 # const char __user * | ||
1666 | lgfr %r4,%r4 # int | ||
1667 | jg sys_finit_module | ||
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index ba500d8dc392..4e8215e0d4b6 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -1127,13 +1127,14 @@ debug_register_view(debug_info_t * id, struct debug_view *view) | |||
1127 | if (i == DEBUG_MAX_VIEWS) { | 1127 | if (i == DEBUG_MAX_VIEWS) { |
1128 | pr_err("Registering view %s/%s would exceed the maximum " | 1128 | pr_err("Registering view %s/%s would exceed the maximum " |
1129 | "number of views %i\n", id->name, view->name, i); | 1129 | "number of views %i\n", id->name, view->name, i); |
1130 | debugfs_remove(pde); | ||
1131 | rc = -1; | 1130 | rc = -1; |
1132 | } else { | 1131 | } else { |
1133 | id->views[i] = view; | 1132 | id->views[i] = view; |
1134 | id->debugfs_entries[i] = pde; | 1133 | id->debugfs_entries[i] = pde; |
1135 | } | 1134 | } |
1136 | spin_unlock_irqrestore(&id->lock, flags); | 1135 | spin_unlock_irqrestore(&id->lock, flags); |
1136 | if (rc) | ||
1137 | debugfs_remove(pde); | ||
1137 | out: | 1138 | out: |
1138 | return rc; | 1139 | return rc; |
1139 | } | 1140 | } |
@@ -1146,9 +1147,9 @@ EXPORT_SYMBOL(debug_register_view); | |||
1146 | int | 1147 | int |
1147 | debug_unregister_view(debug_info_t * id, struct debug_view *view) | 1148 | debug_unregister_view(debug_info_t * id, struct debug_view *view) |
1148 | { | 1149 | { |
1149 | int rc = 0; | 1150 | struct dentry *dentry = NULL; |
1150 | int i; | ||
1151 | unsigned long flags; | 1151 | unsigned long flags; |
1152 | int i, rc = 0; | ||
1152 | 1153 | ||
1153 | if (!id) | 1154 | if (!id) |
1154 | goto out; | 1155 | goto out; |
@@ -1160,10 +1161,12 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view) | |||
1160 | if (i == DEBUG_MAX_VIEWS) | 1161 | if (i == DEBUG_MAX_VIEWS) |
1161 | rc = -1; | 1162 | rc = -1; |
1162 | else { | 1163 | else { |
1163 | debugfs_remove(id->debugfs_entries[i]); | 1164 | dentry = id->debugfs_entries[i]; |
1164 | id->views[i] = NULL; | 1165 | id->views[i] = NULL; |
1166 | id->debugfs_entries[i] = NULL; | ||
1165 | } | 1167 | } |
1166 | spin_unlock_irqrestore(&id->lock, flags); | 1168 | spin_unlock_irqrestore(&id->lock, flags); |
1169 | debugfs_remove(dentry); | ||
1167 | out: | 1170 | out: |
1168 | return rc; | 1171 | return rc; |
1169 | } | 1172 | } |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index bf24293970ce..9df824ea1667 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -24,43 +24,65 @@ | |||
24 | #include <asm/irq.h> | 24 | #include <asm/irq.h> |
25 | #include "entry.h" | 25 | #include "entry.h" |
26 | 26 | ||
27 | DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); | ||
28 | EXPORT_PER_CPU_SYMBOL_GPL(irq_stat); | ||
29 | |||
27 | struct irq_class { | 30 | struct irq_class { |
28 | char *name; | 31 | char *name; |
29 | char *desc; | 32 | char *desc; |
30 | }; | 33 | }; |
31 | 34 | ||
32 | static const struct irq_class intrclass_names[] = { | 35 | /* |
36 | * The list of "main" irq classes on s390. This is the list of interrrupts | ||
37 | * that appear both in /proc/stat ("intr" line) and /proc/interrupts. | ||
38 | * Historically only external and I/O interrupts have been part of /proc/stat. | ||
39 | * We can't add the split external and I/O sub classes since the first field | ||
40 | * in the "intr" line in /proc/stat is supposed to be the sum of all other | ||
41 | * fields. | ||
42 | * Since the external and I/O interrupt fields are already sums we would end | ||
43 | * up with having a sum which accounts each interrupt twice. | ||
44 | */ | ||
45 | static const struct irq_class irqclass_main_desc[NR_IRQS] = { | ||
33 | [EXTERNAL_INTERRUPT] = {.name = "EXT"}, | 46 | [EXTERNAL_INTERRUPT] = {.name = "EXT"}, |
34 | [IO_INTERRUPT] = {.name = "I/O"}, | 47 | [IO_INTERRUPT] = {.name = "I/O"} |
35 | [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, | 48 | }; |
36 | [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, | 49 | |
37 | [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, | 50 | /* |
38 | [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, | 51 | * The list of split external and I/O interrupts that appear only in |
39 | [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, | 52 | * /proc/interrupts. |
40 | [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, | 53 | * In addition this list contains non external / I/O events like NMIs. |
41 | [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, | 54 | */ |
42 | [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, | 55 | static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = { |
43 | [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, | 56 | [IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, |
44 | [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, | 57 | [IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, |
45 | [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, | 58 | [IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, |
46 | [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, | 59 | [IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, |
47 | [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, | 60 | [IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, |
48 | [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, | 61 | [IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, |
49 | [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, | 62 | [IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, |
50 | [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, | 63 | [IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, |
51 | [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, | 64 | [IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, |
52 | [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, | 65 | [IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, |
53 | [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, | 66 | [IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, |
54 | [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, | 67 | [IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, |
55 | [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, | 68 | [IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, |
56 | [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, | 69 | [IRQIO_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, |
57 | [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, | 70 | [IRQIO_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, |
58 | [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, | 71 | [IRQIO_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, |
59 | [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, | 72 | [IRQIO_C15] = {.name = "C15", .desc = "[I/O] 3215"}, |
60 | [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | 73 | [IRQIO_C70] = {.name = "C70", .desc = "[I/O] 3270"}, |
61 | [IOINT_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, | 74 | [IRQIO_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, |
62 | [IOINT_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, | 75 | [IRQIO_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, |
76 | [IRQIO_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, | ||
77 | [IRQIO_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, | ||
78 | [IRQIO_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, | ||
79 | [IRQIO_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, | ||
80 | [IRQIO_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, | ||
81 | [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | ||
82 | [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, | ||
83 | [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, | ||
63 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, | 84 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, |
85 | [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, | ||
64 | }; | 86 | }; |
65 | 87 | ||
66 | /* | 88 | /* |
@@ -68,30 +90,34 @@ static const struct irq_class intrclass_names[] = { | |||
68 | */ | 90 | */ |
69 | int show_interrupts(struct seq_file *p, void *v) | 91 | int show_interrupts(struct seq_file *p, void *v) |
70 | { | 92 | { |
71 | int i = *(loff_t *) v, j; | 93 | int irq = *(loff_t *) v; |
94 | int cpu; | ||
72 | 95 | ||
73 | get_online_cpus(); | 96 | get_online_cpus(); |
74 | if (i == 0) { | 97 | if (irq == 0) { |
75 | seq_puts(p, " "); | 98 | seq_puts(p, " "); |
76 | for_each_online_cpu(j) | 99 | for_each_online_cpu(cpu) |
77 | seq_printf(p, "CPU%d ",j); | 100 | seq_printf(p, "CPU%d ", cpu); |
78 | seq_putc(p, '\n'); | 101 | seq_putc(p, '\n'); |
79 | } | 102 | } |
80 | 103 | if (irq < NR_IRQS) { | |
81 | if (i < NR_IRQS) { | 104 | seq_printf(p, "%s: ", irqclass_main_desc[irq].name); |
82 | seq_printf(p, "%s: ", intrclass_names[i].name); | 105 | for_each_online_cpu(cpu) |
83 | #ifndef CONFIG_SMP | 106 | seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]); |
84 | seq_printf(p, "%10u ", kstat_irqs(i)); | 107 | seq_putc(p, '\n'); |
85 | #else | 108 | goto skip_arch_irqs; |
86 | for_each_online_cpu(j) | 109 | } |
87 | seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); | 110 | for (irq = 0; irq < NR_ARCH_IRQS; irq++) { |
88 | #endif | 111 | seq_printf(p, "%s: ", irqclass_sub_desc[irq].name); |
89 | if (intrclass_names[i].desc) | 112 | for_each_online_cpu(cpu) |
90 | seq_printf(p, " %s", intrclass_names[i].desc); | 113 | seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]); |
91 | seq_putc(p, '\n'); | 114 | if (irqclass_sub_desc[irq].desc) |
92 | } | 115 | seq_printf(p, " %s", irqclass_sub_desc[irq].desc); |
116 | seq_putc(p, '\n'); | ||
117 | } | ||
118 | skip_arch_irqs: | ||
93 | put_online_cpus(); | 119 | put_online_cpus(); |
94 | return 0; | 120 | return 0; |
95 | } | 121 | } |
96 | 122 | ||
97 | /* | 123 | /* |
@@ -222,7 +248,7 @@ void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code, | |||
222 | /* Serve timer interrupts first. */ | 248 | /* Serve timer interrupts first. */ |
223 | clock_comparator_work(); | 249 | clock_comparator_work(); |
224 | } | 250 | } |
225 | kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; | 251 | kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL); |
226 | if (ext_code.code != 0x1004) | 252 | if (ext_code.code != 0x1004) |
227 | __get_cpu_var(s390_idle).nohz_delay = 1; | 253 | __get_cpu_var(s390_idle).nohz_delay = 1; |
228 | 254 | ||
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index a6daa5c5cdb0..7918fbea36bb 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c | |||
@@ -254,7 +254,7 @@ void notrace s390_do_machine_check(struct pt_regs *regs) | |||
254 | int umode; | 254 | int umode; |
255 | 255 | ||
256 | nmi_enter(); | 256 | nmi_enter(); |
257 | kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++; | 257 | inc_irq_stat(NMI_NMI); |
258 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; | 258 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; |
259 | mcck = &__get_cpu_var(cpu_mcck); | 259 | mcck = &__get_cpu_var(cpu_mcck); |
260 | umode = user_mode(regs); | 260 | umode = user_mode(regs); |
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index c4e7269d4a09..86ec7447e1f5 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c | |||
@@ -229,7 +229,7 @@ static void cpumf_measurement_alert(struct ext_code ext_code, | |||
229 | if (!(alert & CPU_MF_INT_CF_MASK)) | 229 | if (!(alert & CPU_MF_INT_CF_MASK)) |
230 | return; | 230 | return; |
231 | 231 | ||
232 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++; | 232 | inc_irq_stat(IRQEXT_CMC); |
233 | cpuhw = &__get_cpu_var(cpu_hw_events); | 233 | cpuhw = &__get_cpu_var(cpu_hw_events); |
234 | 234 | ||
235 | /* Measurement alerts are shared and might happen when the PMU | 235 | /* Measurement alerts are shared and might happen when the PMU |
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c index 61066f6f71a5..077a99389b07 100644 --- a/arch/s390/kernel/runtime_instr.c +++ b/arch/s390/kernel/runtime_instr.c | |||
@@ -71,7 +71,7 @@ static void runtime_instr_int_handler(struct ext_code ext_code, | |||
71 | if (!(param32 & CPU_MF_INT_RI_MASK)) | 71 | if (!(param32 & CPU_MF_INT_RI_MASK)) |
72 | return; | 72 | return; |
73 | 73 | ||
74 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; | 74 | inc_irq_stat(IRQEXT_CMR); |
75 | 75 | ||
76 | if (!current->thread.ri_cb) | 76 | if (!current->thread.ri_cb) |
77 | return; | 77 | return; |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 2568590973ad..a5360de85ec7 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 16 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
17 | 17 | ||
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/module.h> | 19 | #include <linux/export.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/memblock.h> | 22 | #include <linux/memblock.h> |
@@ -289,6 +289,7 @@ void machine_power_off(void) | |||
289 | * Dummy power off function. | 289 | * Dummy power off function. |
290 | */ | 290 | */ |
291 | void (*pm_power_off)(void) = machine_power_off; | 291 | void (*pm_power_off)(void) = machine_power_off; |
292 | EXPORT_SYMBOL_GPL(pm_power_off); | ||
292 | 293 | ||
293 | static int __init early_parse_mem(char *p) | 294 | static int __init early_parse_mem(char *p) |
294 | { | 295 | { |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0b45baa55438..7433a2f9e5cc 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -433,9 +433,9 @@ static void do_ext_call_interrupt(struct ext_code ext_code, | |||
433 | 433 | ||
434 | cpu = smp_processor_id(); | 434 | cpu = smp_processor_id(); |
435 | if (ext_code.code == 0x1202) | 435 | if (ext_code.code == 0x1202) |
436 | kstat_cpu(cpu).irqs[EXTINT_EXC]++; | 436 | inc_irq_stat(IRQEXT_EXC); |
437 | else | 437 | else |
438 | kstat_cpu(cpu).irqs[EXTINT_EMS]++; | 438 | inc_irq_stat(IRQEXT_EMS); |
439 | /* | 439 | /* |
440 | * handle bit signal external calls | 440 | * handle bit signal external calls |
441 | */ | 441 | */ |
@@ -623,9 +623,10 @@ static struct sclp_cpu_info *smp_get_cpu_info(void) | |||
623 | return info; | 623 | return info; |
624 | } | 624 | } |
625 | 625 | ||
626 | static int smp_add_present_cpu(int cpu); | 626 | static int __cpuinit smp_add_present_cpu(int cpu); |
627 | 627 | ||
628 | static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add) | 628 | static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info, |
629 | int sysfs_add) | ||
629 | { | 630 | { |
630 | struct pcpu *pcpu; | 631 | struct pcpu *pcpu; |
631 | cpumask_t avail; | 632 | cpumask_t avail; |
@@ -708,6 +709,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid) | |||
708 | pfault_init(); | 709 | pfault_init(); |
709 | notify_cpu_starting(smp_processor_id()); | 710 | notify_cpu_starting(smp_processor_id()); |
710 | set_cpu_online(smp_processor_id(), true); | 711 | set_cpu_online(smp_processor_id(), true); |
712 | inc_irq_stat(CPU_RST); | ||
711 | local_irq_enable(); | 713 | local_irq_enable(); |
712 | /* cpu_idle will call schedule for us */ | 714 | /* cpu_idle will call schedule for us */ |
713 | cpu_idle(); | 715 | cpu_idle(); |
@@ -985,7 +987,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
985 | return notifier_from_errno(err); | 987 | return notifier_from_errno(err); |
986 | } | 988 | } |
987 | 989 | ||
988 | static int smp_add_present_cpu(int cpu) | 990 | static int __cpuinit smp_add_present_cpu(int cpu) |
989 | { | 991 | { |
990 | struct cpu *c = &pcpu_devices[cpu].cpu; | 992 | struct cpu *c = &pcpu_devices[cpu].cpu; |
991 | struct device *s = &c->dev; | 993 | struct device *s = &c->dev; |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index 48174850f3b0..6a6c61f94dd3 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -352,3 +352,4 @@ SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wr | |||
352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) | 352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) |
353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) | 353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) |
354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) | 354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) |
355 | SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper) | ||
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 7fcd690d42c7..a5f4f5a1d24b 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); | |||
63 | */ | 63 | */ |
64 | unsigned long long notrace __kprobes sched_clock(void) | 64 | unsigned long long notrace __kprobes sched_clock(void) |
65 | { | 65 | { |
66 | return (get_clock_monotonic() * 125) >> 9; | 66 | return tod_to_ns(get_clock_monotonic()); |
67 | } | 67 | } |
68 | 68 | ||
69 | /* | 69 | /* |
@@ -168,7 +168,7 @@ static void clock_comparator_interrupt(struct ext_code ext_code, | |||
168 | unsigned int param32, | 168 | unsigned int param32, |
169 | unsigned long param64) | 169 | unsigned long param64) |
170 | { | 170 | { |
171 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++; | 171 | inc_irq_stat(IRQEXT_CLK); |
172 | if (S390_lowcore.clock_comparator == -1ULL) | 172 | if (S390_lowcore.clock_comparator == -1ULL) |
173 | set_clock_comparator(S390_lowcore.clock_comparator); | 173 | set_clock_comparator(S390_lowcore.clock_comparator); |
174 | } | 174 | } |
@@ -179,7 +179,7 @@ static void stp_timing_alert(struct stp_irq_parm *); | |||
179 | static void timing_alert_interrupt(struct ext_code ext_code, | 179 | static void timing_alert_interrupt(struct ext_code ext_code, |
180 | unsigned int param32, unsigned long param64) | 180 | unsigned int param32, unsigned long param64) |
181 | { | 181 | { |
182 | kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; | 182 | inc_irq_stat(IRQEXT_TLA); |
183 | if (param32 & 0x00c40000) | 183 | if (param32 & 0x00c40000) |
184 | etr_timing_alert((struct etr_irq_parm *) ¶m32); | 184 | etr_timing_alert((struct etr_irq_parm *) ¶m32); |
185 | if (param32 & 0x00038000) | 185 | if (param32 & 0x00038000) |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index f1aba87cceb8..4b2e3e317004 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/bootmem.h> | 10 | #include <linux/bootmem.h> |
11 | #include <linux/cpuset.h> | 11 | #include <linux/cpuset.h> |
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/export.h> | ||
13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
14 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
@@ -42,6 +43,7 @@ static struct mask_info socket_info; | |||
42 | static struct mask_info book_info; | 43 | static struct mask_info book_info; |
43 | 44 | ||
44 | struct cpu_topology_s390 cpu_topology[NR_CPUS]; | 45 | struct cpu_topology_s390 cpu_topology[NR_CPUS]; |
46 | EXPORT_SYMBOL_GPL(cpu_topology); | ||
45 | 47 | ||
46 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | 48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) |
47 | { | 49 | { |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index c30615e605ac..82c481ddef76 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -408,7 +408,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) | |||
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; | 411 | sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); |
412 | 412 | ||
413 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); | 413 | hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); |
414 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); | 414 | VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index c9011bfaabbe..f090e819bf71 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -613,7 +613,9 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) | |||
613 | kvm_s390_deliver_pending_interrupts(vcpu); | 613 | kvm_s390_deliver_pending_interrupts(vcpu); |
614 | 614 | ||
615 | vcpu->arch.sie_block->icptcode = 0; | 615 | vcpu->arch.sie_block->icptcode = 0; |
616 | preempt_disable(); | ||
616 | kvm_guest_enter(); | 617 | kvm_guest_enter(); |
618 | preempt_enable(); | ||
617 | VCPU_EVENT(vcpu, 6, "entering sie flags %x", | 619 | VCPU_EVENT(vcpu, 6, "entering sie flags %x", |
618 | atomic_read(&vcpu->arch.sie_block->cpuflags)); | 620 | atomic_read(&vcpu->arch.sie_block->cpuflags)); |
619 | trace_kvm_s390_sie_enter(vcpu, | 621 | trace_kvm_s390_sie_enter(vcpu, |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 42601d6e166f..2fb9e63b8fc4 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -569,7 +569,7 @@ static void pfault_interrupt(struct ext_code ext_code, | |||
569 | subcode = ext_code.subcode; | 569 | subcode = ext_code.subcode; |
570 | if ((subcode & 0xff00) != __SUBCODE_MASK) | 570 | if ((subcode & 0xff00) != __SUBCODE_MASK) |
571 | return; | 571 | return; |
572 | kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; | 572 | inc_irq_stat(IRQEXT_PFL); |
573 | /* Get the token (= pid of the affected task). */ | 573 | /* Get the token (= pid of the affected task). */ |
574 | pid = sizeof(void *) == 4 ? param32 : param64; | 574 | pid = sizeof(void *) == 4 ? param32 : param64; |
575 | rcu_read_lock(); | 575 | rcu_read_lock(); |
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c index 0cb385da202c..b5b2916895e0 100644 --- a/arch/s390/oprofile/hwsampler.c +++ b/arch/s390/oprofile/hwsampler.c | |||
@@ -233,7 +233,7 @@ static void hws_ext_handler(struct ext_code ext_code, | |||
233 | if (!(param32 & CPU_MF_INT_SF_MASK)) | 233 | if (!(param32 & CPU_MF_INT_SF_MASK)) |
234 | return; | 234 | return; |
235 | 235 | ||
236 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CMS]++; | 236 | inc_irq_stat(IRQEXT_CMS); |
237 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); | 237 | atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32); |
238 | 238 | ||
239 | if (hws_wq) | 239 | if (hws_wq) |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index ff49427e9941..60e0372545d2 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -160,35 +160,6 @@ int pci_proc_domain(struct pci_bus *bus) | |||
160 | } | 160 | } |
161 | EXPORT_SYMBOL_GPL(pci_proc_domain); | 161 | EXPORT_SYMBOL_GPL(pci_proc_domain); |
162 | 162 | ||
163 | /* Store PCI function information block */ | ||
164 | static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc) | ||
165 | { | ||
166 | struct zpci_fib *fib; | ||
167 | u8 status, cc; | ||
168 | |||
169 | fib = (void *) get_zeroed_page(GFP_KERNEL); | ||
170 | if (!fib) | ||
171 | return -ENOMEM; | ||
172 | |||
173 | do { | ||
174 | cc = __stpcifc(zdev->fh, 0, fib, &status); | ||
175 | if (cc == 2) { | ||
176 | msleep(ZPCI_INSN_BUSY_DELAY); | ||
177 | memset(fib, 0, PAGE_SIZE); | ||
178 | } | ||
179 | } while (cc == 2); | ||
180 | |||
181 | if (cc) | ||
182 | pr_err_once("%s: cc: %u status: %u\n", | ||
183 | __func__, cc, status); | ||
184 | |||
185 | /* Return PCI function controls */ | ||
186 | *fc = fib->fc; | ||
187 | |||
188 | free_page((unsigned long) fib); | ||
189 | return (cc) ? -EIO : 0; | ||
190 | } | ||
191 | |||
192 | /* Modify PCI: Register adapter interruptions */ | 163 | /* Modify PCI: Register adapter interruptions */ |
193 | static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb, | 164 | static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb, |
194 | u64 aibv) | 165 | u64 aibv) |
@@ -469,7 +440,7 @@ static void zpci_irq_handler(void *dont, void *need) | |||
469 | int rescan = 0, max = aisb_max; | 440 | int rescan = 0, max = aisb_max; |
470 | struct zdev_irq_map *imap; | 441 | struct zdev_irq_map *imap; |
471 | 442 | ||
472 | kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++; | 443 | inc_irq_stat(IRQIO_PCI); |
473 | sbit = start; | 444 | sbit = start; |
474 | 445 | ||
475 | scan: | 446 | scan: |
@@ -481,7 +452,7 @@ scan: | |||
481 | /* find vector bit */ | 452 | /* find vector bit */ |
482 | imap = bucket->imap[sbit]; | 453 | imap = bucket->imap[sbit]; |
483 | for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) { | 454 | for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) { |
484 | kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++; | 455 | inc_irq_stat(IRQIO_MSI); |
485 | clear_bit(63 - mbit, &imap->aibv); | 456 | clear_bit(63 - mbit, &imap->aibv); |
486 | 457 | ||
487 | spin_lock(&imap->lock); | 458 | spin_lock(&imap->lock); |
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index 6138468b420f..a547419907c3 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c | |||
@@ -13,8 +13,6 @@ | |||
13 | #include <linux/pci.h> | 13 | #include <linux/pci.h> |
14 | #include <asm/pci_dma.h> | 14 | #include <asm/pci_dma.h> |
15 | 15 | ||
16 | static enum zpci_ioat_dtype zpci_ioat_dt = ZPCI_IOTA_RTTO; | ||
17 | |||
18 | static struct kmem_cache *dma_region_table_cache; | 16 | static struct kmem_cache *dma_region_table_cache; |
19 | static struct kmem_cache *dma_page_table_cache; | 17 | static struct kmem_cache *dma_page_table_cache; |
20 | 18 | ||
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3fede4556c91..a0fa5791cd44 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c | |||
@@ -70,6 +70,16 @@ | |||
70 | * OFF-ON : MMC | 70 | * OFF-ON : MMC |
71 | */ | 71 | */ |
72 | 72 | ||
73 | /* | ||
74 | * FSI - DA7210 | ||
75 | * | ||
76 | * it needs amixer settings for playing | ||
77 | * | ||
78 | * amixer set 'HeadPhone' 80 | ||
79 | * amixer set 'Out Mixer Left DAC Left' on | ||
80 | * amixer set 'Out Mixer Right DAC Right' on | ||
81 | */ | ||
82 | |||
73 | /* Heartbeat */ | 83 | /* Heartbeat */ |
74 | static unsigned char led_pos[] = { 0, 1, 2, 3 }; | 84 | static unsigned char led_pos[] = { 0, 1, 2, 3 }; |
75 | 85 | ||
diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h index 37924afa8d8a..bf9f44f17c29 100644 --- a/arch/sh/include/asm/elf.h +++ b/arch/sh/include/asm/elf.h | |||
@@ -203,9 +203,9 @@ extern void __kernel_vsyscall; | |||
203 | if (vdso_enabled) \ | 203 | if (vdso_enabled) \ |
204 | NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ | 204 | NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ |
205 | else \ | 205 | else \ |
206 | NEW_AUX_ENT(AT_IGNORE, 0); | 206 | NEW_AUX_ENT(AT_IGNORE, 0) |
207 | #else | 207 | #else |
208 | #define VSYSCALL_AUX_ENT | 208 | #define VSYSCALL_AUX_ENT NEW_AUX_ENT(AT_IGNORE, 0) |
209 | #endif /* CONFIG_VSYSCALL */ | 209 | #endif /* CONFIG_VSYSCALL */ |
210 | 210 | ||
211 | #ifdef CONFIG_SH_FPU | 211 | #ifdef CONFIG_SH_FPU |
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index b1320d55ca30..e699a12cdcca 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h | |||
@@ -39,7 +39,7 @@ | |||
39 | /* This decides where the kernel will search for a free chunk of vm | 39 | /* This decides where the kernel will search for a free chunk of vm |
40 | * space during mmap's. | 40 | * space during mmap's. |
41 | */ | 41 | */ |
42 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) | 42 | #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) |
43 | 43 | ||
44 | /* | 44 | /* |
45 | * Bit of SR register | 45 | * Bit of SR register |
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 1ee8946f0952..1cc7d3197143 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h | |||
@@ -47,7 +47,7 @@ pc; }) | |||
47 | /* This decides where the kernel will search for a free chunk of vm | 47 | /* This decides where the kernel will search for a free chunk of vm |
48 | * space during mmap's. | 48 | * space during mmap's. |
49 | */ | 49 | */ |
50 | #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) | 50 | #define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE / 3) |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Bit of SR register | 53 | * Bit of SR register |
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h index 9e465f246dc1..d13a1d623736 100644 --- a/arch/sh/include/uapi/asm/unistd_32.h +++ b/arch/sh/include/uapi/asm/unistd_32.h | |||
@@ -379,7 +379,8 @@ | |||
379 | #define __NR_process_vm_readv 365 | 379 | #define __NR_process_vm_readv 365 |
380 | #define __NR_process_vm_writev 366 | 380 | #define __NR_process_vm_writev 366 |
381 | #define __NR_kcmp 367 | 381 | #define __NR_kcmp 367 |
382 | #define __NR_finit_module 368 | ||
382 | 383 | ||
383 | #define NR_syscalls 368 | 384 | #define NR_syscalls 369 |
384 | 385 | ||
385 | #endif /* __ASM_SH_UNISTD_32_H */ | 386 | #endif /* __ASM_SH_UNISTD_32_H */ |
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h index 8e3a2edd284e..e6820c86e8c7 100644 --- a/arch/sh/include/uapi/asm/unistd_64.h +++ b/arch/sh/include/uapi/asm/unistd_64.h | |||
@@ -399,7 +399,8 @@ | |||
399 | #define __NR_process_vm_readv 376 | 399 | #define __NR_process_vm_readv 376 |
400 | #define __NR_process_vm_writev 377 | 400 | #define __NR_process_vm_writev 377 |
401 | #define __NR_kcmp 378 | 401 | #define __NR_kcmp 378 |
402 | #define __NR_finit_module 379 | ||
402 | 403 | ||
403 | #define NR_syscalls 379 | 404 | #define NR_syscalls 380 |
404 | 405 | ||
405 | #endif /* __ASM_SH_UNISTD_64_H */ | 406 | #endif /* __ASM_SH_UNISTD_64_H */ |
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index fe97ae5e56f1..734234be2f01 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S | |||
@@ -385,3 +385,4 @@ ENTRY(sys_call_table) | |||
385 | .long sys_process_vm_readv /* 365 */ | 385 | .long sys_process_vm_readv /* 365 */ |
386 | .long sys_process_vm_writev | 386 | .long sys_process_vm_writev |
387 | .long sys_kcmp | 387 | .long sys_kcmp |
388 | .long sys_finit_module | ||
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index 5c7b1c67bdc1..579fcb9a896b 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S | |||
@@ -405,3 +405,4 @@ sys_call_table: | |||
405 | .long sys_process_vm_readv | 405 | .long sys_process_vm_readv |
406 | .long sys_process_vm_writev | 406 | .long sys_process_vm_writev |
407 | .long sys_kcmp | 407 | .long sys_kcmp |
408 | .long sys_finit_module | ||
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 60164e65d665..52aa2011d753 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S | |||
@@ -294,6 +294,8 @@ stack_panic: | |||
294 | .align 2 | 294 | .align 2 |
295 | .L_init_thread_union: | 295 | .L_init_thread_union: |
296 | .long init_thread_union | 296 | .long init_thread_union |
297 | .L_ebss: | ||
298 | .long __bss_stop | ||
297 | .Lpanic: | 299 | .Lpanic: |
298 | .long panic | 300 | .long panic |
299 | .Lpanic_s: | 301 | .Lpanic_s: |
diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h index cac719d1bc5c..62ced589bcf7 100644 --- a/arch/sparc/include/uapi/asm/unistd.h +++ b/arch/sparc/include/uapi/asm/unistd.h | |||
@@ -407,8 +407,9 @@ | |||
407 | #define __NR_process_vm_writev 339 | 407 | #define __NR_process_vm_writev 339 |
408 | #define __NR_kern_features 340 | 408 | #define __NR_kern_features 340 |
409 | #define __NR_kcmp 341 | 409 | #define __NR_kcmp 341 |
410 | #define __NR_finit_module 342 | ||
410 | 411 | ||
411 | #define NR_syscalls 342 | 412 | #define NR_syscalls 343 |
412 | 413 | ||
413 | /* Bitmask values returned from kern_features system call. */ | 414 | /* Bitmask values returned from kern_features system call. */ |
414 | #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 | 415 | #define KERN_FEATURE_MIXED_MODE_STACK 0x00000001 |
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index 04bacce76fe6..baf4366e2d6a 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c | |||
@@ -378,7 +378,8 @@ static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p) | |||
378 | /* Cook up fake bus resources for SUNW,simba PCI bridges which lack | 378 | /* Cook up fake bus resources for SUNW,simba PCI bridges which lack |
379 | * a proper 'ranges' property. | 379 | * a proper 'ranges' property. |
380 | */ | 380 | */ |
381 | static void apb_fake_ranges(struct pci_dev *dev, struct pci_bus *bus, | 381 | static void apb_fake_ranges(struct pci_dev *dev, |
382 | struct pci_bus *bus, | ||
382 | struct pci_pbm_info *pbm) | 383 | struct pci_pbm_info *pbm) |
383 | { | 384 | { |
384 | struct pci_bus_region region; | 385 | struct pci_bus_region region; |
@@ -403,13 +404,15 @@ static void apb_fake_ranges(struct pci_dev *dev, struct pci_bus *bus, | |||
403 | pcibios_bus_to_resource(dev, res, ®ion); | 404 | pcibios_bus_to_resource(dev, res, ®ion); |
404 | } | 405 | } |
405 | 406 | ||
406 | static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node, | 407 | static void pci_of_scan_bus(struct pci_pbm_info *pbm, |
408 | struct device_node *node, | ||
407 | struct pci_bus *bus); | 409 | struct pci_bus *bus); |
408 | 410 | ||
409 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) | 411 | #define GET_64BIT(prop, i) ((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1]) |
410 | 412 | ||
411 | static void of_scan_pci_bridge(struct pci_pbm_info *pbm, | 413 | static void of_scan_pci_bridge(struct pci_pbm_info *pbm, |
412 | struct device_node *node, struct pci_dev *dev) | 414 | struct device_node *node, |
415 | struct pci_dev *dev) | ||
413 | { | 416 | { |
414 | struct pci_bus *bus; | 417 | struct pci_bus *bus; |
415 | const u32 *busrange, *ranges; | 418 | const u32 *busrange, *ranges; |
@@ -500,7 +503,8 @@ after_ranges: | |||
500 | pci_of_scan_bus(pbm, node, bus); | 503 | pci_of_scan_bus(pbm, node, bus); |
501 | } | 504 | } |
502 | 505 | ||
503 | static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node, | 506 | static void pci_of_scan_bus(struct pci_pbm_info *pbm, |
507 | struct device_node *node, | ||
504 | struct pci_bus *bus) | 508 | struct pci_bus *bus) |
505 | { | 509 | { |
506 | struct device_node *child; | 510 | struct device_node *child; |
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c index b85238289717..c647634ead2b 100644 --- a/arch/sparc/kernel/pci_psycho.c +++ b/arch/sparc/kernel/pci_psycho.c | |||
@@ -366,7 +366,8 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
366 | pci_config_write8(addr, 64); | 366 | pci_config_write8(addr, 64); |
367 | } | 367 | } |
368 | 368 | ||
369 | static void psycho_scan_bus(struct pci_pbm_info *pbm, struct device *parent) | 369 | static void psycho_scan_bus(struct pci_pbm_info *pbm, |
370 | struct device *parent) | ||
370 | { | 371 | { |
371 | pbm_config_busmastering(pbm); | 372 | pbm_config_busmastering(pbm); |
372 | pbm->is_66mhz_capable = 0; | 373 | pbm->is_66mhz_capable = 0; |
diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c index 531186d7c9ab..6f00d27e8dac 100644 --- a/arch/sparc/kernel/pci_sabre.c +++ b/arch/sparc/kernel/pci_sabre.c | |||
@@ -442,7 +442,8 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm, struct device *parent) | |||
442 | sabre_register_error_handlers(pbm); | 442 | sabre_register_error_handlers(pbm); |
443 | } | 443 | } |
444 | 444 | ||
445 | static void sabre_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op) | 445 | static void sabre_pbm_init(struct pci_pbm_info *pbm, |
446 | struct platform_device *op) | ||
446 | { | 447 | { |
447 | psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); | 448 | psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); |
448 | pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; | 449 | pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; |
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c index 29e888158ae6..8f76f23dac38 100644 --- a/arch/sparc/kernel/pci_schizo.c +++ b/arch/sparc/kernel/pci_schizo.c | |||
@@ -1306,8 +1306,9 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
1306 | } | 1306 | } |
1307 | } | 1307 | } |
1308 | 1308 | ||
1309 | static int schizo_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op, | 1309 | static int schizo_pbm_init(struct pci_pbm_info *pbm, |
1310 | u32 portid, int chip_type) | 1310 | struct platform_device *op, u32 portid, |
1311 | int chip_type) | ||
1311 | { | 1312 | { |
1312 | const struct linux_prom64_registers *regs; | 1313 | const struct linux_prom64_registers *regs; |
1313 | struct device_node *dp = op->dev.of_node; | 1314 | struct device_node *dp = op->dev.of_node; |
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S index 5147f574f125..6ac43c36bbbf 100644 --- a/arch/sparc/kernel/systbls_32.S +++ b/arch/sparc/kernel/systbls_32.S | |||
@@ -85,4 +85,4 @@ sys_call_table: | |||
85 | /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init | 85 | /*325*/ .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init |
86 | /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime | 86 | /*330*/ .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime |
87 | /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev | 87 | /*335*/ .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev |
88 | /*340*/ .long sys_ni_syscall, sys_kcmp | 88 | /*340*/ .long sys_ni_syscall, sys_kcmp, sys_finit_module |
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index cdbd9b817751..1009ecb92678 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S | |||
@@ -86,7 +86,7 @@ sys_call_table32: | |||
86 | .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init | 86 | .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init |
87 | /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime | 87 | /*330*/ .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime |
88 | .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev | 88 | .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev |
89 | /*340*/ .word sys_kern_features, sys_kcmp | 89 | /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module |
90 | 90 | ||
91 | #endif /* CONFIG_COMPAT */ | 91 | #endif /* CONFIG_COMPAT */ |
92 | 92 | ||
@@ -164,4 +164,4 @@ sys_call_table: | |||
164 | .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init | 164 | .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init |
165 | /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime | 165 | /*330*/ .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime |
166 | .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev | 166 | .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev |
167 | /*340*/ .word sys_kern_features, sys_kcmp | 167 | /*340*/ .word sys_kern_features, sys_kcmp, sys_finit_module |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index b1942e222768..18e329ca108e 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -302,7 +302,7 @@ static efi_status_t setup_efi_pci(struct boot_params *params) | |||
302 | if (status != EFI_SUCCESS) | 302 | if (status != EFI_SUCCESS) |
303 | continue; | 303 | continue; |
304 | 304 | ||
305 | if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM) | 305 | if (!(attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)) |
306 | continue; | 306 | continue; |
307 | 307 | ||
308 | if (!pci->romimage || !pci->romsize) | 308 | if (!pci->romimage || !pci->romsize) |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 4428fd178bce..6774c17a5576 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -340,9 +340,6 @@ int x86_setup_perfctr(struct perf_event *event) | |||
340 | /* BTS is currently only allowed for user-mode. */ | 340 | /* BTS is currently only allowed for user-mode. */ |
341 | if (!attr->exclude_kernel) | 341 | if (!attr->exclude_kernel) |
342 | return -EOPNOTSUPP; | 342 | return -EOPNOTSUPP; |
343 | |||
344 | if (!attr->exclude_guest) | ||
345 | return -EOPNOTSUPP; | ||
346 | } | 343 | } |
347 | 344 | ||
348 | hwc->config |= config; | 345 | hwc->config |= config; |
@@ -385,9 +382,6 @@ int x86_pmu_hw_config(struct perf_event *event) | |||
385 | if (event->attr.precise_ip) { | 382 | if (event->attr.precise_ip) { |
386 | int precise = 0; | 383 | int precise = 0; |
387 | 384 | ||
388 | if (!event->attr.exclude_guest) | ||
389 | return -EOPNOTSUPP; | ||
390 | |||
391 | /* Support for constant skid */ | 385 | /* Support for constant skid */ |
392 | if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) { | 386 | if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) { |
393 | precise++; | 387 | precise++; |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index ff84d5469d77..6ed91d9980e2 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -1065,7 +1065,6 @@ ENTRY(xen_failsafe_callback) | |||
1065 | lea 16(%esp),%esp | 1065 | lea 16(%esp),%esp |
1066 | CFI_ADJUST_CFA_OFFSET -16 | 1066 | CFI_ADJUST_CFA_OFFSET -16 |
1067 | jz 5f | 1067 | jz 5f |
1068 | addl $16,%esp | ||
1069 | jmp iret_exc | 1068 | jmp iret_exc |
1070 | 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ | 1069 | 5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ |
1071 | SAVE_ALL | 1070 | SAVE_ALL |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 08b973f64032..9c2bd8bd4b4c 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/apicdef.h> | 43 | #include <asm/apicdef.h> |
44 | #include <asm/hypervisor.h> | 44 | #include <asm/hypervisor.h> |
45 | #include <asm/kvm_guest.h> | 45 | #include <asm/kvm_guest.h> |
46 | #include <asm/context_tracking.h> | ||
46 | 47 | ||
47 | static int kvmapf = 1; | 48 | static int kvmapf = 1; |
48 | 49 | ||
@@ -121,6 +122,8 @@ void kvm_async_pf_task_wait(u32 token) | |||
121 | struct kvm_task_sleep_node n, *e; | 122 | struct kvm_task_sleep_node n, *e; |
122 | DEFINE_WAIT(wait); | 123 | DEFINE_WAIT(wait); |
123 | 124 | ||
125 | rcu_irq_enter(); | ||
126 | |||
124 | spin_lock(&b->lock); | 127 | spin_lock(&b->lock); |
125 | e = _find_apf_task(b, token); | 128 | e = _find_apf_task(b, token); |
126 | if (e) { | 129 | if (e) { |
@@ -128,6 +131,8 @@ void kvm_async_pf_task_wait(u32 token) | |||
128 | hlist_del(&e->link); | 131 | hlist_del(&e->link); |
129 | kfree(e); | 132 | kfree(e); |
130 | spin_unlock(&b->lock); | 133 | spin_unlock(&b->lock); |
134 | |||
135 | rcu_irq_exit(); | ||
131 | return; | 136 | return; |
132 | } | 137 | } |
133 | 138 | ||
@@ -152,13 +157,16 @@ void kvm_async_pf_task_wait(u32 token) | |||
152 | /* | 157 | /* |
153 | * We cannot reschedule. So halt. | 158 | * We cannot reschedule. So halt. |
154 | */ | 159 | */ |
160 | rcu_irq_exit(); | ||
155 | native_safe_halt(); | 161 | native_safe_halt(); |
162 | rcu_irq_enter(); | ||
156 | local_irq_disable(); | 163 | local_irq_disable(); |
157 | } | 164 | } |
158 | } | 165 | } |
159 | if (!n.halted) | 166 | if (!n.halted) |
160 | finish_wait(&n.wq, &wait); | 167 | finish_wait(&n.wq, &wait); |
161 | 168 | ||
169 | rcu_irq_exit(); | ||
162 | return; | 170 | return; |
163 | } | 171 | } |
164 | EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait); | 172 | EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait); |
@@ -252,10 +260,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
252 | break; | 260 | break; |
253 | case KVM_PV_REASON_PAGE_NOT_PRESENT: | 261 | case KVM_PV_REASON_PAGE_NOT_PRESENT: |
254 | /* page is swapped out by the host. */ | 262 | /* page is swapped out by the host. */ |
255 | rcu_irq_enter(); | 263 | exception_enter(regs); |
256 | exit_idle(); | 264 | exit_idle(); |
257 | kvm_async_pf_task_wait((u32)read_cr2()); | 265 | kvm_async_pf_task_wait((u32)read_cr2()); |
258 | rcu_irq_exit(); | 266 | exception_exit(regs); |
259 | break; | 267 | break; |
260 | case KVM_PV_REASON_PAGE_READY: | 268 | case KVM_PV_REASON_PAGE_READY: |
261 | rcu_irq_enter(); | 269 | rcu_irq_enter(); |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 23ddd558fbd5..00f6c1472b85 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -610,6 +610,83 @@ static __init void reserve_ibft_region(void) | |||
610 | 610 | ||
611 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; | 611 | static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; |
612 | 612 | ||
613 | static bool __init snb_gfx_workaround_needed(void) | ||
614 | { | ||
615 | #ifdef CONFIG_PCI | ||
616 | int i; | ||
617 | u16 vendor, devid; | ||
618 | static const __initconst u16 snb_ids[] = { | ||
619 | 0x0102, | ||
620 | 0x0112, | ||
621 | 0x0122, | ||
622 | 0x0106, | ||
623 | 0x0116, | ||
624 | 0x0126, | ||
625 | 0x010a, | ||
626 | }; | ||
627 | |||
628 | /* Assume no if something weird is going on with PCI */ | ||
629 | if (!early_pci_allowed()) | ||
630 | return false; | ||
631 | |||
632 | vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID); | ||
633 | if (vendor != 0x8086) | ||
634 | return false; | ||
635 | |||
636 | devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID); | ||
637 | for (i = 0; i < ARRAY_SIZE(snb_ids); i++) | ||
638 | if (devid == snb_ids[i]) | ||
639 | return true; | ||
640 | #endif | ||
641 | |||
642 | return false; | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | * Sandy Bridge graphics has trouble with certain ranges, exclude | ||
647 | * them from allocation. | ||
648 | */ | ||
649 | static void __init trim_snb_memory(void) | ||
650 | { | ||
651 | static const __initconst unsigned long bad_pages[] = { | ||
652 | 0x20050000, | ||
653 | 0x20110000, | ||
654 | 0x20130000, | ||
655 | 0x20138000, | ||
656 | 0x40004000, | ||
657 | }; | ||
658 | int i; | ||
659 | |||
660 | if (!snb_gfx_workaround_needed()) | ||
661 | return; | ||
662 | |||
663 | printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n"); | ||
664 | |||
665 | /* | ||
666 | * Reserve all memory below the 1 MB mark that has not | ||
667 | * already been reserved. | ||
668 | */ | ||
669 | memblock_reserve(0, 1<<20); | ||
670 | |||
671 | for (i = 0; i < ARRAY_SIZE(bad_pages); i++) { | ||
672 | if (memblock_reserve(bad_pages[i], PAGE_SIZE)) | ||
673 | printk(KERN_WARNING "failed to reserve 0x%08lx\n", | ||
674 | bad_pages[i]); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | /* | ||
679 | * Here we put platform-specific memory range workarounds, i.e. | ||
680 | * memory known to be corrupt or otherwise in need to be reserved on | ||
681 | * specific platforms. | ||
682 | * | ||
683 | * If this gets used more widely it could use a real dispatch mechanism. | ||
684 | */ | ||
685 | static void __init trim_platform_memory_ranges(void) | ||
686 | { | ||
687 | trim_snb_memory(); | ||
688 | } | ||
689 | |||
613 | static void __init trim_bios_range(void) | 690 | static void __init trim_bios_range(void) |
614 | { | 691 | { |
615 | /* | 692 | /* |
@@ -630,6 +707,7 @@ static void __init trim_bios_range(void) | |||
630 | * take them out. | 707 | * take them out. |
631 | */ | 708 | */ |
632 | e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); | 709 | e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); |
710 | |||
633 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); | 711 | sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); |
634 | } | 712 | } |
635 | 713 | ||
@@ -908,6 +986,8 @@ void __init setup_arch(char **cmdline_p) | |||
908 | 986 | ||
909 | setup_real_mode(); | 987 | setup_real_mode(); |
910 | 988 | ||
989 | trim_platform_memory_ranges(); | ||
990 | |||
911 | init_gbpages(); | 991 | init_gbpages(); |
912 | 992 | ||
913 | /* max_pfn_mapped is updated here */ | 993 | /* max_pfn_mapped is updated here */ |
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c index cd3b2438a980..9b4d51d0c0d0 100644 --- a/arch/x86/kernel/step.c +++ b/arch/x86/kernel/step.c | |||
@@ -165,10 +165,11 @@ void set_task_blockstep(struct task_struct *task, bool on) | |||
165 | * Ensure irq/preemption can't change debugctl in between. | 165 | * Ensure irq/preemption can't change debugctl in between. |
166 | * Note also that both TIF_BLOCKSTEP and debugctl should | 166 | * Note also that both TIF_BLOCKSTEP and debugctl should |
167 | * be changed atomically wrt preemption. | 167 | * be changed atomically wrt preemption. |
168 | * FIXME: this means that set/clear TIF_BLOCKSTEP is simply | 168 | * |
169 | * wrong if task != current, SIGKILL can wakeup the stopped | 169 | * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if |
170 | * tracee and set/clear can play with the running task, this | 170 | * task is current or it can't be running, otherwise we can race |
171 | * can confuse the next __switch_to_xtra(). | 171 | * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but |
172 | * PTRACE_KILL is not safe. | ||
172 | */ | 173 | */ |
173 | local_irq_disable(); | 174 | local_irq_disable(); |
174 | debugctl = get_debugctlmsr(); | 175 | debugctl = get_debugctlmsr(); |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 76f54461f7cb..c243b81e3c74 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -120,7 +120,7 @@ struct kvm_shared_msrs { | |||
120 | }; | 120 | }; |
121 | 121 | ||
122 | static struct kvm_shared_msrs_global __read_mostly shared_msrs_global; | 122 | static struct kvm_shared_msrs_global __read_mostly shared_msrs_global; |
123 | static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs); | 123 | static struct kvm_shared_msrs __percpu *shared_msrs; |
124 | 124 | ||
125 | struct kvm_stats_debugfs_item debugfs_entries[] = { | 125 | struct kvm_stats_debugfs_item debugfs_entries[] = { |
126 | { "pf_fixed", VCPU_STAT(pf_fixed) }, | 126 | { "pf_fixed", VCPU_STAT(pf_fixed) }, |
@@ -191,10 +191,10 @@ static void kvm_on_user_return(struct user_return_notifier *urn) | |||
191 | 191 | ||
192 | static void shared_msr_update(unsigned slot, u32 msr) | 192 | static void shared_msr_update(unsigned slot, u32 msr) |
193 | { | 193 | { |
194 | struct kvm_shared_msrs *smsr; | ||
195 | u64 value; | 194 | u64 value; |
195 | unsigned int cpu = smp_processor_id(); | ||
196 | struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); | ||
196 | 197 | ||
197 | smsr = &__get_cpu_var(shared_msrs); | ||
198 | /* only read, and nobody should modify it at this time, | 198 | /* only read, and nobody should modify it at this time, |
199 | * so don't need lock */ | 199 | * so don't need lock */ |
200 | if (slot >= shared_msrs_global.nr) { | 200 | if (slot >= shared_msrs_global.nr) { |
@@ -226,7 +226,8 @@ static void kvm_shared_msr_cpu_online(void) | |||
226 | 226 | ||
227 | void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) | 227 | void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask) |
228 | { | 228 | { |
229 | struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); | 229 | unsigned int cpu = smp_processor_id(); |
230 | struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); | ||
230 | 231 | ||
231 | if (((value ^ smsr->values[slot].curr) & mask) == 0) | 232 | if (((value ^ smsr->values[slot].curr) & mask) == 0) |
232 | return; | 233 | return; |
@@ -242,7 +243,8 @@ EXPORT_SYMBOL_GPL(kvm_set_shared_msr); | |||
242 | 243 | ||
243 | static void drop_user_return_notifiers(void *ignore) | 244 | static void drop_user_return_notifiers(void *ignore) |
244 | { | 245 | { |
245 | struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs); | 246 | unsigned int cpu = smp_processor_id(); |
247 | struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu); | ||
246 | 248 | ||
247 | if (smsr->registered) | 249 | if (smsr->registered) |
248 | kvm_on_user_return(&smsr->urn); | 250 | kvm_on_user_return(&smsr->urn); |
@@ -5233,9 +5235,16 @@ int kvm_arch_init(void *opaque) | |||
5233 | goto out; | 5235 | goto out; |
5234 | } | 5236 | } |
5235 | 5237 | ||
5238 | r = -ENOMEM; | ||
5239 | shared_msrs = alloc_percpu(struct kvm_shared_msrs); | ||
5240 | if (!shared_msrs) { | ||
5241 | printk(KERN_ERR "kvm: failed to allocate percpu kvm_shared_msrs\n"); | ||
5242 | goto out; | ||
5243 | } | ||
5244 | |||
5236 | r = kvm_mmu_module_init(); | 5245 | r = kvm_mmu_module_init(); |
5237 | if (r) | 5246 | if (r) |
5238 | goto out; | 5247 | goto out_free_percpu; |
5239 | 5248 | ||
5240 | kvm_set_mmio_spte_mask(); | 5249 | kvm_set_mmio_spte_mask(); |
5241 | kvm_init_msr_list(); | 5250 | kvm_init_msr_list(); |
@@ -5258,6 +5267,8 @@ int kvm_arch_init(void *opaque) | |||
5258 | 5267 | ||
5259 | return 0; | 5268 | return 0; |
5260 | 5269 | ||
5270 | out_free_percpu: | ||
5271 | free_percpu(shared_msrs); | ||
5261 | out: | 5272 | out: |
5262 | return r; | 5273 | return r; |
5263 | } | 5274 | } |
@@ -5275,6 +5286,7 @@ void kvm_arch_exit(void) | |||
5275 | #endif | 5286 | #endif |
5276 | kvm_x86_ops = NULL; | 5287 | kvm_x86_ops = NULL; |
5277 | kvm_mmu_module_exit(); | 5288 | kvm_mmu_module_exit(); |
5289 | free_percpu(shared_msrs); | ||
5278 | } | 5290 | } |
5279 | 5291 | ||
5280 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) | 5292 | int kvm_emulate_halt(struct kvm_vcpu *vcpu) |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 4f7d2599b484..34bc4cee8887 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -432,13 +432,6 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ | |||
432 | play_dead_common(); | 432 | play_dead_common(); |
433 | HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); | 433 | HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); |
434 | cpu_bringup(); | 434 | cpu_bringup(); |
435 | /* | ||
436 | * Balance out the preempt calls - as we are running in cpu_idle | ||
437 | * loop which has been called at bootup from cpu_bringup_and_idle. | ||
438 | * The cpucpu_bringup_and_idle called cpu_bringup which made a | ||
439 | * preempt_disable() So this preempt_enable will balance it out. | ||
440 | */ | ||
441 | preempt_enable(); | ||
442 | } | 435 | } |
443 | 436 | ||
444 | #else /* !CONFIG_HOTPLUG_CPU */ | 437 | #else /* !CONFIG_HOTPLUG_CPU */ |
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0b..46f80e2c92f7 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, | |||
590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && | 590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && |
591 | *access_bit_width < 32) | 591 | *access_bit_width < 32) |
592 | *access_bit_width = 32; | 592 | *access_bit_width = 32; |
593 | else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && | ||
594 | *access_bit_width < 64) | ||
595 | *access_bit_width = 64; | ||
593 | 596 | ||
594 | if ((bit_width + bit_offset) > *access_bit_width) { | 597 | if ((bit_width + bit_offset) > *access_bit_width) { |
595 | pr_warning(FW_BUG APEI_PFX | 598 | pr_warning(FW_BUG APEI_PFX |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 95af6f674a6c..35da18113216 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -297,7 +297,7 @@ static int acpi_platform_notify(struct device *dev) | |||
297 | if (!ret) { | 297 | if (!ret) { |
298 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 298 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
299 | 299 | ||
300 | acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer); | 300 | acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); |
301 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); | 301 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); |
302 | kfree(buffer.pointer); | 302 | kfree(buffer.pointer); |
303 | } else | 303 | } else |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f1a5da44591d..ed9a1cc690be 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) | |||
958 | return -EINVAL; | 958 | return -EINVAL; |
959 | } | 959 | } |
960 | 960 | ||
961 | if (!dev) | ||
962 | return -EINVAL; | ||
963 | |||
961 | dev->cpu = pr->id; | 964 | dev->cpu = pr->id; |
962 | 965 | ||
963 | if (max_cstate == 0) | 966 | if (max_cstate == 0) |
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1149 | } | 1152 | } |
1150 | 1153 | ||
1151 | /* Populate Updated C-state information */ | 1154 | /* Populate Updated C-state information */ |
1155 | acpi_processor_get_power_info(pr); | ||
1152 | acpi_processor_setup_cpuidle_states(pr); | 1156 | acpi_processor_setup_cpuidle_states(pr); |
1153 | 1157 | ||
1154 | /* Enable all cpuidle devices */ | 1158 | /* Enable all cpuidle devices */ |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe069042..53e7ac9403a7 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) | |||
340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) | 340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) |
341 | || boot_cpu_data.x86 == 0x11) { | 341 | || boot_cpu_data.x86 == 0x11) { |
342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); | 342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); |
343 | /* | ||
344 | * MSR C001_0064+: | ||
345 | * Bit 63: PstateEn. Read-write. If set, the P-state is valid. | ||
346 | */ | ||
347 | if (!(hi & BIT(31))) | ||
348 | return; | ||
349 | |||
343 | fid = lo & 0x3f; | 350 | fid = lo & 0x3f; |
344 | did = (lo >> 6) & 7; | 351 | did = (lo >> 6) & 7; |
345 | if (boot_cpu_data.x86 == 0x10) | 352 | if (boot_cpu_data.x86 == 0x10) |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 7862d17976b7..497912732566 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | enum { | 54 | enum { |
55 | AHCI_PCI_BAR_STA2X11 = 0, | 55 | AHCI_PCI_BAR_STA2X11 = 0, |
56 | AHCI_PCI_BAR_ENMOTUS = 2, | ||
56 | AHCI_PCI_BAR_STANDARD = 5, | 57 | AHCI_PCI_BAR_STANDARD = 5, |
57 | }; | 58 | }; |
58 | 59 | ||
@@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
410 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ | 411 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ |
411 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ | 412 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ |
412 | 413 | ||
414 | /* Enmotus */ | ||
415 | { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, | ||
416 | |||
413 | /* Generic, PCI class code for AHCI */ | 417 | /* Generic, PCI class code for AHCI */ |
414 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 418 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
415 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, | 419 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, |
@@ -1098,9 +1102,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1098 | dev_info(&pdev->dev, | 1102 | dev_info(&pdev->dev, |
1099 | "PDC42819 can only drive SATA devices with this driver\n"); | 1103 | "PDC42819 can only drive SATA devices with this driver\n"); |
1100 | 1104 | ||
1101 | /* The Connext uses non-standard BAR */ | 1105 | /* Both Connext and Enmotus devices use non-standard BARs */ |
1102 | if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) | 1106 | if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) |
1103 | ahci_pci_bar = AHCI_PCI_BAR_STA2X11; | 1107 | ahci_pci_bar = AHCI_PCI_BAR_STA2X11; |
1108 | else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) | ||
1109 | ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; | ||
1104 | 1110 | ||
1105 | /* acquire resources */ | 1111 | /* acquire resources */ |
1106 | rc = pcim_enable_device(pdev); | 1112 | rc = pcim_enable_device(pdev); |
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 320712a7b9ea..6cd7805e47ca 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
@@ -1951,13 +1951,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) | |||
1951 | /* Use the nominal value 10 ms if the read MDAT is zero, | 1951 | /* Use the nominal value 10 ms if the read MDAT is zero, |
1952 | * the nominal value of DETO is 20 ms. | 1952 | * the nominal value of DETO is 20 ms. |
1953 | */ | 1953 | */ |
1954 | if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & | 1954 | if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & |
1955 | ATA_LOG_DEVSLP_VALID_MASK) { | 1955 | ATA_LOG_DEVSLP_VALID_MASK) { |
1956 | mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & | 1956 | mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & |
1957 | ATA_LOG_DEVSLP_MDAT_MASK; | 1957 | ATA_LOG_DEVSLP_MDAT_MASK; |
1958 | if (!mdat) | 1958 | if (!mdat) |
1959 | mdat = 10; | 1959 | mdat = 10; |
1960 | deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; | 1960 | deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; |
1961 | if (!deto) | 1961 | if (!deto) |
1962 | deto = 20; | 1962 | deto = 20; |
1963 | } else { | 1963 | } else { |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9e8b99af400d..46cd3f4c6aaa 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) | |||
2325 | } | 2325 | } |
2326 | } | 2326 | } |
2327 | 2327 | ||
2328 | /* check and mark DevSlp capability */ | 2328 | /* Check and mark DevSlp capability. Get DevSlp timing variables |
2329 | if (ata_id_has_devslp(dev->id)) | 2329 | * from SATA Settings page of Identify Device Data Log. |
2330 | dev->flags |= ATA_DFLAG_DEVSLP; | ||
2331 | |||
2332 | /* Obtain SATA Settings page from Identify Device Data Log, | ||
2333 | * which contains DevSlp timing variables etc. | ||
2334 | * Exclude old devices with ata_id_has_ncq() | ||
2335 | */ | 2330 | */ |
2336 | if (ata_id_has_ncq(dev->id)) { | 2331 | if (ata_id_has_devslp(dev->id)) { |
2332 | u8 sata_setting[ATA_SECT_SIZE]; | ||
2333 | int i, j; | ||
2334 | |||
2335 | dev->flags |= ATA_DFLAG_DEVSLP; | ||
2337 | err_mask = ata_read_log_page(dev, | 2336 | err_mask = ata_read_log_page(dev, |
2338 | ATA_LOG_SATA_ID_DEV_DATA, | 2337 | ATA_LOG_SATA_ID_DEV_DATA, |
2339 | ATA_LOG_SATA_SETTINGS, | 2338 | ATA_LOG_SATA_SETTINGS, |
2340 | dev->sata_settings, | 2339 | sata_setting, |
2341 | 1); | 2340 | 1); |
2342 | if (err_mask) | 2341 | if (err_mask) |
2343 | ata_dev_dbg(dev, | 2342 | ata_dev_dbg(dev, |
2344 | "failed to get Identify Device Data, Emask 0x%x\n", | 2343 | "failed to get Identify Device Data, Emask 0x%x\n", |
2345 | err_mask); | 2344 | err_mask); |
2345 | else | ||
2346 | for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { | ||
2347 | j = ATA_LOG_DEVSLP_OFFSET + i; | ||
2348 | dev->devslp_timing[i] = sata_setting[j]; | ||
2349 | } | ||
2346 | } | 2350 | } |
2347 | 2351 | ||
2348 | dev->cdb_len = 16; | 2352 | dev->cdb_len = 16; |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index bf039b0e97b7..bcf4437214f5 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, | |||
2094 | */ | 2094 | */ |
2095 | static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) | 2095 | static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) |
2096 | { | 2096 | { |
2097 | if (qc->flags & AC_ERR_MEDIA) | 2097 | if (qc->err_mask & AC_ERR_MEDIA) |
2098 | return 0; /* don't retry media errors */ | 2098 | return 0; /* don't retry media errors */ |
2099 | if (qc->flags & ATA_QCFLAG_IO) | 2099 | if (qc->flags & ATA_QCFLAG_IO) |
2100 | return 1; /* otherwise retry anything from fs stack */ | 2100 | return 1; /* otherwise retry anything from fs stack */ |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 63452943abd1..fb10728f6372 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -224,7 +224,7 @@ static void cpu_device_release(struct device *dev) | |||
224 | * by the cpu device. | 224 | * by the cpu device. |
225 | * | 225 | * |
226 | * Never copy this way of doing things, or you too will be made fun of | 226 | * Never copy this way of doing things, or you too will be made fun of |
227 | * on the linux-kerenl list, you have been warned. | 227 | * on the linux-kernel list, you have been warned. |
228 | */ | 228 | */ |
229 | } | 229 | } |
230 | 230 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d81460309182..b392b353be39 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -305,7 +305,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf | |||
305 | char *buf; | 305 | char *buf; |
306 | 306 | ||
307 | size = fw_file_size(file); | 307 | size = fw_file_size(file); |
308 | if (size < 0) | 308 | if (size <= 0) |
309 | return false; | 309 | return false; |
310 | buf = vmalloc(size); | 310 | buf = vmalloc(size); |
311 | if (!buf) | 311 | if (!buf) |
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 07aad786f817..d9a6c94ce423 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = { | |||
56 | .llseek = default_llseek, | 56 | .llseek = default_llseek, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static void regmap_debugfs_free_dump_cache(struct regmap *map) | ||
60 | { | ||
61 | struct regmap_debugfs_off_cache *c; | ||
62 | |||
63 | while (!list_empty(&map->debugfs_off_cache)) { | ||
64 | c = list_first_entry(&map->debugfs_off_cache, | ||
65 | struct regmap_debugfs_off_cache, | ||
66 | list); | ||
67 | list_del(&c->list); | ||
68 | kfree(c); | ||
69 | } | ||
70 | } | ||
71 | |||
59 | /* | 72 | /* |
60 | * Work out where the start offset maps into register numbers, bearing | 73 | * Work out where the start offset maps into register numbers, bearing |
61 | * in mind that we suppress hidden registers. | 74 | * in mind that we suppress hidden registers. |
@@ -91,8 +104,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
91 | /* No cache entry? Start a new one */ | 104 | /* No cache entry? Start a new one */ |
92 | if (!c) { | 105 | if (!c) { |
93 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 106 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
94 | if (!c) | 107 | if (!c) { |
95 | break; | 108 | regmap_debugfs_free_dump_cache(map); |
109 | return base; | ||
110 | } | ||
96 | c->min = p; | 111 | c->min = p; |
97 | c->base_reg = i; | 112 | c->base_reg = i; |
98 | } | 113 | } |
@@ -101,14 +116,32 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
101 | } | 116 | } |
102 | } | 117 | } |
103 | 118 | ||
119 | /* Close the last entry off if we didn't scan beyond it */ | ||
120 | if (c) { | ||
121 | c->max = p - 1; | ||
122 | list_add_tail(&c->list, | ||
123 | &map->debugfs_off_cache); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * This should never happen; we return above if we fail to | ||
128 | * allocate and we should never be in this code if there are | ||
129 | * no registers at all. | ||
130 | */ | ||
131 | if (list_empty(&map->debugfs_off_cache)) { | ||
132 | WARN_ON(list_empty(&map->debugfs_off_cache)); | ||
133 | return base; | ||
134 | } | ||
135 | |||
104 | /* Find the relevant block */ | 136 | /* Find the relevant block */ |
105 | list_for_each_entry(c, &map->debugfs_off_cache, list) { | 137 | list_for_each_entry(c, &map->debugfs_off_cache, list) { |
106 | if (*pos >= c->min && *pos <= c->max) { | 138 | if (from >= c->min && from <= c->max) { |
107 | *pos = c->min; | 139 | *pos = c->min; |
108 | return c->base_reg; | 140 | return c->base_reg; |
109 | } | 141 | } |
110 | 142 | ||
111 | ret = c->max; | 143 | *pos = c->min; |
144 | ret = c->base_reg; | ||
112 | } | 145 | } |
113 | 146 | ||
114 | return ret; | 147 | return ret; |
@@ -387,16 +420,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
387 | 420 | ||
388 | void regmap_debugfs_exit(struct regmap *map) | 421 | void regmap_debugfs_exit(struct regmap *map) |
389 | { | 422 | { |
390 | struct regmap_debugfs_off_cache *c; | ||
391 | |||
392 | debugfs_remove_recursive(map->debugfs); | 423 | debugfs_remove_recursive(map->debugfs); |
393 | while (!list_empty(&map->debugfs_off_cache)) { | 424 | regmap_debugfs_free_dump_cache(map); |
394 | c = list_first_entry(&map->debugfs_off_cache, | ||
395 | struct regmap_debugfs_off_cache, | ||
396 | list); | ||
397 | list_del(&c->list); | ||
398 | kfree(c); | ||
399 | } | ||
400 | kfree(map->debugfs_name); | 425 | kfree(map->debugfs_name); |
401 | } | 426 | } |
402 | 427 | ||
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 42d5cb0f503f..f00b059c057a 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -1106,7 +1106,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write); | |||
1106 | * @val_count: Number of registers to write | 1106 | * @val_count: Number of registers to write |
1107 | * | 1107 | * |
1108 | * This function is intended to be used for writing a large block of | 1108 | * This function is intended to be used for writing a large block of |
1109 | * data to be device either in single transfer or multiple transfer. | 1109 | * data to the device either in single transfer or multiple transfer. |
1110 | * | 1110 | * |
1111 | * A value of zero will be returned on success, a negative errno will | 1111 | * A value of zero will be returned on success, a negative errno will |
1112 | * be returned in error cases. | 1112 | * be returned in error cases. |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9d8409c02082..8ad21a25bc0d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
889 | { | 889 | { |
890 | struct virtio_blk *vblk = vdev->priv; | 890 | struct virtio_blk *vblk = vdev->priv; |
891 | int index = vblk->index; | 891 | int index = vblk->index; |
892 | int refc; | ||
892 | 893 | ||
893 | /* Prevent config work handler from accessing the device. */ | 894 | /* Prevent config work handler from accessing the device. */ |
894 | mutex_lock(&vblk->config_lock); | 895 | mutex_lock(&vblk->config_lock); |
@@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
903 | 904 | ||
904 | flush_work(&vblk->config_work); | 905 | flush_work(&vblk->config_work); |
905 | 906 | ||
907 | refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); | ||
906 | put_disk(vblk->disk); | 908 | put_disk(vblk->disk); |
907 | mempool_destroy(vblk->pool); | 909 | mempool_destroy(vblk->pool); |
908 | vdev->config->del_vqs(vdev); | 910 | vdev->config->del_vqs(vdev); |
909 | kfree(vblk); | 911 | kfree(vblk); |
910 | ida_simple_remove(&vd_index_ida, index); | 912 | |
913 | /* Only free device id if we don't have any users */ | ||
914 | if (refc == 1) | ||
915 | ida_simple_remove(&vd_index_ida, index); | ||
911 | } | 916 | } |
912 | 917 | ||
913 | #ifdef CONFIG_PM | 918 | #ifdef CONFIG_PM |
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index ff004578a119..9dd2551a0a41 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c | |||
@@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
124 | 124 | ||
125 | clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); | 125 | clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); |
126 | if (WARN_ON(!clks)) | 126 | if (WARN_ON(!clks)) |
127 | return; | 127 | goto clks_out; |
128 | 128 | ||
129 | for_each_node_by_type(dn, "cpu") { | 129 | for_each_node_by_type(dn, "cpu") { |
130 | struct clk_init_data init; | 130 | struct clk_init_data init; |
@@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
134 | int cpu, err; | 134 | int cpu, err; |
135 | 135 | ||
136 | if (WARN_ON(!clk_name)) | 136 | if (WARN_ON(!clk_name)) |
137 | return; | 137 | goto bail_out; |
138 | 138 | ||
139 | err = of_property_read_u32(dn, "reg", &cpu); | 139 | err = of_property_read_u32(dn, "reg", &cpu); |
140 | if (WARN_ON(err)) | 140 | if (WARN_ON(err)) |
141 | return; | 141 | goto bail_out; |
142 | 142 | ||
143 | sprintf(clk_name, "cpu%d", cpu); | 143 | sprintf(clk_name, "cpu%d", cpu); |
144 | parent_clk = of_clk_get(node, 0); | 144 | parent_clk = of_clk_get(node, 0); |
@@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
167 | return; | 167 | return; |
168 | bail_out: | 168 | bail_out: |
169 | kfree(clks); | 169 | kfree(clks); |
170 | while(ncpus--) | ||
171 | kfree(cpuclk[ncpus].clk_name); | ||
172 | clks_out: | ||
170 | kfree(cpuclk); | 173 | kfree(cpuclk); |
171 | } | 174 | } |
172 | 175 | ||
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 934854ae5eb4..7227cd734042 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 | |||
@@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI | |||
106 | config X86_POWERNOW_K8 | 106 | config X86_POWERNOW_K8 |
107 | tristate "AMD Opteron/Athlon64 PowerNow!" | 107 | tristate "AMD Opteron/Athlon64 PowerNow!" |
108 | select CPU_FREQ_TABLE | 108 | select CPU_FREQ_TABLE |
109 | depends on ACPI && ACPI_PROCESSOR | 109 | depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ |
110 | help | 110 | help |
111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. | 111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. |
112 | Support for K10 and newer processors is now in acpi-cpufreq. | 112 | Support for K10 and newer processors is now in acpi-cpufreq. |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0d048f6a2b23..7b0d49d78c61 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict, | |||
1030 | late_initcall(acpi_cpufreq_init); | 1030 | late_initcall(acpi_cpufreq_init); |
1031 | module_exit(acpi_cpufreq_exit); | 1031 | module_exit(acpi_cpufreq_exit); |
1032 | 1032 | ||
1033 | static const struct x86_cpu_id acpi_cpufreq_ids[] = { | ||
1034 | X86_FEATURE_MATCH(X86_FEATURE_ACPI), | ||
1035 | X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), | ||
1036 | {} | ||
1037 | }; | ||
1038 | MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); | ||
1039 | |||
1033 | MODULE_ALIAS("acpi"); | 1040 | MODULE_ALIAS("acpi"); |
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 52bf36d599f5..debc5a7c8db6 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c | |||
@@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, | |||
71 | } | 71 | } |
72 | 72 | ||
73 | if (cpu_reg) { | 73 | if (cpu_reg) { |
74 | rcu_read_lock(); | ||
74 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); | 75 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); |
75 | if (IS_ERR(opp)) { | 76 | if (IS_ERR(opp)) { |
77 | rcu_read_unlock(); | ||
76 | pr_err("failed to find OPP for %ld\n", freq_Hz); | 78 | pr_err("failed to find OPP for %ld\n", freq_Hz); |
77 | return PTR_ERR(opp); | 79 | return PTR_ERR(opp); |
78 | } | 80 | } |
79 | volt = opp_get_voltage(opp); | 81 | volt = opp_get_voltage(opp); |
82 | rcu_read_unlock(); | ||
80 | tol = volt * voltage_tolerance / 100; | 83 | tol = volt * voltage_tolerance / 100; |
81 | volt_old = regulator_get_voltage(cpu_reg); | 84 | volt_old = regulator_get_voltage(cpu_reg); |
82 | } | 85 | } |
@@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void) | |||
236 | */ | 239 | */ |
237 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 240 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) |
238 | ; | 241 | ; |
242 | rcu_read_lock(); | ||
239 | opp = opp_find_freq_exact(cpu_dev, | 243 | opp = opp_find_freq_exact(cpu_dev, |
240 | freq_table[0].frequency * 1000, true); | 244 | freq_table[0].frequency * 1000, true); |
241 | min_uV = opp_get_voltage(opp); | 245 | min_uV = opp_get_voltage(opp); |
242 | opp = opp_find_freq_exact(cpu_dev, | 246 | opp = opp_find_freq_exact(cpu_dev, |
243 | freq_table[i-1].frequency * 1000, true); | 247 | freq_table[i-1].frequency * 1000, true); |
244 | max_uV = opp_get_voltage(opp); | 248 | max_uV = opp_get_voltage(opp); |
249 | rcu_read_unlock(); | ||
245 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); | 250 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); |
246 | if (ret > 0) | 251 | if (ret > 0) |
247 | transition_latency += ret * 1000; | 252 | transition_latency += ret * 1000; |
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 1f3417a8322d..97102b05843f 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c | |||
@@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy, | |||
110 | freq = ret; | 110 | freq = ret; |
111 | 111 | ||
112 | if (mpu_reg) { | 112 | if (mpu_reg) { |
113 | rcu_read_lock(); | ||
113 | opp = opp_find_freq_ceil(mpu_dev, &freq); | 114 | opp = opp_find_freq_ceil(mpu_dev, &freq); |
114 | if (IS_ERR(opp)) { | 115 | if (IS_ERR(opp)) { |
116 | rcu_read_unlock(); | ||
115 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", | 117 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", |
116 | __func__, freqs.new); | 118 | __func__, freqs.new); |
117 | return -EINVAL; | 119 | return -EINVAL; |
118 | } | 120 | } |
119 | volt = opp_get_voltage(opp); | 121 | volt = opp_get_voltage(opp); |
122 | rcu_read_unlock(); | ||
120 | tol = volt * OPP_TOLERANCE / 100; | 123 | tol = volt * OPP_TOLERANCE / 100; |
121 | volt_old = regulator_get_voltage(mpu_reg); | 124 | volt_old = regulator_get_voltage(mpu_reg); |
122 | } | 125 | } |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fb4a7dd57f94..e1f6860e069c 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -69,24 +69,15 @@ int cpuidle_play_dead(void) | |||
69 | { | 69 | { |
70 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | 70 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); |
71 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 71 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
72 | int i, dead_state = -1; | 72 | int i; |
73 | int power_usage = INT_MAX; | ||
74 | 73 | ||
75 | if (!drv) | 74 | if (!drv) |
76 | return -ENODEV; | 75 | return -ENODEV; |
77 | 76 | ||
78 | /* Find lowest-power state that supports long-term idle */ | 77 | /* Find lowest-power state that supports long-term idle */ |
79 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 78 | for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) |
80 | struct cpuidle_state *s = &drv->states[i]; | 79 | if (drv->states[i].enter_dead) |
81 | 80 | return drv->states[i].enter_dead(dev, i); | |
82 | if (s->power_usage < power_usage && s->enter_dead) { | ||
83 | power_usage = s->power_usage; | ||
84 | dead_state = i; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if (dead_state != -1) | ||
89 | return drv->states[dead_state].enter_dead(dev, dead_state); | ||
90 | 81 | ||
91 | return -ENODEV; | 82 | return -ENODEV; |
92 | } | 83 | } |
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index c2b281afe0ed..422c7b69ba7c 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -19,34 +19,9 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); | |||
19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); | 19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); |
20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); | 20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); |
21 | 21 | ||
22 | static void set_power_states(struct cpuidle_driver *drv) | ||
23 | { | ||
24 | int i; | ||
25 | |||
26 | /* | ||
27 | * cpuidle driver should set the drv->power_specified bit | ||
28 | * before registering if the driver provides | ||
29 | * power_usage numbers. | ||
30 | * | ||
31 | * If power_specified is not set, | ||
32 | * we fill in power_usage with decreasing values as the | ||
33 | * cpuidle code has an implicit assumption that state Cn | ||
34 | * uses less power than C(n-1). | ||
35 | * | ||
36 | * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned | ||
37 | * an power value of -1. So we use -2, -3, etc, for other | ||
38 | * c-states. | ||
39 | */ | ||
40 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) | ||
41 | drv->states[i].power_usage = -1 - i; | ||
42 | } | ||
43 | |||
44 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) | 22 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) |
45 | { | 23 | { |
46 | drv->refcnt = 0; | 24 | drv->refcnt = 0; |
47 | |||
48 | if (!drv->power_specified) | ||
49 | set_power_states(drv); | ||
50 | } | 25 | } |
51 | 26 | ||
52 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) | 27 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 20ea33afdda1..fe343a06b7da 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -312,7 +312,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
312 | { | 312 | { |
313 | struct menu_device *data = &__get_cpu_var(menu_devices); | 313 | struct menu_device *data = &__get_cpu_var(menu_devices); |
314 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 314 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
315 | int power_usage = INT_MAX; | ||
316 | int i; | 315 | int i; |
317 | int multiplier; | 316 | int multiplier; |
318 | struct timespec t; | 317 | struct timespec t; |
@@ -383,11 +382,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
383 | if (s->exit_latency * multiplier > data->predicted_us) | 382 | if (s->exit_latency * multiplier > data->predicted_us) |
384 | continue; | 383 | continue; |
385 | 384 | ||
386 | if (s->power_usage < power_usage) { | 385 | data->last_state_idx = i; |
387 | power_usage = s->power_usage; | 386 | data->exit_us = s->exit_latency; |
388 | data->last_state_idx = i; | ||
389 | data->exit_us = s->exit_latency; | ||
390 | } | ||
391 | } | 387 | } |
392 | 388 | ||
393 | /* not deepest C-state chosen for low predicted residency */ | 389 | /* not deepest C-state chosen for low predicted residency */ |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 340942946106..428754af6236 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -374,7 +374,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) | |||
374 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); | 374 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); |
375 | 375 | ||
376 | /* state statistics */ | 376 | /* state statistics */ |
377 | for (i = 0; i < drv->state_count; i++) { | 377 | for (i = 0; i < device->state_count; i++) { |
378 | kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); | 378 | kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); |
379 | if (!kobj) | 379 | if (!kobj) |
380 | goto error_state; | 380 | goto error_state; |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 53766f39aadd..3b367973a802 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -994,6 +994,11 @@ module_exit(devfreq_exit); | |||
994 | * @freq: The frequency given to target function | 994 | * @freq: The frequency given to target function |
995 | * @flags: Flags handed from devfreq framework. | 995 | * @flags: Flags handed from devfreq framework. |
996 | * | 996 | * |
997 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
998 | * protected pointer. The reason for the same is that the opp pointer which is | ||
999 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
1000 | * under the locked area. The pointer returned must be used prior to unlocking | ||
1001 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
997 | */ | 1002 | */ |
998 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, | 1003 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, |
999 | u32 flags) | 1004 | u32 flags) |
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 80c745e83082..46d94e9e95b5 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c | |||
@@ -73,6 +73,16 @@ enum busclk_level_idx { | |||
73 | #define EX4210_LV_NUM (LV_2 + 1) | 73 | #define EX4210_LV_NUM (LV_2 + 1) |
74 | #define EX4x12_LV_NUM (LV_4 + 1) | 74 | #define EX4x12_LV_NUM (LV_4 + 1) |
75 | 75 | ||
76 | /** | ||
77 | * struct busfreq_opp_info - opp information for bus | ||
78 | * @rate: Frequency in hertz | ||
79 | * @volt: Voltage in microvolts corresponding to this OPP | ||
80 | */ | ||
81 | struct busfreq_opp_info { | ||
82 | unsigned long rate; | ||
83 | unsigned long volt; | ||
84 | }; | ||
85 | |||
76 | struct busfreq_data { | 86 | struct busfreq_data { |
77 | enum exynos4_busf_type type; | 87 | enum exynos4_busf_type type; |
78 | struct device *dev; | 88 | struct device *dev; |
@@ -80,7 +90,7 @@ struct busfreq_data { | |||
80 | bool disabled; | 90 | bool disabled; |
81 | struct regulator *vdd_int; | 91 | struct regulator *vdd_int; |
82 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ | 92 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ |
83 | struct opp *curr_opp; | 93 | struct busfreq_opp_info curr_oppinfo; |
84 | struct exynos4_ppmu dmc[2]; | 94 | struct exynos4_ppmu dmc[2]; |
85 | 95 | ||
86 | struct notifier_block pm_notifier; | 96 | struct notifier_block pm_notifier; |
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { | |||
296 | }; | 306 | }; |
297 | 307 | ||
298 | 308 | ||
299 | static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | 309 | static int exynos4210_set_busclk(struct busfreq_data *data, |
310 | struct busfreq_opp_info *oppi) | ||
300 | { | 311 | { |
301 | unsigned int index; | 312 | unsigned int index; |
302 | unsigned int tmp; | 313 | unsigned int tmp; |
303 | 314 | ||
304 | for (index = LV_0; index < EX4210_LV_NUM; index++) | 315 | for (index = LV_0; index < EX4210_LV_NUM; index++) |
305 | if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) | 316 | if (oppi->rate == exynos4210_busclk_table[index].clk) |
306 | break; | 317 | break; |
307 | 318 | ||
308 | if (index == EX4210_LV_NUM) | 319 | if (index == EX4210_LV_NUM) |
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | |||
361 | return 0; | 372 | return 0; |
362 | } | 373 | } |
363 | 374 | ||
364 | static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) | 375 | static int exynos4x12_set_busclk(struct busfreq_data *data, |
376 | struct busfreq_opp_info *oppi) | ||
365 | { | 377 | { |
366 | unsigned int index; | 378 | unsigned int index; |
367 | unsigned int tmp; | 379 | unsigned int tmp; |
368 | 380 | ||
369 | for (index = LV_0; index < EX4x12_LV_NUM; index++) | 381 | for (index = LV_0; index < EX4x12_LV_NUM; index++) |
370 | if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) | 382 | if (oppi->rate == exynos4x12_mifclk_table[index].clk) |
371 | break; | 383 | break; |
372 | 384 | ||
373 | if (index == EX4x12_LV_NUM) | 385 | if (index == EX4x12_LV_NUM) |
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) | |||
576 | return -EINVAL; | 588 | return -EINVAL; |
577 | } | 589 | } |
578 | 590 | ||
579 | static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | 591 | static int exynos4_bus_setvolt(struct busfreq_data *data, |
580 | struct opp *oldopp) | 592 | struct busfreq_opp_info *oppi, |
593 | struct busfreq_opp_info *oldoppi) | ||
581 | { | 594 | { |
582 | int err = 0, tmp; | 595 | int err = 0, tmp; |
583 | unsigned long volt = opp_get_voltage(opp); | 596 | unsigned long volt = oppi->volt; |
584 | 597 | ||
585 | switch (data->type) { | 598 | switch (data->type) { |
586 | case TYPE_BUSF_EXYNOS4210: | 599 | case TYPE_BUSF_EXYNOS4210: |
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
595 | if (err) | 608 | if (err) |
596 | break; | 609 | break; |
597 | 610 | ||
598 | tmp = exynos4x12_get_intspec(opp_get_freq(opp)); | 611 | tmp = exynos4x12_get_intspec(oppi->rate); |
599 | if (tmp < 0) { | 612 | if (tmp < 0) { |
600 | err = tmp; | 613 | err = tmp; |
601 | regulator_set_voltage(data->vdd_mif, | 614 | regulator_set_voltage(data->vdd_mif, |
602 | opp_get_voltage(oldopp), | 615 | oldoppi->volt, |
603 | MAX_SAFEVOLT); | 616 | MAX_SAFEVOLT); |
604 | break; | 617 | break; |
605 | } | 618 | } |
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
609 | /* Try to recover */ | 622 | /* Try to recover */ |
610 | if (err) | 623 | if (err) |
611 | regulator_set_voltage(data->vdd_mif, | 624 | regulator_set_voltage(data->vdd_mif, |
612 | opp_get_voltage(oldopp), | 625 | oldoppi->volt, |
613 | MAX_SAFEVOLT); | 626 | MAX_SAFEVOLT); |
614 | break; | 627 | break; |
615 | default: | 628 | default: |
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
626 | struct platform_device *pdev = container_of(dev, struct platform_device, | 639 | struct platform_device *pdev = container_of(dev, struct platform_device, |
627 | dev); | 640 | dev); |
628 | struct busfreq_data *data = platform_get_drvdata(pdev); | 641 | struct busfreq_data *data = platform_get_drvdata(pdev); |
629 | struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); | 642 | struct opp *opp; |
630 | unsigned long freq = opp_get_freq(opp); | 643 | unsigned long freq; |
631 | unsigned long old_freq = opp_get_freq(data->curr_opp); | 644 | unsigned long old_freq = data->curr_oppinfo.rate; |
645 | struct busfreq_opp_info new_oppinfo; | ||
632 | 646 | ||
633 | if (IS_ERR(opp)) | 647 | rcu_read_lock(); |
648 | opp = devfreq_recommended_opp(dev, _freq, flags); | ||
649 | if (IS_ERR(opp)) { | ||
650 | rcu_read_unlock(); | ||
634 | return PTR_ERR(opp); | 651 | return PTR_ERR(opp); |
652 | } | ||
653 | new_oppinfo.rate = opp_get_freq(opp); | ||
654 | new_oppinfo.volt = opp_get_voltage(opp); | ||
655 | rcu_read_unlock(); | ||
656 | freq = new_oppinfo.rate; | ||
635 | 657 | ||
636 | if (old_freq == freq) | 658 | if (old_freq == freq) |
637 | return 0; | 659 | return 0; |
638 | 660 | ||
639 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp)); | 661 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt); |
640 | 662 | ||
641 | mutex_lock(&data->lock); | 663 | mutex_lock(&data->lock); |
642 | 664 | ||
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
644 | goto out; | 666 | goto out; |
645 | 667 | ||
646 | if (old_freq < freq) | 668 | if (old_freq < freq) |
647 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 669 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
670 | &data->curr_oppinfo); | ||
648 | if (err) | 671 | if (err) |
649 | goto out; | 672 | goto out; |
650 | 673 | ||
651 | if (old_freq != freq) { | 674 | if (old_freq != freq) { |
652 | switch (data->type) { | 675 | switch (data->type) { |
653 | case TYPE_BUSF_EXYNOS4210: | 676 | case TYPE_BUSF_EXYNOS4210: |
654 | err = exynos4210_set_busclk(data, opp); | 677 | err = exynos4210_set_busclk(data, &new_oppinfo); |
655 | break; | 678 | break; |
656 | case TYPE_BUSF_EXYNOS4x12: | 679 | case TYPE_BUSF_EXYNOS4x12: |
657 | err = exynos4x12_set_busclk(data, opp); | 680 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
658 | break; | 681 | break; |
659 | default: | 682 | default: |
660 | err = -EINVAL; | 683 | err = -EINVAL; |
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
664 | goto out; | 687 | goto out; |
665 | 688 | ||
666 | if (old_freq > freq) | 689 | if (old_freq > freq) |
667 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 690 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
691 | &data->curr_oppinfo); | ||
668 | if (err) | 692 | if (err) |
669 | goto out; | 693 | goto out; |
670 | 694 | ||
671 | data->curr_opp = opp; | 695 | data->curr_oppinfo = new_oppinfo; |
672 | out: | 696 | out: |
673 | mutex_unlock(&data->lock); | 697 | mutex_unlock(&data->lock); |
674 | return err; | 698 | return err; |
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, | |||
702 | 726 | ||
703 | exynos4_read_ppmu(data); | 727 | exynos4_read_ppmu(data); |
704 | busier_dmc = exynos4_get_busier_dmc(data); | 728 | busier_dmc = exynos4_get_busier_dmc(data); |
705 | stat->current_frequency = opp_get_freq(data->curr_opp); | 729 | stat->current_frequency = data->curr_oppinfo.rate; |
706 | 730 | ||
707 | if (busier_dmc) | 731 | if (busier_dmc) |
708 | addr = S5P_VA_DMC1; | 732 | addr = S5P_VA_DMC1; |
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
933 | struct busfreq_data *data = container_of(this, struct busfreq_data, | 957 | struct busfreq_data *data = container_of(this, struct busfreq_data, |
934 | pm_notifier); | 958 | pm_notifier); |
935 | struct opp *opp; | 959 | struct opp *opp; |
960 | struct busfreq_opp_info new_oppinfo; | ||
936 | unsigned long maxfreq = ULONG_MAX; | 961 | unsigned long maxfreq = ULONG_MAX; |
937 | int err = 0; | 962 | int err = 0; |
938 | 963 | ||
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
943 | 968 | ||
944 | data->disabled = true; | 969 | data->disabled = true; |
945 | 970 | ||
971 | rcu_read_lock(); | ||
946 | opp = opp_find_freq_floor(data->dev, &maxfreq); | 972 | opp = opp_find_freq_floor(data->dev, &maxfreq); |
973 | if (IS_ERR(opp)) { | ||
974 | rcu_read_unlock(); | ||
975 | dev_err(data->dev, "%s: unable to find a min freq\n", | ||
976 | __func__); | ||
977 | return PTR_ERR(opp); | ||
978 | } | ||
979 | new_oppinfo.rate = opp_get_freq(opp); | ||
980 | new_oppinfo.volt = opp_get_voltage(opp); | ||
981 | rcu_read_unlock(); | ||
947 | 982 | ||
948 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 983 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
984 | &data->curr_oppinfo); | ||
949 | if (err) | 985 | if (err) |
950 | goto unlock; | 986 | goto unlock; |
951 | 987 | ||
952 | switch (data->type) { | 988 | switch (data->type) { |
953 | case TYPE_BUSF_EXYNOS4210: | 989 | case TYPE_BUSF_EXYNOS4210: |
954 | err = exynos4210_set_busclk(data, opp); | 990 | err = exynos4210_set_busclk(data, &new_oppinfo); |
955 | break; | 991 | break; |
956 | case TYPE_BUSF_EXYNOS4x12: | 992 | case TYPE_BUSF_EXYNOS4x12: |
957 | err = exynos4x12_set_busclk(data, opp); | 993 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
958 | break; | 994 | break; |
959 | default: | 995 | default: |
960 | err = -EINVAL; | 996 | err = -EINVAL; |
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
962 | if (err) | 998 | if (err) |
963 | goto unlock; | 999 | goto unlock; |
964 | 1000 | ||
965 | data->curr_opp = opp; | 1001 | data->curr_oppinfo = new_oppinfo; |
966 | unlock: | 1002 | unlock: |
967 | mutex_unlock(&data->lock); | 1003 | mutex_unlock(&data->lock); |
968 | if (err) | 1004 | if (err) |
@@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) | |||
1027 | } | 1063 | } |
1028 | } | 1064 | } |
1029 | 1065 | ||
1066 | rcu_read_lock(); | ||
1030 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); | 1067 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); |
1031 | if (IS_ERR(opp)) { | 1068 | if (IS_ERR(opp)) { |
1069 | rcu_read_unlock(); | ||
1032 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", | 1070 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", |
1033 | exynos4_devfreq_profile.initial_freq); | 1071 | exynos4_devfreq_profile.initial_freq); |
1034 | return PTR_ERR(opp); | 1072 | return PTR_ERR(opp); |
1035 | } | 1073 | } |
1036 | data->curr_opp = opp; | 1074 | data->curr_oppinfo.rate = opp_get_freq(opp); |
1075 | data->curr_oppinfo.volt = opp_get_voltage(opp); | ||
1076 | rcu_read_unlock(); | ||
1037 | 1077 | ||
1038 | platform_set_drvdata(pdev, data); | 1078 | platform_set_drvdata(pdev, data); |
1039 | 1079 | ||
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index dbf0e6f8de8a..a7dcf78b1ff8 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
@@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
684 | break; | 684 | break; |
685 | } | 685 | } |
686 | 686 | ||
687 | imxdmac->hw_chaining = 1; | 687 | imxdmac->hw_chaining = 0; |
688 | if (!imxdma_hw_chain(imxdmac)) | 688 | |
689 | return -EINVAL; | ||
690 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | | 689 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | |
691 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | | 690 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | |
692 | CCR_REN; | 691 | CCR_REN; |
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e5fc944de1f0..3e9d66920eb3 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -951,7 +951,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) | |||
951 | goto free_resources; | 951 | goto free_resources; |
952 | } | 952 | } |
953 | } | 953 | } |
954 | dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); | 954 | dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); |
955 | 955 | ||
956 | /* skip validate if the capability is not present */ | 956 | /* skip validate if the capability is not present */ |
957 | if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) | 957 | if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) |
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index c39e61bc8172..3cad856fe67f 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c | |||
@@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( | |||
266 | if (async_tx_test_ack(&dma_desc->txd)) { | 266 | if (async_tx_test_ack(&dma_desc->txd)) { |
267 | list_del(&dma_desc->node); | 267 | list_del(&dma_desc->node); |
268 | spin_unlock_irqrestore(&tdc->lock, flags); | 268 | spin_unlock_irqrestore(&tdc->lock, flags); |
269 | dma_desc->txd.flags = 0; | ||
269 | return dma_desc; | 270 | return dma_desc; |
270 | } | 271 | } |
271 | } | 272 | } |
@@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | |||
1050 | TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; | 1051 | TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; |
1051 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; | 1052 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; |
1052 | 1053 | ||
1053 | csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC; | 1054 | csr |= TEGRA_APBDMA_CSR_FLOW; |
1055 | if (flags & DMA_PREP_INTERRUPT) | ||
1056 | csr |= TEGRA_APBDMA_CSR_IE_EOC; | ||
1054 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; | 1057 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; |
1055 | 1058 | ||
1056 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; | 1059 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; |
@@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | |||
1095 | mem += len; | 1098 | mem += len; |
1096 | } | 1099 | } |
1097 | sg_req->last_sg = true; | 1100 | sg_req->last_sg = true; |
1098 | dma_desc->txd.flags = 0; | 1101 | if (flags & DMA_CTRL_ACK) |
1102 | dma_desc->txd.flags = DMA_CTRL_ACK; | ||
1099 | 1103 | ||
1100 | /* | 1104 | /* |
1101 | * Make sure that mode should not be conflicting with currently | 1105 | * Make sure that mode should not be conflicting with currently |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7d9bd94be8d2..6819d63cb167 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
547 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); | 547 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); |
548 | if (! mvchip->membase) { | 548 | if (! mvchip->membase) { |
549 | dev_err(&pdev->dev, "Cannot ioremap\n"); | 549 | dev_err(&pdev->dev, "Cannot ioremap\n"); |
550 | kfree(mvchip->chip.label); | ||
551 | return -ENOMEM; | 550 | return -ENOMEM; |
552 | } | 551 | } |
553 | 552 | ||
@@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
557 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 556 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
558 | if (! res) { | 557 | if (! res) { |
559 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | 558 | dev_err(&pdev->dev, "Cannot get memory resource\n"); |
560 | kfree(mvchip->chip.label); | ||
561 | return -ENODEV; | 559 | return -ENODEV; |
562 | } | 560 | } |
563 | 561 | ||
564 | mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); | 562 | mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); |
565 | if (! mvchip->percpu_membase) { | 563 | if (! mvchip->percpu_membase) { |
566 | dev_err(&pdev->dev, "Cannot ioremap\n"); | 564 | dev_err(&pdev->dev, "Cannot ioremap\n"); |
567 | kfree(mvchip->chip.label); | ||
568 | return -ENOMEM; | 565 | return -ENOMEM; |
569 | } | 566 | } |
570 | } | 567 | } |
@@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
625 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); | 622 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); |
626 | if (mvchip->irqbase < 0) { | 623 | if (mvchip->irqbase < 0) { |
627 | dev_err(&pdev->dev, "no irqs\n"); | 624 | dev_err(&pdev->dev, "no irqs\n"); |
628 | kfree(mvchip->chip.label); | ||
629 | return -ENOMEM; | 625 | return -ENOMEM; |
630 | } | 626 | } |
631 | 627 | ||
@@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
633 | mvchip->membase, handle_level_irq); | 629 | mvchip->membase, handle_level_irq); |
634 | if (! gc) { | 630 | if (! gc) { |
635 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); | 631 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); |
636 | kfree(mvchip->chip.label); | ||
637 | return -ENOMEM; | 632 | return -ENOMEM; |
638 | } | 633 | } |
639 | 634 | ||
@@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
668 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | 663 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, |
669 | IRQ_LEVEL | IRQ_NOPROBE); | 664 | IRQ_LEVEL | IRQ_NOPROBE); |
670 | kfree(gc); | 665 | kfree(gc); |
671 | kfree(mvchip->chip.label); | ||
672 | return -ENODEV; | 666 | return -ENODEV; |
673 | } | 667 | } |
674 | 668 | ||
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 01f7fe955590..76be7eed79de 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
34 | #include <mach/map.h> | 34 | #include <mach/map.h> |
35 | #include <mach/regs-clock.h> | ||
36 | #include <mach/regs-gpio.h> | 35 | #include <mach/regs-gpio.h> |
37 | 36 | ||
38 | #include <plat/cpu.h> | 37 | #include <plat/cpu.h> |
@@ -446,7 +445,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { | |||
446 | }; | 445 | }; |
447 | #endif | 446 | #endif |
448 | 447 | ||
449 | #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) | 448 | #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250) |
450 | static struct samsung_gpio_cfg exynos_gpio_cfg = { | 449 | static struct samsung_gpio_cfg exynos_gpio_cfg = { |
451 | .set_pull = exynos_gpio_setpull, | 450 | .set_pull = exynos_gpio_setpull, |
452 | .get_pull = exynos_gpio_getpull, | 451 | .get_pull = exynos_gpio_getpull, |
@@ -2446,7 +2445,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { | |||
2446 | }; | 2445 | }; |
2447 | #endif | 2446 | #endif |
2448 | 2447 | ||
2449 | #ifdef CONFIG_ARCH_EXYNOS5 | 2448 | #ifdef CONFIG_SOC_EXYNOS5250 |
2450 | static struct samsung_gpio_chip exynos5_gpios_1[] = { | 2449 | static struct samsung_gpio_chip exynos5_gpios_1[] = { |
2451 | { | 2450 | { |
2452 | .chip = { | 2451 | .chip = { |
@@ -2614,7 +2613,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { | |||
2614 | }; | 2613 | }; |
2615 | #endif | 2614 | #endif |
2616 | 2615 | ||
2617 | #ifdef CONFIG_ARCH_EXYNOS5 | 2616 | #ifdef CONFIG_SOC_EXYNOS5250 |
2618 | static struct samsung_gpio_chip exynos5_gpios_2[] = { | 2617 | static struct samsung_gpio_chip exynos5_gpios_2[] = { |
2619 | { | 2618 | { |
2620 | .chip = { | 2619 | .chip = { |
@@ -2675,7 +2674,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = { | |||
2675 | }; | 2674 | }; |
2676 | #endif | 2675 | #endif |
2677 | 2676 | ||
2678 | #ifdef CONFIG_ARCH_EXYNOS5 | 2677 | #ifdef CONFIG_SOC_EXYNOS5250 |
2679 | static struct samsung_gpio_chip exynos5_gpios_3[] = { | 2678 | static struct samsung_gpio_chip exynos5_gpios_3[] = { |
2680 | { | 2679 | { |
2681 | .chip = { | 2680 | .chip = { |
@@ -2711,7 +2710,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = { | |||
2711 | }; | 2710 | }; |
2712 | #endif | 2711 | #endif |
2713 | 2712 | ||
2714 | #ifdef CONFIG_ARCH_EXYNOS5 | 2713 | #ifdef CONFIG_SOC_EXYNOS5250 |
2715 | static struct samsung_gpio_chip exynos5_gpios_4[] = { | 2714 | static struct samsung_gpio_chip exynos5_gpios_4[] = { |
2716 | { | 2715 | { |
2717 | .chip = { | 2716 | .chip = { |
@@ -3010,7 +3009,7 @@ static __init int samsung_gpiolib_init(void) | |||
3010 | int i, nr_chips; | 3009 | int i, nr_chips; |
3011 | int group = 0; | 3010 | int group = 0; |
3012 | 3011 | ||
3013 | #ifdef CONFIG_PINCTRL_SAMSUNG | 3012 | #if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440) |
3014 | /* | 3013 | /* |
3015 | * This gpio driver includes support for device tree support and there | 3014 | * This gpio driver includes support for device tree support and there |
3016 | * are platforms using it. In order to maintain compatibility with those | 3015 | * are platforms using it. In order to maintain compatibility with those |
@@ -3026,6 +3025,7 @@ static __init int samsung_gpiolib_init(void) | |||
3026 | static const struct of_device_id exynos_pinctrl_ids[] = { | 3025 | static const struct of_device_id exynos_pinctrl_ids[] = { |
3027 | { .compatible = "samsung,pinctrl-exynos4210", }, | 3026 | { .compatible = "samsung,pinctrl-exynos4210", }, |
3028 | { .compatible = "samsung,pinctrl-exynos4x12", }, | 3027 | { .compatible = "samsung,pinctrl-exynos4x12", }, |
3028 | { .compatible = "samsung,pinctrl-exynos5440", }, | ||
3029 | }; | 3029 | }; |
3030 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) | 3030 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) |
3031 | if (pctrl_np && of_device_is_available(pctrl_np)) | 3031 | if (pctrl_np && of_device_is_available(pctrl_np)) |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 2bf9670ba29b..2aa331499f81 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -221,11 +221,13 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | |||
221 | 221 | ||
222 | BUG_ON(!hole_node->hole_follows || node->allocated); | 222 | BUG_ON(!hole_node->hole_follows || node->allocated); |
223 | 223 | ||
224 | if (mm->color_adjust) | ||
225 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); | ||
226 | |||
227 | if (adj_start < start) | 224 | if (adj_start < start) |
228 | adj_start = start; | 225 | adj_start = start; |
226 | if (adj_end > end) | ||
227 | adj_end = end; | ||
228 | |||
229 | if (mm->color_adjust) | ||
230 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); | ||
229 | 231 | ||
230 | if (alignment) { | 232 | if (alignment) { |
231 | unsigned tmp = adj_start % alignment; | 233 | unsigned tmp = adj_start % alignment; |
@@ -506,7 +508,7 @@ void drm_mm_init_scan(struct drm_mm *mm, | |||
506 | mm->scan_size = size; | 508 | mm->scan_size = size; |
507 | mm->scanned_blocks = 0; | 509 | mm->scanned_blocks = 0; |
508 | mm->scan_hit_start = 0; | 510 | mm->scan_hit_start = 0; |
509 | mm->scan_hit_size = 0; | 511 | mm->scan_hit_end = 0; |
510 | mm->scan_check_range = 0; | 512 | mm->scan_check_range = 0; |
511 | mm->prev_scanned_node = NULL; | 513 | mm->prev_scanned_node = NULL; |
512 | } | 514 | } |
@@ -533,7 +535,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, | |||
533 | mm->scan_size = size; | 535 | mm->scan_size = size; |
534 | mm->scanned_blocks = 0; | 536 | mm->scanned_blocks = 0; |
535 | mm->scan_hit_start = 0; | 537 | mm->scan_hit_start = 0; |
536 | mm->scan_hit_size = 0; | 538 | mm->scan_hit_end = 0; |
537 | mm->scan_start = start; | 539 | mm->scan_start = start; |
538 | mm->scan_end = end; | 540 | mm->scan_end = end; |
539 | mm->scan_check_range = 1; | 541 | mm->scan_check_range = 1; |
@@ -552,8 +554,7 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
552 | struct drm_mm *mm = node->mm; | 554 | struct drm_mm *mm = node->mm; |
553 | struct drm_mm_node *prev_node; | 555 | struct drm_mm_node *prev_node; |
554 | unsigned long hole_start, hole_end; | 556 | unsigned long hole_start, hole_end; |
555 | unsigned long adj_start; | 557 | unsigned long adj_start, adj_end; |
556 | unsigned long adj_end; | ||
557 | 558 | ||
558 | mm->scanned_blocks++; | 559 | mm->scanned_blocks++; |
559 | 560 | ||
@@ -570,14 +571,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
570 | node->node_list.next = &mm->prev_scanned_node->node_list; | 571 | node->node_list.next = &mm->prev_scanned_node->node_list; |
571 | mm->prev_scanned_node = node; | 572 | mm->prev_scanned_node = node; |
572 | 573 | ||
573 | hole_start = drm_mm_hole_node_start(prev_node); | 574 | adj_start = hole_start = drm_mm_hole_node_start(prev_node); |
574 | hole_end = drm_mm_hole_node_end(prev_node); | 575 | adj_end = hole_end = drm_mm_hole_node_end(prev_node); |
575 | |||
576 | adj_start = hole_start; | ||
577 | adj_end = hole_end; | ||
578 | |||
579 | if (mm->color_adjust) | ||
580 | mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); | ||
581 | 576 | ||
582 | if (mm->scan_check_range) { | 577 | if (mm->scan_check_range) { |
583 | if (adj_start < mm->scan_start) | 578 | if (adj_start < mm->scan_start) |
@@ -586,11 +581,14 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
586 | adj_end = mm->scan_end; | 581 | adj_end = mm->scan_end; |
587 | } | 582 | } |
588 | 583 | ||
584 | if (mm->color_adjust) | ||
585 | mm->color_adjust(prev_node, mm->scan_color, | ||
586 | &adj_start, &adj_end); | ||
587 | |||
589 | if (check_free_hole(adj_start, adj_end, | 588 | if (check_free_hole(adj_start, adj_end, |
590 | mm->scan_size, mm->scan_alignment)) { | 589 | mm->scan_size, mm->scan_alignment)) { |
591 | mm->scan_hit_start = hole_start; | 590 | mm->scan_hit_start = hole_start; |
592 | mm->scan_hit_size = hole_end; | 591 | mm->scan_hit_end = hole_end; |
593 | |||
594 | return 1; | 592 | return 1; |
595 | } | 593 | } |
596 | 594 | ||
@@ -626,19 +624,10 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node) | |||
626 | node_list); | 624 | node_list); |
627 | 625 | ||
628 | prev_node->hole_follows = node->scanned_preceeds_hole; | 626 | prev_node->hole_follows = node->scanned_preceeds_hole; |
629 | INIT_LIST_HEAD(&node->node_list); | ||
630 | list_add(&node->node_list, &prev_node->node_list); | 627 | list_add(&node->node_list, &prev_node->node_list); |
631 | 628 | ||
632 | /* Only need to check for containement because start&size for the | 629 | return (drm_mm_hole_node_end(node) > mm->scan_hit_start && |
633 | * complete resulting free block (not just the desired part) is | 630 | node->start < mm->scan_hit_end); |
634 | * stored. */ | ||
635 | if (node->start >= mm->scan_hit_start && | ||
636 | node->start + node->size | ||
637 | <= mm->scan_hit_start + mm->scan_hit_size) { | ||
638 | return 1; | ||
639 | } | ||
640 | |||
641 | return 0; | ||
642 | } | 631 | } |
643 | EXPORT_SYMBOL(drm_mm_scan_remove_block); | 632 | EXPORT_SYMBOL(drm_mm_scan_remove_block); |
644 | 633 | ||
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85eaf..7944d301518a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -641,6 +641,7 @@ static void i915_ring_error_state(struct seq_file *m, | |||
641 | seq_printf(m, "%s command stream:\n", ring_str(ring)); | 641 | seq_printf(m, "%s command stream:\n", ring_str(ring)); |
642 | seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); | 642 | seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); |
643 | seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); | 643 | seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); |
644 | seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]); | ||
644 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); | 645 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); |
645 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); | 646 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); |
646 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); | 647 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); |
@@ -693,6 +694,8 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
693 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | 694 | seq_printf(m, "EIR: 0x%08x\n", error->eir); |
694 | seq_printf(m, "IER: 0x%08x\n", error->ier); | 695 | seq_printf(m, "IER: 0x%08x\n", error->ier); |
695 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 696 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
697 | seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); | ||
698 | seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr); | ||
696 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); | 699 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); |
697 | 700 | ||
698 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 701 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed3059575576..12ab3bdea54d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -188,10 +188,13 @@ struct drm_i915_error_state { | |||
188 | u32 pgtbl_er; | 188 | u32 pgtbl_er; |
189 | u32 ier; | 189 | u32 ier; |
190 | u32 ccid; | 190 | u32 ccid; |
191 | u32 derrmr; | ||
192 | u32 forcewake; | ||
191 | bool waiting[I915_NUM_RINGS]; | 193 | bool waiting[I915_NUM_RINGS]; |
192 | u32 pipestat[I915_MAX_PIPES]; | 194 | u32 pipestat[I915_MAX_PIPES]; |
193 | u32 tail[I915_NUM_RINGS]; | 195 | u32 tail[I915_NUM_RINGS]; |
194 | u32 head[I915_NUM_RINGS]; | 196 | u32 head[I915_NUM_RINGS]; |
197 | u32 ctl[I915_NUM_RINGS]; | ||
195 | u32 ipeir[I915_NUM_RINGS]; | 198 | u32 ipeir[I915_NUM_RINGS]; |
196 | u32 ipehr[I915_NUM_RINGS]; | 199 | u32 ipehr[I915_NUM_RINGS]; |
197 | u32 instdone[I915_NUM_RINGS]; | 200 | u32 instdone[I915_NUM_RINGS]; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index da3c82e301b1..8febea6daa08 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1717,7 +1717,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) | |||
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | static long | 1719 | static long |
1720 | i915_gem_purge(struct drm_i915_private *dev_priv, long target) | 1720 | __i915_gem_shrink(struct drm_i915_private *dev_priv, long target, |
1721 | bool purgeable_only) | ||
1721 | { | 1722 | { |
1722 | struct drm_i915_gem_object *obj, *next; | 1723 | struct drm_i915_gem_object *obj, *next; |
1723 | long count = 0; | 1724 | long count = 0; |
@@ -1725,7 +1726,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1725 | list_for_each_entry_safe(obj, next, | 1726 | list_for_each_entry_safe(obj, next, |
1726 | &dev_priv->mm.unbound_list, | 1727 | &dev_priv->mm.unbound_list, |
1727 | gtt_list) { | 1728 | gtt_list) { |
1728 | if (i915_gem_object_is_purgeable(obj) && | 1729 | if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && |
1729 | i915_gem_object_put_pages(obj) == 0) { | 1730 | i915_gem_object_put_pages(obj) == 0) { |
1730 | count += obj->base.size >> PAGE_SHIFT; | 1731 | count += obj->base.size >> PAGE_SHIFT; |
1731 | if (count >= target) | 1732 | if (count >= target) |
@@ -1736,7 +1737,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1736 | list_for_each_entry_safe(obj, next, | 1737 | list_for_each_entry_safe(obj, next, |
1737 | &dev_priv->mm.inactive_list, | 1738 | &dev_priv->mm.inactive_list, |
1738 | mm_list) { | 1739 | mm_list) { |
1739 | if (i915_gem_object_is_purgeable(obj) && | 1740 | if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && |
1740 | i915_gem_object_unbind(obj) == 0 && | 1741 | i915_gem_object_unbind(obj) == 0 && |
1741 | i915_gem_object_put_pages(obj) == 0) { | 1742 | i915_gem_object_put_pages(obj) == 0) { |
1742 | count += obj->base.size >> PAGE_SHIFT; | 1743 | count += obj->base.size >> PAGE_SHIFT; |
@@ -1748,6 +1749,12 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1748 | return count; | 1749 | return count; |
1749 | } | 1750 | } |
1750 | 1751 | ||
1752 | static long | ||
1753 | i915_gem_purge(struct drm_i915_private *dev_priv, long target) | ||
1754 | { | ||
1755 | return __i915_gem_shrink(dev_priv, target, true); | ||
1756 | } | ||
1757 | |||
1751 | static void | 1758 | static void |
1752 | i915_gem_shrink_all(struct drm_i915_private *dev_priv) | 1759 | i915_gem_shrink_all(struct drm_i915_private *dev_priv) |
1753 | { | 1760 | { |
@@ -3522,14 +3529,15 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
3522 | goto out; | 3529 | goto out; |
3523 | } | 3530 | } |
3524 | 3531 | ||
3525 | obj->user_pin_count++; | 3532 | if (obj->user_pin_count == 0) { |
3526 | obj->pin_filp = file; | ||
3527 | if (obj->user_pin_count == 1) { | ||
3528 | ret = i915_gem_object_pin(obj, args->alignment, true, false); | 3533 | ret = i915_gem_object_pin(obj, args->alignment, true, false); |
3529 | if (ret) | 3534 | if (ret) |
3530 | goto out; | 3535 | goto out; |
3531 | } | 3536 | } |
3532 | 3537 | ||
3538 | obj->user_pin_count++; | ||
3539 | obj->pin_filp = file; | ||
3540 | |||
3533 | /* XXX - flush the CPU caches for pinned objects | 3541 | /* XXX - flush the CPU caches for pinned objects |
3534 | * as the X server doesn't manage domains yet | 3542 | * as the X server doesn't manage domains yet |
3535 | */ | 3543 | */ |
@@ -4395,6 +4403,9 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
4395 | if (nr_to_scan) { | 4403 | if (nr_to_scan) { |
4396 | nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); | 4404 | nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); |
4397 | if (nr_to_scan > 0) | 4405 | if (nr_to_scan > 0) |
4406 | nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, | ||
4407 | false); | ||
4408 | if (nr_to_scan > 0) | ||
4398 | i915_gem_shrink_all(dev_priv); | 4409 | i915_gem_shrink_all(dev_priv); |
4399 | } | 4410 | } |
4400 | 4411 | ||
@@ -4402,7 +4413,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
4402 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) | 4413 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) |
4403 | if (obj->pages_pin_count == 0) | 4414 | if (obj->pages_pin_count == 0) |
4404 | cnt += obj->base.size >> PAGE_SHIFT; | 4415 | cnt += obj->base.size >> PAGE_SHIFT; |
4405 | list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) | 4416 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) |
4406 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) | 4417 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) |
4407 | cnt += obj->base.size >> PAGE_SHIFT; | 4418 | cnt += obj->base.size >> PAGE_SHIFT; |
4408 | 4419 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a07393..26d08bb58218 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
539 | total = 0; | 539 | total = 0; |
540 | for (i = 0; i < count; i++) { | 540 | for (i = 0; i < count; i++) { |
541 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 541 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
542 | u64 invalid_offset = (u64)-1; | ||
543 | int j; | ||
542 | 544 | ||
543 | user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; | 545 | user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; |
544 | 546 | ||
@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
549 | goto err; | 551 | goto err; |
550 | } | 552 | } |
551 | 553 | ||
554 | /* As we do not update the known relocation offsets after | ||
555 | * relocating (due to the complexities in lock handling), | ||
556 | * we need to mark them as invalid now so that we force the | ||
557 | * relocation processing next time. Just in case the target | ||
558 | * object is evicted and then rebound into its old | ||
559 | * presumed_offset before the next execbuffer - if that | ||
560 | * happened we would make the mistake of assuming that the | ||
561 | * relocations were valid. | ||
562 | */ | ||
563 | for (j = 0; j < exec[i].relocation_count; j++) { | ||
564 | if (copy_to_user(&user_relocs[j].presumed_offset, | ||
565 | &invalid_offset, | ||
566 | sizeof(invalid_offset))) { | ||
567 | ret = -EFAULT; | ||
568 | mutex_lock(&dev->struct_mutex); | ||
569 | goto err; | ||
570 | } | ||
571 | } | ||
572 | |||
552 | reloc_offset[i] = total; | 573 | reloc_offset[i] = total; |
553 | total += exec[i].relocation_count; | 574 | total += exec[i].relocation_count; |
554 | } | 575 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d9..fe843389c7b4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev, | |||
1157 | error->acthd[ring->id] = intel_ring_get_active_head(ring); | 1157 | error->acthd[ring->id] = intel_ring_get_active_head(ring); |
1158 | error->head[ring->id] = I915_READ_HEAD(ring); | 1158 | error->head[ring->id] = I915_READ_HEAD(ring); |
1159 | error->tail[ring->id] = I915_READ_TAIL(ring); | 1159 | error->tail[ring->id] = I915_READ_TAIL(ring); |
1160 | error->ctl[ring->id] = I915_READ_CTL(ring); | ||
1160 | 1161 | ||
1161 | error->cpu_ring_head[ring->id] = ring->head; | 1162 | error->cpu_ring_head[ring->id] = ring->head; |
1162 | error->cpu_ring_tail[ring->id] = ring->tail; | 1163 | error->cpu_ring_tail[ring->id] = ring->tail; |
@@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
1251 | else | 1252 | else |
1252 | error->ier = I915_READ(IER); | 1253 | error->ier = I915_READ(IER); |
1253 | 1254 | ||
1255 | if (INTEL_INFO(dev)->gen >= 6) | ||
1256 | error->derrmr = I915_READ(DERRMR); | ||
1257 | |||
1258 | if (IS_VALLEYVIEW(dev)) | ||
1259 | error->forcewake = I915_READ(FORCEWAKE_VLV); | ||
1260 | else if (INTEL_INFO(dev)->gen >= 7) | ||
1261 | error->forcewake = I915_READ(FORCEWAKE_MT); | ||
1262 | else if (INTEL_INFO(dev)->gen == 6) | ||
1263 | error->forcewake = I915_READ(FORCEWAKE); | ||
1264 | |||
1254 | for_each_pipe(pipe) | 1265 | for_each_pipe(pipe) |
1255 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); | 1266 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); |
1256 | 1267 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b51..b401788e1791 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -512,6 +512,8 @@ | |||
512 | #define GEN7_ERR_INT 0x44040 | 512 | #define GEN7_ERR_INT 0x44040 |
513 | #define ERR_INT_MMIO_UNCLAIMED (1<<13) | 513 | #define ERR_INT_MMIO_UNCLAIMED (1<<13) |
514 | 514 | ||
515 | #define DERRMR 0x44050 | ||
516 | |||
515 | /* GM45+ chicken bits -- debug workaround bits that may be required | 517 | /* GM45+ chicken bits -- debug workaround bits that may be required |
516 | * for various sorts of correct behavior. The top 16 bits of each are | 518 | * for various sorts of correct behavior. The top 16 bits of each are |
517 | * the enables for writing to the corresponding low bit. | 519 | * the enables for writing to the corresponding low bit. |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a9fb046b94a1..da1ad9c80bb5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -8598,19 +8598,30 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8598 | { | 8598 | { |
8599 | int ret; | 8599 | int ret; |
8600 | 8600 | ||
8601 | if (obj->tiling_mode == I915_TILING_Y) | 8601 | if (obj->tiling_mode == I915_TILING_Y) { |
8602 | DRM_DEBUG("hardware does not support tiling Y\n"); | ||
8602 | return -EINVAL; | 8603 | return -EINVAL; |
8604 | } | ||
8603 | 8605 | ||
8604 | if (mode_cmd->pitches[0] & 63) | 8606 | if (mode_cmd->pitches[0] & 63) { |
8607 | DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n", | ||
8608 | mode_cmd->pitches[0]); | ||
8605 | return -EINVAL; | 8609 | return -EINVAL; |
8610 | } | ||
8606 | 8611 | ||
8607 | /* FIXME <= Gen4 stride limits are bit unclear */ | 8612 | /* FIXME <= Gen4 stride limits are bit unclear */ |
8608 | if (mode_cmd->pitches[0] > 32768) | 8613 | if (mode_cmd->pitches[0] > 32768) { |
8614 | DRM_DEBUG("pitch (%d) must be at less than 32768\n", | ||
8615 | mode_cmd->pitches[0]); | ||
8609 | return -EINVAL; | 8616 | return -EINVAL; |
8617 | } | ||
8610 | 8618 | ||
8611 | if (obj->tiling_mode != I915_TILING_NONE && | 8619 | if (obj->tiling_mode != I915_TILING_NONE && |
8612 | mode_cmd->pitches[0] != obj->stride) | 8620 | mode_cmd->pitches[0] != obj->stride) { |
8621 | DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n", | ||
8622 | mode_cmd->pitches[0], obj->stride); | ||
8613 | return -EINVAL; | 8623 | return -EINVAL; |
8624 | } | ||
8614 | 8625 | ||
8615 | /* Reject formats not supported by any plane early. */ | 8626 | /* Reject formats not supported by any plane early. */ |
8616 | switch (mode_cmd->pixel_format) { | 8627 | switch (mode_cmd->pixel_format) { |
@@ -8621,8 +8632,10 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8621 | break; | 8632 | break; |
8622 | case DRM_FORMAT_XRGB1555: | 8633 | case DRM_FORMAT_XRGB1555: |
8623 | case DRM_FORMAT_ARGB1555: | 8634 | case DRM_FORMAT_ARGB1555: |
8624 | if (INTEL_INFO(dev)->gen > 3) | 8635 | if (INTEL_INFO(dev)->gen > 3) { |
8636 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8625 | return -EINVAL; | 8637 | return -EINVAL; |
8638 | } | ||
8626 | break; | 8639 | break; |
8627 | case DRM_FORMAT_XBGR8888: | 8640 | case DRM_FORMAT_XBGR8888: |
8628 | case DRM_FORMAT_ABGR8888: | 8641 | case DRM_FORMAT_ABGR8888: |
@@ -8630,18 +8643,22 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8630 | case DRM_FORMAT_ARGB2101010: | 8643 | case DRM_FORMAT_ARGB2101010: |
8631 | case DRM_FORMAT_XBGR2101010: | 8644 | case DRM_FORMAT_XBGR2101010: |
8632 | case DRM_FORMAT_ABGR2101010: | 8645 | case DRM_FORMAT_ABGR2101010: |
8633 | if (INTEL_INFO(dev)->gen < 4) | 8646 | if (INTEL_INFO(dev)->gen < 4) { |
8647 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8634 | return -EINVAL; | 8648 | return -EINVAL; |
8649 | } | ||
8635 | break; | 8650 | break; |
8636 | case DRM_FORMAT_YUYV: | 8651 | case DRM_FORMAT_YUYV: |
8637 | case DRM_FORMAT_UYVY: | 8652 | case DRM_FORMAT_UYVY: |
8638 | case DRM_FORMAT_YVYU: | 8653 | case DRM_FORMAT_YVYU: |
8639 | case DRM_FORMAT_VYUY: | 8654 | case DRM_FORMAT_VYUY: |
8640 | if (INTEL_INFO(dev)->gen < 6) | 8655 | if (INTEL_INFO(dev)->gen < 5) { |
8656 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8641 | return -EINVAL; | 8657 | return -EINVAL; |
8658 | } | ||
8642 | break; | 8659 | break; |
8643 | default: | 8660 | default: |
8644 | DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); | 8661 | DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); |
8645 | return -EINVAL; | 8662 | return -EINVAL; |
8646 | } | 8663 | } |
8647 | 8664 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a0..fb3715b4b09d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect | |||
2579 | 2579 | ||
2580 | static void | 2580 | static void |
2581 | intel_dp_init_panel_power_sequencer(struct drm_device *dev, | 2581 | intel_dp_init_panel_power_sequencer(struct drm_device *dev, |
2582 | struct intel_dp *intel_dp) | 2582 | struct intel_dp *intel_dp, |
2583 | struct edp_power_seq *out) | ||
2583 | { | 2584 | { |
2584 | struct drm_i915_private *dev_priv = dev->dev_private; | 2585 | struct drm_i915_private *dev_priv = dev->dev_private; |
2585 | struct edp_power_seq cur, vbt, spec, final; | 2586 | struct edp_power_seq cur, vbt, spec, final; |
@@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
2650 | intel_dp->panel_power_cycle_delay = get_delay(t11_t12); | 2651 | intel_dp->panel_power_cycle_delay = get_delay(t11_t12); |
2651 | #undef get_delay | 2652 | #undef get_delay |
2652 | 2653 | ||
2654 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
2655 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
2656 | intel_dp->panel_power_cycle_delay); | ||
2657 | |||
2658 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
2659 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
2660 | |||
2661 | if (out) | ||
2662 | *out = final; | ||
2663 | } | ||
2664 | |||
2665 | static void | ||
2666 | intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | ||
2667 | struct intel_dp *intel_dp, | ||
2668 | struct edp_power_seq *seq) | ||
2669 | { | ||
2670 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2671 | u32 pp_on, pp_off, pp_div; | ||
2672 | |||
2653 | /* And finally store the new values in the power sequencer. */ | 2673 | /* And finally store the new values in the power sequencer. */ |
2654 | pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | | 2674 | pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | |
2655 | (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); | 2675 | (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); |
2656 | pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | | 2676 | pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | |
2657 | (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); | 2677 | (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); |
2658 | /* Compute the divisor for the pp clock, simply match the Bspec | 2678 | /* Compute the divisor for the pp clock, simply match the Bspec |
2659 | * formula. */ | 2679 | * formula. */ |
2660 | pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) | 2680 | pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) |
2661 | << PP_REFERENCE_DIVIDER_SHIFT; | 2681 | << PP_REFERENCE_DIVIDER_SHIFT; |
2662 | pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) | 2682 | pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) |
2663 | << PANEL_POWER_CYCLE_DELAY_SHIFT); | 2683 | << PANEL_POWER_CYCLE_DELAY_SHIFT); |
2664 | 2684 | ||
2665 | /* Haswell doesn't have any port selection bits for the panel | 2685 | /* Haswell doesn't have any port selection bits for the panel |
@@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
2675 | I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); | 2695 | I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); |
2676 | I915_WRITE(PCH_PP_DIVISOR, pp_div); | 2696 | I915_WRITE(PCH_PP_DIVISOR, pp_div); |
2677 | 2697 | ||
2678 | |||
2679 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
2680 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
2681 | intel_dp->panel_power_cycle_delay); | ||
2682 | |||
2683 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
2684 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
2685 | |||
2686 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", | 2698 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", |
2687 | I915_READ(PCH_PP_ON_DELAYS), | 2699 | I915_READ(PCH_PP_ON_DELAYS), |
2688 | I915_READ(PCH_PP_OFF_DELAYS), | 2700 | I915_READ(PCH_PP_OFF_DELAYS), |
@@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2699 | struct drm_device *dev = intel_encoder->base.dev; | 2711 | struct drm_device *dev = intel_encoder->base.dev; |
2700 | struct drm_i915_private *dev_priv = dev->dev_private; | 2712 | struct drm_i915_private *dev_priv = dev->dev_private; |
2701 | struct drm_display_mode *fixed_mode = NULL; | 2713 | struct drm_display_mode *fixed_mode = NULL; |
2714 | struct edp_power_seq power_seq = { 0 }; | ||
2702 | enum port port = intel_dig_port->port; | 2715 | enum port port = intel_dig_port->port; |
2703 | const char *name = NULL; | 2716 | const char *name = NULL; |
2704 | int type; | 2717 | int type; |
@@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2771 | } | 2784 | } |
2772 | 2785 | ||
2773 | if (is_edp(intel_dp)) | 2786 | if (is_edp(intel_dp)) |
2774 | intel_dp_init_panel_power_sequencer(dev, intel_dp); | 2787 | intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); |
2775 | 2788 | ||
2776 | intel_dp_i2c_init(intel_dp, intel_connector, name); | 2789 | intel_dp_i2c_init(intel_dp, intel_connector, name); |
2777 | 2790 | ||
@@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2798 | return; | 2811 | return; |
2799 | } | 2812 | } |
2800 | 2813 | ||
2814 | /* We now know it's not a ghost, init power sequence regs. */ | ||
2815 | intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, | ||
2816 | &power_seq); | ||
2817 | |||
2801 | ironlake_edp_panel_vdd_on(intel_dp); | 2818 | ironlake_edp_panel_vdd_on(intel_dp); |
2802 | edid = drm_get_edid(connector, &intel_dp->adapter); | 2819 | edid = drm_get_edid(connector, &intel_dp->adapter); |
2803 | if (edid) { | 2820 | if (edid) { |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b9a660a53677..17aee74258ad 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -776,14 +776,6 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
776 | }, | 776 | }, |
777 | { | 777 | { |
778 | .callback = intel_no_lvds_dmi_callback, | 778 | .callback = intel_no_lvds_dmi_callback, |
779 | .ident = "ZOTAC ZBOXSD-ID12/ID13", | ||
780 | .matches = { | ||
781 | DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), | ||
782 | DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), | ||
783 | }, | ||
784 | }, | ||
785 | { | ||
786 | .callback = intel_no_lvds_dmi_callback, | ||
787 | .ident = "Gigabyte GA-D525TUD", | 779 | .ident = "Gigabyte GA-D525TUD", |
788 | .matches = { | 780 | .matches = { |
789 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), | 781 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e6f54ffab3ba..3280cffe50f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -44,6 +44,14 @@ | |||
44 | * i915.i915_enable_fbc parameter | 44 | * i915.i915_enable_fbc parameter |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static bool intel_crtc_active(struct drm_crtc *crtc) | ||
48 | { | ||
49 | /* Be paranoid as we can arrive here with only partial | ||
50 | * state retrieved from the hardware during setup. | ||
51 | */ | ||
52 | return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; | ||
53 | } | ||
54 | |||
47 | static void i8xx_disable_fbc(struct drm_device *dev) | 55 | static void i8xx_disable_fbc(struct drm_device *dev) |
48 | { | 56 | { |
49 | struct drm_i915_private *dev_priv = dev->dev_private; | 57 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device *dev) | |||
405 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 413 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
406 | */ | 414 | */ |
407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 415 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
408 | if (to_intel_crtc(tmp_crtc)->active && | 416 | if (intel_crtc_active(tmp_crtc) && |
409 | !to_intel_crtc(tmp_crtc)->primary_disabled && | 417 | !to_intel_crtc(tmp_crtc)->primary_disabled) { |
410 | tmp_crtc->fb) { | ||
411 | if (crtc) { | 418 | if (crtc) { |
412 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 419 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
413 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 420 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) | |||
992 | struct drm_crtc *crtc, *enabled = NULL; | 999 | struct drm_crtc *crtc, *enabled = NULL; |
993 | 1000 | ||
994 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 1001 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
995 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1002 | if (intel_crtc_active(crtc)) { |
996 | if (enabled) | 1003 | if (enabled) |
997 | return NULL; | 1004 | return NULL; |
998 | enabled = crtc; | 1005 | enabled = crtc; |
@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, | |||
1086 | int entries, tlb_miss; | 1093 | int entries, tlb_miss; |
1087 | 1094 | ||
1088 | crtc = intel_get_crtc_for_plane(dev, plane); | 1095 | crtc = intel_get_crtc_for_plane(dev, plane); |
1089 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { | 1096 | if (!intel_crtc_active(crtc)) { |
1090 | *cursor_wm = cursor->guard_size; | 1097 | *cursor_wm = cursor->guard_size; |
1091 | *plane_wm = display->guard_size; | 1098 | *plane_wm = display->guard_size; |
1092 | return false; | 1099 | return false; |
@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, | |||
1215 | int entries; | 1222 | int entries; |
1216 | 1223 | ||
1217 | crtc = intel_get_crtc_for_plane(dev, plane); | 1224 | crtc = intel_get_crtc_for_plane(dev, plane); |
1218 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) | 1225 | if (!intel_crtc_active(crtc)) |
1219 | return false; | 1226 | return false; |
1220 | 1227 | ||
1221 | clock = crtc->mode.clock; /* VESA DOT Clock */ | 1228 | clock = crtc->mode.clock; /* VESA DOT Clock */ |
@@ -1476,7 +1483,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
1476 | 1483 | ||
1477 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); | 1484 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); |
1478 | crtc = intel_get_crtc_for_plane(dev, 0); | 1485 | crtc = intel_get_crtc_for_plane(dev, 0); |
1479 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1486 | if (intel_crtc_active(crtc)) { |
1480 | int cpp = crtc->fb->bits_per_pixel / 8; | 1487 | int cpp = crtc->fb->bits_per_pixel / 8; |
1481 | if (IS_GEN2(dev)) | 1488 | if (IS_GEN2(dev)) |
1482 | cpp = 4; | 1489 | cpp = 4; |
@@ -1490,7 +1497,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
1490 | 1497 | ||
1491 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); | 1498 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); |
1492 | crtc = intel_get_crtc_for_plane(dev, 1); | 1499 | crtc = intel_get_crtc_for_plane(dev, 1); |
1493 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1500 | if (intel_crtc_active(crtc)) { |
1494 | int cpp = crtc->fb->bits_per_pixel / 8; | 1501 | int cpp = crtc->fb->bits_per_pixel / 8; |
1495 | if (IS_GEN2(dev)) | 1502 | if (IS_GEN2(dev)) |
1496 | cpp = 4; | 1503 | cpp = 4; |
@@ -2044,7 +2051,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, | |||
2044 | int entries, tlb_miss; | 2051 | int entries, tlb_miss; |
2045 | 2052 | ||
2046 | crtc = intel_get_crtc_for_plane(dev, plane); | 2053 | crtc = intel_get_crtc_for_plane(dev, plane); |
2047 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { | 2054 | if (!intel_crtc_active(crtc)) { |
2048 | *sprite_wm = display->guard_size; | 2055 | *sprite_wm = display->guard_size; |
2049 | return false; | 2056 | return false; |
2050 | } | 2057 | } |
@@ -4243,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | |||
4243 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | 4250 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) |
4244 | { | 4251 | { |
4245 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); | 4252 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); |
4246 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | 4253 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4254 | POSTING_READ(ECOBUS); | ||
4247 | } | 4255 | } |
4248 | 4256 | ||
4249 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | 4257 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) |
@@ -4260,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | |||
4260 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); | 4268 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); |
4261 | 4269 | ||
4262 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | 4270 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); |
4263 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | 4271 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4272 | POSTING_READ(ECOBUS); | ||
4264 | 4273 | ||
4265 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), | 4274 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), |
4266 | FORCEWAKE_ACK_TIMEOUT_MS)) | 4275 | FORCEWAKE_ACK_TIMEOUT_MS)) |
@@ -4297,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | |||
4297 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | 4306 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
4298 | { | 4307 | { |
4299 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | 4308 | I915_WRITE_NOTRACE(FORCEWAKE, 0); |
4300 | /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ | 4309 | /* something from same cacheline, but !FORCEWAKE */ |
4310 | POSTING_READ(ECOBUS); | ||
4301 | gen6_gt_check_fifodbg(dev_priv); | 4311 | gen6_gt_check_fifodbg(dev_priv); |
4302 | } | 4312 | } |
4303 | 4313 | ||
4304 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | 4314 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) |
4305 | { | 4315 | { |
4306 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 4316 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
4307 | /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ | 4317 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4318 | POSTING_READ(ECOBUS); | ||
4308 | gen6_gt_check_fifodbg(dev_priv); | 4319 | gen6_gt_check_fifodbg(dev_priv); |
4309 | } | 4320 | } |
4310 | 4321 | ||
@@ -4344,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | |||
4344 | static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) | 4355 | static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) |
4345 | { | 4356 | { |
4346 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); | 4357 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); |
4358 | /* something from same cacheline, but !FORCEWAKE_VLV */ | ||
4359 | POSTING_READ(FORCEWAKE_ACK_VLV); | ||
4347 | } | 4360 | } |
4348 | 4361 | ||
4349 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | 4362 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) |
@@ -4364,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | |||
4364 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) | 4377 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) |
4365 | { | 4378 | { |
4366 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 4379 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
4367 | /* The below doubles as a POSTING_READ */ | 4380 | /* something from same cacheline, but !FORCEWAKE_VLV */ |
4381 | POSTING_READ(FORCEWAKE_ACK_VLV); | ||
4368 | gen6_gt_check_fifodbg(dev_priv); | 4382 | gen6_gt_check_fifodbg(dev_priv); |
4369 | } | 4383 | } |
4370 | 4384 | ||
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 827dcd4edf1c..d7b060e0a231 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
120 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); | 120 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); |
121 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); | 121 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
122 | 122 | ||
123 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 123 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
124 | sprsurf_offset = | 124 | sprsurf_offset = |
125 | intel_gen4_compute_offset_xtiled(&x, &y, | 125 | intel_gen4_compute_offset_xtiled(&x, &y, |
126 | fb->bits_per_pixel / 8, | 126 | pixel_size, fb->pitches[0]); |
127 | fb->pitches[0]); | ||
128 | linear_offset -= sprsurf_offset; | 127 | linear_offset -= sprsurf_offset; |
129 | 128 | ||
130 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 129 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
@@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
286 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); | 285 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); |
287 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); | 286 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); |
288 | 287 | ||
289 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 288 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
290 | dvssurf_offset = | 289 | dvssurf_offset = |
291 | intel_gen4_compute_offset_xtiled(&x, &y, | 290 | intel_gen4_compute_offset_xtiled(&x, &y, |
292 | fb->bits_per_pixel / 8, | 291 | pixel_size, fb->pitches[0]); |
293 | fb->pitches[0]); | ||
294 | linear_offset -= dvssurf_offset; | 292 | linear_offset -= dvssurf_offset; |
295 | 293 | ||
296 | if (obj->tiling_mode != I915_TILING_NONE) | 294 | if (obj->tiling_mode != I915_TILING_NONE) |
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index c617f0480071..8bbb58f94a19 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c | |||
@@ -66,10 +66,8 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg, | |||
66 | 66 | ||
67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, | 67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, |
68 | nv_object(client), &client->root); | 68 | nv_object(client), &client->root); |
69 | if (ret) { | 69 | if (ret) |
70 | nouveau_namedb_destroy(&client->base); | ||
71 | return ret; | 70 | return ret; |
72 | } | ||
73 | 71 | ||
74 | /* prevent init/fini being called, os in in charge of this */ | 72 | /* prevent init/fini being called, os in in charge of this */ |
75 | atomic_set(&nv_object(client)->usecount, 2); | 73 | atomic_set(&nv_object(client)->usecount, 2); |
diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c index b8d2cbf8a7a7..264c2b338ac3 100644 --- a/drivers/gpu/drm/nouveau/core/core/handle.c +++ b/drivers/gpu/drm/nouveau/core/core/handle.c | |||
@@ -109,7 +109,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) | 109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) |
110 | namedb = namedb->parent; | 110 | namedb = namedb->parent; |
111 | 111 | ||
112 | handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL); | 112 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
113 | if (!handle) | 113 | if (!handle) |
114 | return -ENOMEM; | 114 | return -ENOMEM; |
115 | 115 | ||
@@ -146,6 +146,9 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
146 | } | 146 | } |
147 | 147 | ||
148 | hprintk(handle, TRACE, "created\n"); | 148 | hprintk(handle, TRACE, "created\n"); |
149 | |||
150 | *phandle = handle; | ||
151 | |||
149 | return 0; | 152 | return 0; |
150 | } | 153 | } |
151 | 154 | ||
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 0f09af135415..ca1a7d76a95b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -851,20 +851,23 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); | 852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); |
853 | 853 | ||
854 | if (nv_device(priv)->chipset < 0x90 || | 854 | if (!(ctrl & (1 << head))) { |
855 | nv_device(priv)->chipset == 0x92 || | 855 | if (nv_device(priv)->chipset < 0x90 || |
856 | nv_device(priv)->chipset == 0xa0) { | 856 | nv_device(priv)->chipset == 0x92 || |
857 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 857 | nv_device(priv)->chipset == 0xa0) { |
858 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); | 858 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
859 | i += 3; | 859 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); |
860 | } else { | 860 | i += 4; |
861 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 861 | } else { |
862 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); | 862 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
863 | i += 3; | 863 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); |
864 | i += 4; | ||
865 | } | ||
864 | } | 866 | } |
865 | 867 | ||
866 | if (!(ctrl & (1 << head))) | 868 | if (!(ctrl & (1 << head))) |
867 | return false; | 869 | return false; |
870 | i--; | ||
868 | 871 | ||
869 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); | 872 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); |
870 | if (data) { | 873 | if (data) { |
@@ -898,20 +901,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
898 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 901 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
899 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); | 902 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); |
900 | 903 | ||
901 | if (nv_device(priv)->chipset < 0x90 || | 904 | if (!(ctrl & (1 << head))) { |
902 | nv_device(priv)->chipset == 0x92 || | 905 | if (nv_device(priv)->chipset < 0x90 || |
903 | nv_device(priv)->chipset == 0xa0) { | 906 | nv_device(priv)->chipset == 0x92 || |
904 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 907 | nv_device(priv)->chipset == 0xa0) { |
905 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); | 908 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
906 | i += 3; | 909 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); |
907 | } else { | 910 | i += 4; |
908 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 911 | } else { |
909 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); | 912 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
910 | i += 3; | 913 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); |
914 | i += 4; | ||
915 | } | ||
911 | } | 916 | } |
912 | 917 | ||
913 | if (!(ctrl & (1 << head))) | 918 | if (!(ctrl & (1 << head))) |
914 | return 0x0000; | 919 | return 0x0000; |
920 | i--; | ||
915 | 921 | ||
916 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); | 922 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); |
917 | if (!data) | 923 | if (!data) |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index 0193532ceac9..63acc0346ff2 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h | |||
@@ -36,6 +36,9 @@ nouveau_client(void *obj) | |||
36 | 36 | ||
37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, | 37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, |
38 | const char *dbg, int, void **); | 38 | const char *dbg, int, void **); |
39 | #define nouveau_client_destroy(p) \ | ||
40 | nouveau_namedb_destroy(&(p)->base) | ||
41 | |||
39 | int nouveau_client_init(struct nouveau_client *); | 42 | int nouveau_client_init(struct nouveau_client *); |
40 | int nouveau_client_fini(struct nouveau_client *, bool suspend); | 43 | int nouveau_client_fini(struct nouveau_client *, bool suspend); |
41 | 44 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h index c345097592f2..b2f3d4d0aa49 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | |||
@@ -38,6 +38,8 @@ enum nvbios_pll_type { | |||
38 | PLL_UNK42 = 0x42, | 38 | PLL_UNK42 = 0x42, |
39 | PLL_VPLL0 = 0x80, | 39 | PLL_VPLL0 = 0x80, |
40 | PLL_VPLL1 = 0x81, | 40 | PLL_VPLL1 = 0x81, |
41 | PLL_VPLL2 = 0x82, | ||
42 | PLL_VPLL3 = 0x83, | ||
41 | PLL_MAX = 0xff | 43 | PLL_MAX = 0xff |
42 | }; | 44 | }; |
43 | 45 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2917d552689b..690ed438b2ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c | |||
@@ -1534,7 +1534,6 @@ init_io(struct nvbios_init *init) | |||
1534 | mdelay(10); | 1534 | mdelay(10); |
1535 | init_wr32(init, 0x614100, 0x10000018); | 1535 | init_wr32(init, 0x614100, 0x10000018); |
1536 | init_wr32(init, 0x614900, 0x10000018); | 1536 | init_wr32(init, 0x614900, 0x10000018); |
1537 | return; | ||
1538 | } | 1537 | } |
1539 | 1538 | ||
1540 | value = init_rdport(init, port) & mask; | 1539 | value = init_rdport(init, port) & mask; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index f6962c9b6c36..7c9626258a46 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | |||
@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | |||
52 | switch (info.type) { | 52 | switch (info.type) { |
53 | case PLL_VPLL0: | 53 | case PLL_VPLL0: |
54 | case PLL_VPLL1: | 54 | case PLL_VPLL1: |
55 | case PLL_VPLL2: | ||
56 | case PLL_VPLL3: | ||
55 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); | 57 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); |
56 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); | 58 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); |
57 | nv_wr32(priv, info.reg + 0x10, fN << 16); | 59 | nv_wr32(priv, info.reg + 0x10, fN << 16); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 306bdf121452..7606ed15b6fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | |||
@@ -145,14 +145,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
145 | mem->memtype = type; | 145 | mem->memtype = type; |
146 | mem->size = size; | 146 | mem->size = size; |
147 | 147 | ||
148 | mutex_lock(&mm->mutex); | 148 | mutex_lock(&pfb->base.mutex); |
149 | do { | 149 | do { |
150 | if (back) | 150 | if (back) |
151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); | 151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); |
152 | else | 152 | else |
153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); | 153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); |
154 | if (ret) { | 154 | if (ret) { |
155 | mutex_unlock(&mm->mutex); | 155 | mutex_unlock(&pfb->base.mutex); |
156 | pfb->ram.put(pfb, &mem); | 156 | pfb->ram.put(pfb, &mem); |
157 | return ret; | 157 | return ret; |
158 | } | 158 | } |
@@ -160,7 +160,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
160 | list_add_tail(&r->rl_entry, &mem->regions); | 160 | list_add_tail(&r->rl_entry, &mem->regions); |
161 | size -= r->length; | 161 | size -= r->length; |
162 | } while (size); | 162 | } while (size); |
163 | mutex_unlock(&mm->mutex); | 163 | mutex_unlock(&pfb->base.mutex); |
164 | 164 | ||
165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); | 165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
166 | mem->offset = (u64)r->offset << 12; | 166 | mem->offset = (u64)r->offset << 12; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 1188227ca6aa..6565f3dbbe04 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | |||
@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent, | |||
40 | if (ret) | 40 | if (ret) |
41 | return ret; | 41 | return ret; |
42 | 42 | ||
43 | mutex_lock(&imem->base.mutex); | ||
43 | list_add(&iobj->head, &imem->list); | 44 | list_add(&iobj->head, &imem->list); |
45 | mutex_unlock(&imem->base.mutex); | ||
44 | return 0; | 46 | return 0; |
45 | } | 47 | } |
46 | 48 | ||
47 | void | 49 | void |
48 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) | 50 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) |
49 | { | 51 | { |
50 | if (iobj->head.prev) | 52 | struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); |
51 | list_del(&iobj->head); | 53 | |
54 | mutex_lock(&subdev->mutex); | ||
55 | list_del(&iobj->head); | ||
56 | mutex_unlock(&subdev->mutex); | ||
57 | |||
52 | return nouveau_object_destroy(&iobj->base); | 58 | return nouveau_object_destroy(&iobj->base); |
53 | } | 59 | } |
54 | 60 | ||
@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
88 | if (ret) | 94 | if (ret) |
89 | return ret; | 95 | return ret; |
90 | 96 | ||
97 | mutex_lock(&imem->base.mutex); | ||
98 | |||
91 | list_for_each_entry(iobj, &imem->list, head) { | 99 | list_for_each_entry(iobj, &imem->list, head) { |
92 | if (iobj->suspend) { | 100 | if (iobj->suspend) { |
93 | for (i = 0; i < iobj->size; i += 4) | 101 | for (i = 0; i < iobj->size; i += 4) |
@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
97 | } | 105 | } |
98 | } | 106 | } |
99 | 107 | ||
108 | mutex_unlock(&imem->base.mutex); | ||
109 | |||
100 | return 0; | 110 | return 0; |
101 | } | 111 | } |
102 | 112 | ||
@@ -104,17 +114,26 @@ int | |||
104 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) | 114 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) |
105 | { | 115 | { |
106 | struct nouveau_instobj *iobj; | 116 | struct nouveau_instobj *iobj; |
107 | int i; | 117 | int i, ret = 0; |
108 | 118 | ||
109 | if (suspend) { | 119 | if (suspend) { |
120 | mutex_lock(&imem->base.mutex); | ||
121 | |||
110 | list_for_each_entry(iobj, &imem->list, head) { | 122 | list_for_each_entry(iobj, &imem->list, head) { |
111 | iobj->suspend = vmalloc(iobj->size); | 123 | iobj->suspend = vmalloc(iobj->size); |
112 | if (iobj->suspend) { | 124 | if (!iobj->suspend) { |
113 | for (i = 0; i < iobj->size; i += 4) | 125 | ret = -ENOMEM; |
114 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | 126 | break; |
115 | } else | 127 | } |
116 | return -ENOMEM; | 128 | |
129 | for (i = 0; i < iobj->size; i += 4) | ||
130 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | ||
117 | } | 131 | } |
132 | |||
133 | mutex_unlock(&imem->base.mutex); | ||
134 | |||
135 | if (ret) | ||
136 | return ret; | ||
118 | } | 137 | } |
119 | 138 | ||
120 | return nouveau_subdev_fini(&imem->base, suspend); | 139 | return nouveau_subdev_fini(&imem->base, suspend); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 082c11b75acb..77c67fc970e6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c | |||
@@ -352,7 +352,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
352 | u64 mm_length = (offset + length) - mm_offset; | 352 | u64 mm_length = (offset + length) - mm_offset; |
353 | int ret; | 353 | int ret; |
354 | 354 | ||
355 | vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); | 355 | vm = kzalloc(sizeof(*vm), GFP_KERNEL); |
356 | if (!vm) | 356 | if (!vm) |
357 | return -ENOMEM; | 357 | return -ENOMEM; |
358 | 358 | ||
@@ -376,6 +376,8 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
376 | return ret; | 376 | return ret; |
377 | } | 377 | } |
378 | 378 | ||
379 | *pvm = vm; | ||
380 | |||
379 | return 0; | 381 | return 0; |
380 | } | 382 | } |
381 | 383 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index ac340ba32017..e620ba8271b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -127,12 +127,26 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
127 | struct nouveau_encoder **pnv_encoder) | 127 | struct nouveau_encoder **pnv_encoder) |
128 | { | 128 | { |
129 | struct drm_device *dev = connector->dev; | 129 | struct drm_device *dev = connector->dev; |
130 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
130 | struct nouveau_drm *drm = nouveau_drm(dev); | 131 | struct nouveau_drm *drm = nouveau_drm(dev); |
132 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||
131 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | 133 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |
132 | int i; | 134 | struct nouveau_i2c_port *port = NULL; |
135 | int i, panel = -ENODEV; | ||
136 | |||
137 | /* eDP panels need powering on by us (if the VBIOS doesn't default it | ||
138 | * to on) before doing any AUX channel transactions. LVDS panel power | ||
139 | * is handled by the SOR itself, and not required for LVDS DDC. | ||
140 | */ | ||
141 | if (nv_connector->type == DCB_CONNECTOR_eDP) { | ||
142 | panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); | ||
143 | if (panel == 0) { | ||
144 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
145 | msleep(300); | ||
146 | } | ||
147 | } | ||
133 | 148 | ||
134 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 149 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
135 | struct nouveau_i2c_port *port = NULL; | ||
136 | struct nouveau_encoder *nv_encoder; | 150 | struct nouveau_encoder *nv_encoder; |
137 | struct drm_mode_object *obj; | 151 | struct drm_mode_object *obj; |
138 | int id; | 152 | int id; |
@@ -150,11 +164,19 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
150 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); | 164 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); |
151 | if (port && nv_probe_i2c(port, 0x50)) { | 165 | if (port && nv_probe_i2c(port, 0x50)) { |
152 | *pnv_encoder = nv_encoder; | 166 | *pnv_encoder = nv_encoder; |
153 | return port; | 167 | break; |
154 | } | 168 | } |
169 | |||
170 | port = NULL; | ||
155 | } | 171 | } |
156 | 172 | ||
157 | return NULL; | 173 | /* eDP panel not detected, restore panel power GPIO to previous |
174 | * state to avoid confusing the SOR for other output types. | ||
175 | */ | ||
176 | if (!port && panel == 0) | ||
177 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); | ||
178 | |||
179 | return port; | ||
158 | } | 180 | } |
159 | 181 | ||
160 | static struct nouveau_encoder * | 182 | static struct nouveau_encoder * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e4188f24fc75..508b00a2ce0d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -225,15 +225,6 @@ nouveau_display_init(struct drm_device *dev) | |||
225 | if (ret) | 225 | if (ret) |
226 | return ret; | 226 | return ret; |
227 | 227 | ||
228 | /* power on internal panel if it's not already. the init tables of | ||
229 | * some vbios default this to off for some reason, causing the | ||
230 | * panel to not work after resume | ||
231 | */ | ||
232 | if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { | ||
233 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
234 | msleep(300); | ||
235 | } | ||
236 | |||
237 | /* enable polling for external displays */ | 228 | /* enable polling for external displays */ |
238 | drm_kms_helper_poll_enable(dev); | 229 | drm_kms_helper_poll_enable(dev); |
239 | 230 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 180a45e3b525..8b090f1eb51d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -84,11 +84,16 @@ nouveau_cli_create(struct pci_dev *pdev, const char *name, | |||
84 | struct nouveau_cli *cli; | 84 | struct nouveau_cli *cli; |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | *pcli = NULL; | ||
87 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, | 88 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, |
88 | nouveau_debug, size, pcli); | 89 | nouveau_debug, size, pcli); |
89 | cli = *pcli; | 90 | cli = *pcli; |
90 | if (ret) | 91 | if (ret) { |
92 | if (cli) | ||
93 | nouveau_client_destroy(&cli->base); | ||
94 | *pcli = NULL; | ||
91 | return ret; | 95 | return ret; |
96 | } | ||
92 | 97 | ||
93 | mutex_init(&cli->mutex); | 98 | mutex_init(&cli->mutex); |
94 | return 0; | 99 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index bedafd1c9539..cdb83acdffe2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h | |||
@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_channel *); | |||
60 | void nv10_fence_context_del(struct nouveau_channel *); | 60 | void nv10_fence_context_del(struct nouveau_channel *); |
61 | void nv10_fence_destroy(struct nouveau_drm *); | 61 | void nv10_fence_destroy(struct nouveau_drm *); |
62 | int nv10_fence_create(struct nouveau_drm *); | 62 | int nv10_fence_create(struct nouveau_drm *); |
63 | void nv17_fence_resume(struct nouveau_drm *drm); | ||
63 | 64 | ||
64 | int nv50_fence_create(struct nouveau_drm *); | 65 | int nv50_fence_create(struct nouveau_drm *); |
65 | int nv84_fence_create(struct nouveau_drm *); | 66 | int nv84_fence_create(struct nouveau_drm *); |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 184cdf806761..39ffc07f906b 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) | |||
505 | 505 | ||
506 | static inline bool is_powersaving_dpms(int mode) | 506 | static inline bool is_powersaving_dpms(int mode) |
507 | { | 507 | { |
508 | return (mode != DRM_MODE_DPMS_ON); | 508 | return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; |
509 | } | 509 | } |
510 | 510 | ||
511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | 511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) |
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 7ae7f97a6d4d..03017f24d593 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c | |||
@@ -162,6 +162,13 @@ nv10_fence_destroy(struct nouveau_drm *drm) | |||
162 | kfree(priv); | 162 | kfree(priv); |
163 | } | 163 | } |
164 | 164 | ||
165 | void nv17_fence_resume(struct nouveau_drm *drm) | ||
166 | { | ||
167 | struct nv10_fence_priv *priv = drm->fence; | ||
168 | |||
169 | nouveau_bo_wr32(priv->bo, 0, priv->sequence); | ||
170 | } | ||
171 | |||
165 | int | 172 | int |
166 | nv10_fence_create(struct nouveau_drm *drm) | 173 | nv10_fence_create(struct nouveau_drm *drm) |
167 | { | 174 | { |
@@ -197,6 +204,7 @@ nv10_fence_create(struct nouveau_drm *drm) | |||
197 | if (ret == 0) { | 204 | if (ret == 0) { |
198 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 205 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
199 | priv->base.sync = nv17_fence_sync; | 206 | priv->base.sync = nv17_fence_sync; |
207 | priv->base.resume = nv17_fence_resume; | ||
200 | } | 208 | } |
201 | } | 209 | } |
202 | 210 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index c20f2727ea0b..d889f3ac0d41 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c | |||
@@ -122,6 +122,7 @@ nv50_fence_create(struct nouveau_drm *drm) | |||
122 | if (ret == 0) { | 122 | if (ret == 0) { |
123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
124 | priv->base.sync = nv17_fence_sync; | 124 | priv->base.sync = nv17_fence_sync; |
125 | priv->base.resume = nv17_fence_resume; | ||
125 | } | 126 | } |
126 | 127 | ||
127 | if (ret) | 128 | if (ret) |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 061fa0a28900..4d0e60adbc6d 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2401,6 +2401,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2401 | { | 2401 | { |
2402 | struct evergreen_mc_save save; | 2402 | struct evergreen_mc_save save; |
2403 | 2403 | ||
2404 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
2405 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
2406 | |||
2407 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
2408 | reset_mask &= ~RADEON_RESET_DMA; | ||
2409 | |||
2404 | if (reset_mask == 0) | 2410 | if (reset_mask == 0) |
2405 | return 0; | 2411 | return 0; |
2406 | 2412 | ||
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 896f1cbc58a5..59acabb45c9b 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -1409,6 +1409,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1409 | { | 1409 | { |
1410 | struct evergreen_mc_save save; | 1410 | struct evergreen_mc_save save; |
1411 | 1411 | ||
1412 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1413 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
1414 | |||
1415 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1416 | reset_mask &= ~RADEON_RESET_DMA; | ||
1417 | |||
1412 | if (reset_mask == 0) | 1418 | if (reset_mask == 0) |
1413 | return 0; | 1419 | return 0; |
1414 | 1420 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 537e259b3837..3cb9d6089373 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1378 | { | 1378 | { |
1379 | struct rv515_mc_save save; | 1379 | struct rv515_mc_save save; |
1380 | 1380 | ||
1381 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1382 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
1383 | |||
1384 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1385 | reset_mask &= ~RADEON_RESET_DMA; | ||
1386 | |||
1381 | if (reset_mask == 0) | 1387 | if (reset_mask == 0) |
1382 | return 0; | 1388 | return 0; |
1383 | 1389 | ||
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 03191a56eb44..69ec24ab8d63 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -2476,8 +2476,10 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) | |||
2476 | kfree(parser->relocs); | 2476 | kfree(parser->relocs); |
2477 | for (i = 0; i < parser->nchunks; i++) { | 2477 | for (i = 0; i < parser->nchunks; i++) { |
2478 | kfree(parser->chunks[i].kdata); | 2478 | kfree(parser->chunks[i].kdata); |
2479 | kfree(parser->chunks[i].kpage[0]); | 2479 | if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) { |
2480 | kfree(parser->chunks[i].kpage[1]); | 2480 | kfree(parser->chunks[i].kpage[0]); |
2481 | kfree(parser->chunks[i].kpage[1]); | ||
2482 | } | ||
2481 | } | 2483 | } |
2482 | kfree(parser->chunks); | 2484 | kfree(parser->chunks); |
2483 | kfree(parser->chunks_array); | 2485 | kfree(parser->chunks_array); |
@@ -2561,16 +2563,16 @@ int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, | |||
2561 | struct radeon_cs_chunk *relocs_chunk; | 2563 | struct radeon_cs_chunk *relocs_chunk; |
2562 | unsigned idx; | 2564 | unsigned idx; |
2563 | 2565 | ||
2566 | *cs_reloc = NULL; | ||
2564 | if (p->chunk_relocs_idx == -1) { | 2567 | if (p->chunk_relocs_idx == -1) { |
2565 | DRM_ERROR("No relocation chunk !\n"); | 2568 | DRM_ERROR("No relocation chunk !\n"); |
2566 | return -EINVAL; | 2569 | return -EINVAL; |
2567 | } | 2570 | } |
2568 | *cs_reloc = NULL; | ||
2569 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | 2571 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; |
2570 | idx = p->dma_reloc_idx; | 2572 | idx = p->dma_reloc_idx; |
2571 | if (idx >= relocs_chunk->length_dw) { | 2573 | if (idx >= p->nrelocs) { |
2572 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", | 2574 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", |
2573 | idx, relocs_chunk->length_dw); | 2575 | idx, p->nrelocs); |
2574 | return -EINVAL; | 2576 | return -EINVAL; |
2575 | } | 2577 | } |
2576 | *cs_reloc = p->relocs_ptr[idx]; | 2578 | *cs_reloc = p->relocs_ptr[idx]; |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 34e52304a525..a08f657329a0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -324,7 +324,6 @@ struct radeon_bo { | |||
324 | struct list_head list; | 324 | struct list_head list; |
325 | /* Protected by tbo.reserved */ | 325 | /* Protected by tbo.reserved */ |
326 | u32 placements[3]; | 326 | u32 placements[3]; |
327 | u32 busy_placements[3]; | ||
328 | struct ttm_placement placement; | 327 | struct ttm_placement placement; |
329 | struct ttm_buffer_object tbo; | 328 | struct ttm_buffer_object tbo; |
330 | struct ttm_bo_kmap_obj kmap; | 329 | struct ttm_bo_kmap_obj kmap; |
@@ -654,6 +653,8 @@ struct radeon_ring { | |||
654 | u32 ptr_reg_mask; | 653 | u32 ptr_reg_mask; |
655 | u32 nop; | 654 | u32 nop; |
656 | u32 idx; | 655 | u32 idx; |
656 | u64 last_semaphore_signal_addr; | ||
657 | u64 last_semaphore_wait_addr; | ||
657 | }; | 658 | }; |
658 | 659 | ||
659 | /* | 660 | /* |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 396baba0141a..469661fd1903 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -279,13 +279,13 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) | |||
279 | p->chunks[p->chunk_ib_idx].length_dw); | 279 | p->chunks[p->chunk_ib_idx].length_dw); |
280 | return -EINVAL; | 280 | return -EINVAL; |
281 | } | 281 | } |
282 | if ((p->rdev->flags & RADEON_IS_AGP)) { | 282 | if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) { |
283 | p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); | 283 | p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); |
284 | p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); | 284 | p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); |
285 | if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || | 285 | if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || |
286 | p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { | 286 | p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { |
287 | kfree(p->chunks[i].kpage[0]); | 287 | kfree(p->chunks[p->chunk_ib_idx].kpage[0]); |
288 | kfree(p->chunks[i].kpage[1]); | 288 | kfree(p->chunks[p->chunk_ib_idx].kpage[1]); |
289 | return -ENOMEM; | 289 | return -ENOMEM; |
290 | } | 290 | } |
291 | } | 291 | } |
@@ -583,7 +583,8 @@ static int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx) | |||
583 | struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; | 583 | struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; |
584 | int i; | 584 | int i; |
585 | int size = PAGE_SIZE; | 585 | int size = PAGE_SIZE; |
586 | bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true; | 586 | bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ? |
587 | false : true; | ||
587 | 588 | ||
588 | for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { | 589 | for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { |
589 | if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), | 590 | if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dff6cf77f953..d9bf96ee299a 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -69,9 +69,10 @@ | |||
69 | * 2.26.0 - r600-eg: fix htile size computation | 69 | * 2.26.0 - r600-eg: fix htile size computation |
70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA | 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA |
71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support | 71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support |
72 | * 2.29.0 - R500 FP16 color clear registers | ||
72 | */ | 73 | */ |
73 | #define KMS_DRIVER_MAJOR 2 | 74 | #define KMS_DRIVER_MAJOR 2 |
74 | #define KMS_DRIVER_MINOR 28 | 75 | #define KMS_DRIVER_MINOR 29 |
75 | #define KMS_DRIVER_PATCHLEVEL 0 | 76 | #define KMS_DRIVER_PATCHLEVEL 0 |
76 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 77 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
77 | int radeon_driver_unload_kms(struct drm_device *dev); | 78 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index f5ba2241dacc..62cd512f5c8d 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc | |||
640 | enum drm_connector_status found = connector_status_disconnected; | 640 | enum drm_connector_status found = connector_status_disconnected; |
641 | bool color = true; | 641 | bool color = true; |
642 | 642 | ||
643 | /* just don't bother on RN50 those chip are often connected to remoting | ||
644 | * console hw and often we get failure to load detect those. So to make | ||
645 | * everyone happy report the encoder as always connected. | ||
646 | */ | ||
647 | if (ASIC_IS_RN50(rdev)) { | ||
648 | return connector_status_connected; | ||
649 | } | ||
650 | |||
643 | /* save the regs we need */ | 651 | /* save the regs we need */ |
644 | vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | 652 | vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); |
645 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | 653 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 883c95d8d90f..d3aface2d12d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
84 | rbo->placement.fpfn = 0; | 84 | rbo->placement.fpfn = 0; |
85 | rbo->placement.lpfn = 0; | 85 | rbo->placement.lpfn = 0; |
86 | rbo->placement.placement = rbo->placements; | 86 | rbo->placement.placement = rbo->placements; |
87 | rbo->placement.busy_placement = rbo->placements; | ||
87 | if (domain & RADEON_GEM_DOMAIN_VRAM) | 88 | if (domain & RADEON_GEM_DOMAIN_VRAM) |
88 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | | 89 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | |
89 | TTM_PL_FLAG_VRAM; | 90 | TTM_PL_FLAG_VRAM; |
@@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
104 | if (!c) | 105 | if (!c) |
105 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; | 106 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; |
106 | rbo->placement.num_placement = c; | 107 | rbo->placement.num_placement = c; |
107 | |||
108 | c = 0; | ||
109 | rbo->placement.busy_placement = rbo->busy_placements; | ||
110 | if (rbo->rdev->flags & RADEON_IS_AGP) { | ||
111 | rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; | ||
112 | } else { | ||
113 | rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; | ||
114 | } | ||
115 | rbo->placement.num_busy_placement = c; | 108 | rbo->placement.num_busy_placement = c; |
116 | } | 109 | } |
117 | 110 | ||
@@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head) | |||
357 | { | 350 | { |
358 | struct radeon_bo_list *lobj; | 351 | struct radeon_bo_list *lobj; |
359 | struct radeon_bo *bo; | 352 | struct radeon_bo *bo; |
353 | u32 domain; | ||
360 | int r; | 354 | int r; |
361 | 355 | ||
362 | r = ttm_eu_reserve_buffers(head); | 356 | r = ttm_eu_reserve_buffers(head); |
@@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head) | |||
366 | list_for_each_entry(lobj, head, tv.head) { | 360 | list_for_each_entry(lobj, head, tv.head) { |
367 | bo = lobj->bo; | 361 | bo = lobj->bo; |
368 | if (!bo->pin_count) { | 362 | if (!bo->pin_count) { |
363 | domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; | ||
364 | |||
365 | retry: | ||
366 | radeon_ttm_placement_from_domain(bo, domain); | ||
369 | r = ttm_bo_validate(&bo->tbo, &bo->placement, | 367 | r = ttm_bo_validate(&bo->tbo, &bo->placement, |
370 | true, false); | 368 | true, false); |
371 | if (unlikely(r)) { | 369 | if (unlikely(r)) { |
370 | if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { | ||
371 | domain |= RADEON_GEM_DOMAIN_GTT; | ||
372 | goto retry; | ||
373 | } | ||
372 | return r; | 374 | return r; |
373 | } | 375 | } |
374 | } | 376 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 141f2b6a9cf2..2430d80b1871 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -784,6 +784,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
784 | } | 784 | } |
785 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); | 785 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); |
786 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); | 786 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); |
787 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); | ||
788 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); | ||
787 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); | 789 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); |
788 | seq_printf(m, "%u dwords in ring\n", count); | 790 | seq_printf(m, "%u dwords in ring\n", count); |
789 | /* print 8 dw before current rptr as often it's the last executed | 791 | /* print 8 dw before current rptr as often it's the last executed |
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 97f3ece81cd2..8dcc20f53d73 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c | |||
@@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, | |||
95 | /* we assume caller has already allocated space on waiters ring */ | 95 | /* we assume caller has already allocated space on waiters ring */ |
96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); | 96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
97 | 97 | ||
98 | /* for debugging lockup only, used by sysfs debug files */ | ||
99 | rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; | ||
100 | rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; | ||
101 | |||
98 | return 0; | 102 | return 0; |
99 | } | 103 | } |
100 | 104 | ||
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 911a8fbd32bb..78d5e99d759d 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 | |||
@@ -324,6 +324,8 @@ rv515 0x6d40 | |||
324 | 0x46AC US_OUT_FMT_2 | 324 | 0x46AC US_OUT_FMT_2 |
325 | 0x46B0 US_OUT_FMT_3 | 325 | 0x46B0 US_OUT_FMT_3 |
326 | 0x46B4 US_W_FMT | 326 | 0x46B4 US_W_FMT |
327 | 0x46C0 RB3D_COLOR_CLEAR_VALUE_AR | ||
328 | 0x46C4 RB3D_COLOR_CLEAR_VALUE_GB | ||
327 | 0x4BC0 FG_FOG_BLEND | 329 | 0x4BC0 FG_FOG_BLEND |
328 | 0x4BC4 FG_FOG_FACTOR | 330 | 0x4BC4 FG_FOG_FACTOR |
329 | 0x4BC8 FG_FOG_COLOR_R | 331 | 0x4BC8 FG_FOG_COLOR_R |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3240a3d64f30..ae8b48205a6c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2215 | { | 2215 | { |
2216 | struct evergreen_mc_save save; | 2216 | struct evergreen_mc_save save; |
2217 | 2217 | ||
2218 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
2219 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
2220 | |||
2221 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
2222 | reset_mask &= ~RADEON_RESET_DMA; | ||
2223 | |||
2218 | if (reset_mask == 0) | 2224 | if (reset_mask == 0) |
2219 | return 0; | 2225 | return 0; |
2220 | 2226 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33d20be87db5..52b20b12c83a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
434 | bo->mem = tmp_mem; | 434 | bo->mem = tmp_mem; |
435 | bdev->driver->move_notify(bo, mem); | 435 | bdev->driver->move_notify(bo, mem); |
436 | bo->mem = *mem; | 436 | bo->mem = *mem; |
437 | *mem = tmp_mem; | ||
437 | } | 438 | } |
438 | 439 | ||
439 | goto out_err; | 440 | goto out_err; |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d73d6e3e17b2..44420fca7dfa 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
344 | 344 | ||
345 | if (ttm->state == tt_unpopulated) { | 345 | if (ttm->state == tt_unpopulated) { |
346 | ret = ttm->bdev->driver->ttm_tt_populate(ttm); | 346 | ret = ttm->bdev->driver->ttm_tt_populate(ttm); |
347 | if (ret) | 347 | if (ret) { |
348 | /* if we fail here don't nuke the mm node | ||
349 | * as the bo still owns it */ | ||
350 | old_copy.mm_node = NULL; | ||
348 | goto out1; | 351 | goto out1; |
352 | } | ||
349 | } | 353 | } |
350 | 354 | ||
351 | add = 0; | 355 | add = 0; |
@@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
371 | prot); | 375 | prot); |
372 | } else | 376 | } else |
373 | ret = ttm_copy_io_page(new_iomap, old_iomap, page); | 377 | ret = ttm_copy_io_page(new_iomap, old_iomap, page); |
374 | if (ret) | 378 | if (ret) { |
379 | /* failing here, means keep old copy as-is */ | ||
380 | old_copy.mm_node = NULL; | ||
375 | goto out1; | 381 | goto out1; |
382 | } | ||
376 | } | 383 | } |
377 | mb(); | 384 | mb(); |
378 | out2: | 385 | out2: |
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 512f44add89f..fe5cdbcf2636 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c | |||
@@ -22,13 +22,17 @@ | |||
22 | static u8 *udl_get_edid(struct udl_device *udl) | 22 | static u8 *udl_get_edid(struct udl_device *udl) |
23 | { | 23 | { |
24 | u8 *block; | 24 | u8 *block; |
25 | char rbuf[3]; | 25 | char *rbuf; |
26 | int ret, i; | 26 | int ret, i; |
27 | 27 | ||
28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); | 28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); |
29 | if (block == NULL) | 29 | if (block == NULL) |
30 | return NULL; | 30 | return NULL; |
31 | 31 | ||
32 | rbuf = kmalloc(2, GFP_KERNEL); | ||
33 | if (rbuf == NULL) | ||
34 | goto error; | ||
35 | |||
32 | for (i = 0; i < EDID_LENGTH; i++) { | 36 | for (i = 0; i < EDID_LENGTH; i++) { |
33 | ret = usb_control_msg(udl->ddev->usbdev, | 37 | ret = usb_control_msg(udl->ddev->usbdev, |
34 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), | 38 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), |
@@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl) | |||
36 | HZ); | 40 | HZ); |
37 | if (ret < 1) { | 41 | if (ret < 1) { |
38 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); | 42 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); |
39 | i--; | ||
40 | goto error; | 43 | goto error; |
41 | } | 44 | } |
42 | block[i] = rbuf[1]; | 45 | block[i] = rbuf[1]; |
43 | } | 46 | } |
44 | 47 | ||
48 | kfree(rbuf); | ||
45 | return block; | 49 | return block; |
46 | 50 | ||
47 | error: | 51 | error: |
48 | kfree(block); | 52 | kfree(block); |
53 | kfree(rbuf); | ||
49 | return NULL; | 54 | return NULL; |
50 | } | 55 | } |
51 | 56 | ||
@@ -57,6 +62,14 @@ static int udl_get_modes(struct drm_connector *connector) | |||
57 | 62 | ||
58 | edid = (struct edid *)udl_get_edid(udl); | 63 | edid = (struct edid *)udl_get_edid(udl); |
59 | 64 | ||
65 | /* | ||
66 | * We only read the main block, but if the monitor reports extension | ||
67 | * blocks then the drm edid code expects them to be present, so patch | ||
68 | * the extension count to 0. | ||
69 | */ | ||
70 | edid->checksum += edid->extensions; | ||
71 | edid->extensions = 0; | ||
72 | |||
60 | drm_mode_connector_update_edid_property(connector, edid); | 73 | drm_mode_connector_update_edid_property(connector, edid); |
61 | ret = drm_add_edid_modes(connector, edid); | 74 | ret = drm_add_edid_modes(connector, edid); |
62 | kfree(edid); | 75 | kfree(edid); |
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index f6c0011a0337..dd289fd179ca 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c | |||
@@ -403,7 +403,7 @@ struct dm_info_header { | |||
403 | */ | 403 | */ |
404 | 404 | ||
405 | struct dm_info_msg { | 405 | struct dm_info_msg { |
406 | struct dm_info_header header; | 406 | struct dm_header hdr; |
407 | __u32 reserved; | 407 | __u32 reserved; |
408 | __u32 info_size; | 408 | __u32 info_size; |
409 | __u8 info[]; | 409 | __u8 info[]; |
@@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) | |||
503 | 503 | ||
504 | static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) | 504 | static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) |
505 | { | 505 | { |
506 | switch (msg->header.type) { | 506 | struct dm_info_header *info_hdr; |
507 | |||
508 | info_hdr = (struct dm_info_header *)msg->info; | ||
509 | |||
510 | switch (info_hdr->type) { | ||
507 | case INFO_TYPE_MAX_PAGE_CNT: | 511 | case INFO_TYPE_MAX_PAGE_CNT: |
508 | pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); | 512 | pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); |
509 | pr_info("Data Size is %d\n", msg->header.data_size); | 513 | pr_info("Data Size is %d\n", info_hdr->data_size); |
510 | break; | 514 | break; |
511 | default: | 515 | default: |
512 | pr_info("Received Unknown type: %d\n", msg->header.type); | 516 | pr_info("Received Unknown type: %d\n", info_hdr->type); |
513 | } | 517 | } |
514 | } | 518 | } |
515 | 519 | ||
@@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev, | |||
879 | balloon_onchannelcallback, dev); | 883 | balloon_onchannelcallback, dev); |
880 | 884 | ||
881 | if (ret) | 885 | if (ret) |
882 | return ret; | 886 | goto probe_error0; |
883 | 887 | ||
884 | dm_device.dev = dev; | 888 | dm_device.dev = dev; |
885 | dm_device.state = DM_INITIALIZING; | 889 | dm_device.state = DM_INITIALIZING; |
@@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev, | |||
891 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); | 895 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); |
892 | if (IS_ERR(dm_device.thread)) { | 896 | if (IS_ERR(dm_device.thread)) { |
893 | ret = PTR_ERR(dm_device.thread); | 897 | ret = PTR_ERR(dm_device.thread); |
894 | goto probe_error0; | 898 | goto probe_error1; |
895 | } | 899 | } |
896 | 900 | ||
897 | hv_set_drvdata(dev, &dm_device); | 901 | hv_set_drvdata(dev, &dm_device); |
@@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev, | |||
914 | VM_PKT_DATA_INBAND, | 918 | VM_PKT_DATA_INBAND, |
915 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 919 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
916 | if (ret) | 920 | if (ret) |
917 | goto probe_error1; | 921 | goto probe_error2; |
918 | 922 | ||
919 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); | 923 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); |
920 | if (t == 0) { | 924 | if (t == 0) { |
921 | ret = -ETIMEDOUT; | 925 | ret = -ETIMEDOUT; |
922 | goto probe_error1; | 926 | goto probe_error2; |
923 | } | 927 | } |
924 | 928 | ||
925 | /* | 929 | /* |
@@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev, | |||
928 | */ | 932 | */ |
929 | if (dm_device.state == DM_INIT_ERROR) { | 933 | if (dm_device.state == DM_INIT_ERROR) { |
930 | ret = -ETIMEDOUT; | 934 | ret = -ETIMEDOUT; |
931 | goto probe_error1; | 935 | goto probe_error2; |
932 | } | 936 | } |
933 | /* | 937 | /* |
934 | * Now submit our capabilities to the host. | 938 | * Now submit our capabilities to the host. |
@@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev, | |||
961 | VM_PKT_DATA_INBAND, | 965 | VM_PKT_DATA_INBAND, |
962 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 966 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
963 | if (ret) | 967 | if (ret) |
964 | goto probe_error1; | 968 | goto probe_error2; |
965 | 969 | ||
966 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); | 970 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); |
967 | if (t == 0) { | 971 | if (t == 0) { |
968 | ret = -ETIMEDOUT; | 972 | ret = -ETIMEDOUT; |
969 | goto probe_error1; | 973 | goto probe_error2; |
970 | } | 974 | } |
971 | 975 | ||
972 | /* | 976 | /* |
@@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev, | |||
975 | */ | 979 | */ |
976 | if (dm_device.state == DM_INIT_ERROR) { | 980 | if (dm_device.state == DM_INIT_ERROR) { |
977 | ret = -ETIMEDOUT; | 981 | ret = -ETIMEDOUT; |
978 | goto probe_error1; | 982 | goto probe_error2; |
979 | } | 983 | } |
980 | 984 | ||
981 | dm_device.state = DM_INITIALIZED; | 985 | dm_device.state = DM_INITIALIZED; |
982 | 986 | ||
983 | return 0; | 987 | return 0; |
984 | 988 | ||
985 | probe_error1: | 989 | probe_error2: |
986 | kthread_stop(dm_device.thread); | 990 | kthread_stop(dm_device.thread); |
987 | 991 | ||
988 | probe_error0: | 992 | probe_error1: |
989 | vmbus_close(dev->channel); | 993 | vmbus_close(dev->channel); |
994 | probe_error0: | ||
995 | kfree(send_buffer); | ||
990 | return ret; | 996 | return ret; |
991 | } | 997 | } |
992 | 998 | ||
@@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev) | |||
999 | 1005 | ||
1000 | vmbus_close(dev->channel); | 1006 | vmbus_close(dev->channel); |
1001 | kthread_stop(dm->thread); | 1007 | kthread_stop(dm->thread); |
1008 | kfree(send_buffer); | ||
1002 | 1009 | ||
1003 | return 0; | 1010 | return 0; |
1004 | } | 1011 | } |
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c index 86d7f6d858b1..d867e6bb2be1 100644 --- a/drivers/hwmon/vexpress.c +++ b/drivers/hwmon/vexpress.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/hwmon.h> | 19 | #include <linux/hwmon.h> |
20 | #include <linux/hwmon-sysfs.h> | 20 | #include <linux/hwmon-sysfs.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
24 | #include <linux/vexpress.h> | 25 | #include <linux/vexpress.h> |
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index cbba7db9ad59..f5258c205de5 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/module.h> | ||
37 | #include "i2c-designware-core.h" | 38 | #include "i2c-designware-core.h" |
38 | 39 | ||
39 | /* | 40 | /* |
@@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) | |||
725 | return dw_readl(dev, DW_IC_COMP_PARAM_1); | 726 | return dw_readl(dev, DW_IC_COMP_PARAM_1); |
726 | } | 727 | } |
727 | EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); | 728 | EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); |
729 | |||
730 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core"); | ||
731 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1b1a936eccc9..d6abaf2cf2e3 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -127,7 +127,7 @@ struct mxs_i2c_dev { | |||
127 | struct device *dev; | 127 | struct device *dev; |
128 | void __iomem *regs; | 128 | void __iomem *regs; |
129 | struct completion cmd_complete; | 129 | struct completion cmd_complete; |
130 | u32 cmd_err; | 130 | int cmd_err; |
131 | struct i2c_adapter adapter; | 131 | struct i2c_adapter adapter; |
132 | const struct mxs_i2c_speed_config *speed; | 132 | const struct mxs_i2c_speed_config *speed; |
133 | 133 | ||
@@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
316 | if (msg->len == 0) | 316 | if (msg->len == 0) |
317 | return -EINVAL; | 317 | return -EINVAL; |
318 | 318 | ||
319 | init_completion(&i2c->cmd_complete); | 319 | INIT_COMPLETION(i2c->cmd_complete); |
320 | i2c->cmd_err = 0; | 320 | i2c->cmd_err = 0; |
321 | 321 | ||
322 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); | 322 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); |
@@ -473,6 +473,8 @@ static int mxs_i2c_probe(struct platform_device *pdev) | |||
473 | i2c->dev = dev; | 473 | i2c->dev = dev; |
474 | i2c->speed = &mxs_i2c_95kHz_config; | 474 | i2c->speed = &mxs_i2c_95kHz_config; |
475 | 475 | ||
476 | init_completion(&i2c->cmd_complete); | ||
477 | |||
476 | if (dev->of_node) { | 478 | if (dev->of_node) { |
477 | err = mxs_i2c_get_ofdata(i2c); | 479 | err = mxs_i2c_get_ofdata(i2c); |
478 | if (err) | 480 | if (err) |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 20d41bfa7c19..4cc2f0528c88 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev) | |||
803 | if (stat & OMAP_I2C_STAT_AL) { | 803 | if (stat & OMAP_I2C_STAT_AL) { |
804 | dev_err(dev->dev, "Arbitration lost\n"); | 804 | dev_err(dev->dev, "Arbitration lost\n"); |
805 | dev->cmd_err |= OMAP_I2C_STAT_AL; | 805 | dev->cmd_err |= OMAP_I2C_STAT_AL; |
806 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); | 806 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); |
807 | } | 807 | } |
808 | 808 | ||
809 | return -EIO; | 809 | return -EIO; |
@@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) | |||
963 | i2c_omap_errata_i207(dev, stat); | 963 | i2c_omap_errata_i207(dev, stat); |
964 | 964 | ||
965 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); | 965 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); |
966 | break; | 966 | continue; |
967 | } | 967 | } |
968 | 968 | ||
969 | if (stat & OMAP_I2C_STAT_RRDY) { | 969 | if (stat & OMAP_I2C_STAT_RRDY) { |
@@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) | |||
989 | break; | 989 | break; |
990 | 990 | ||
991 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); | 991 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); |
992 | break; | 992 | continue; |
993 | } | 993 | } |
994 | 994 | ||
995 | if (stat & OMAP_I2C_STAT_XRDY) { | 995 | if (stat & OMAP_I2C_STAT_XRDY) { |
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 3f1818b87974..e03381aee34f 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/of_i2c.h> | ||
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
@@ -328,6 +329,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) | |||
328 | adap->algo = &i2c_sirfsoc_algo; | 329 | adap->algo = &i2c_sirfsoc_algo; |
329 | adap->algo_data = siic; | 330 | adap->algo_data = siic; |
330 | 331 | ||
332 | adap->dev.of_node = pdev->dev.of_node; | ||
331 | adap->dev.parent = &pdev->dev; | 333 | adap->dev.parent = &pdev->dev; |
332 | adap->nr = pdev->id; | 334 | adap->nr = pdev->id; |
333 | 335 | ||
@@ -371,6 +373,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) | |||
371 | 373 | ||
372 | clk_disable(clk); | 374 | clk_disable(clk); |
373 | 375 | ||
376 | of_i2c_register_devices(adap); | ||
377 | |||
374 | dev_info(&pdev->dev, " I2C adapter ready to operate\n"); | 378 | dev_info(&pdev->dev, " I2C adapter ready to operate\n"); |
375 | 379 | ||
376 | return 0; | 380 | return 0; |
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 1e44d04d1b22..a43c0ce5e3d8 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c | |||
@@ -167,7 +167,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | mux->busses = devm_kzalloc(&pdev->dev, | 169 | mux->busses = devm_kzalloc(&pdev->dev, |
170 | sizeof(mux->busses) * mux->pdata->bus_count, | 170 | sizeof(*mux->busses) * mux->pdata->bus_count, |
171 | GFP_KERNEL); | 171 | GFP_KERNEL); |
172 | if (!mux->busses) { | 172 | if (!mux->busses) { |
173 | dev_err(&pdev->dev, "Cannot allocate busses\n"); | 173 | dev_err(&pdev->dev, "Cannot allocate busses\n"); |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4ba384f1ab54..2df9414a72f7 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -448,8 +448,6 @@ static int intel_idle_probe(void) | |||
448 | else | 448 | else |
449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); | 449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); |
450 | 450 | ||
451 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
452 | |||
453 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION | 451 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION |
454 | " model 0x%X\n", boot_cpu_data.x86_model); | 452 | " model 0x%X\n", boot_cpu_data.x86_model); |
455 | 453 | ||
@@ -612,6 +610,7 @@ static int __init intel_idle_init(void) | |||
612 | return retval; | 610 | return retval; |
613 | } | 611 | } |
614 | } | 612 | } |
613 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
615 | 614 | ||
616 | return 0; | 615 | return 0; |
617 | } | 616 | } |
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index fe4bcd7c5b12..05e996fafc9d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig | |||
@@ -8,6 +8,7 @@ config HID_SENSOR_ACCEL_3D | |||
8 | select IIO_BUFFER | 8 | select IIO_BUFFER |
9 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
10 | select HID_SENSOR_IIO_COMMON | 10 | select HID_SENSOR_IIO_COMMON |
11 | select HID_SENSOR_IIO_TRIGGER | ||
11 | tristate "HID Accelerometers 3D" | 12 | tristate "HID Accelerometers 3D" |
12 | help | 13 | help |
13 | Say yes here to build support for the HID SENSOR | 14 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 4a5f639bc684..bbad9b94cd75 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c | |||
@@ -411,7 +411,11 @@ static int ad7266_probe(struct spi_device *spi) | |||
411 | if (ret) | 411 | if (ret) |
412 | goto error_put_reg; | 412 | goto error_put_reg; |
413 | 413 | ||
414 | st->vref_uv = regulator_get_voltage(st->reg); | 414 | ret = regulator_get_voltage(st->reg); |
415 | if (ret < 0) | ||
416 | goto error_disable_reg; | ||
417 | |||
418 | st->vref_uv = ret; | ||
415 | } else { | 419 | } else { |
416 | /* Use internal reference */ | 420 | /* Use internal reference */ |
417 | st->vref_uv = 2500000; | 421 | st->vref_uv = 2500000; |
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 04b013561f0f..a526c0e3aaa8 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c | |||
@@ -80,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) | |||
80 | *timestamp = pf->timestamp; | 80 | *timestamp = pf->timestamp; |
81 | } | 81 | } |
82 | 82 | ||
83 | iio_push_to_buffers(indio_dev, (u8 *)st->buffer); | 83 | iio_push_to_buffers(idev, (u8 *)st->buffer); |
84 | 84 | ||
85 | iio_trigger_notify_done(idev->trig); | 85 | iio_trigger_notify_done(idev->trig); |
86 | 86 | ||
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index b5669be6f396..03b25b3dc71e 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c | |||
@@ -1605,19 +1605,20 @@ static int max1363_probe(struct i2c_client *client, | |||
1605 | 1605 | ||
1606 | return 0; | 1606 | return 0; |
1607 | error_free_irq: | 1607 | error_free_irq: |
1608 | free_irq(st->client->irq, indio_dev); | 1608 | if (client->irq) |
1609 | free_irq(st->client->irq, indio_dev); | ||
1609 | error_uninit_buffer: | 1610 | error_uninit_buffer: |
1610 | iio_buffer_unregister(indio_dev); | 1611 | iio_buffer_unregister(indio_dev); |
1611 | error_cleanup_buffer: | 1612 | error_cleanup_buffer: |
1612 | max1363_buffer_cleanup(indio_dev); | 1613 | max1363_buffer_cleanup(indio_dev); |
1613 | error_free_available_scan_masks: | 1614 | error_free_available_scan_masks: |
1614 | kfree(indio_dev->available_scan_masks); | 1615 | kfree(indio_dev->available_scan_masks); |
1615 | error_unregister_map: | ||
1616 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | ||
1617 | error_disable_reg: | 1616 | error_disable_reg: |
1618 | regulator_disable(st->reg); | 1617 | regulator_disable(st->reg); |
1619 | error_put_reg: | 1618 | error_put_reg: |
1620 | regulator_put(st->reg); | 1619 | regulator_put(st->reg); |
1620 | error_unregister_map: | ||
1621 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | ||
1621 | error_free_device: | 1622 | error_free_device: |
1622 | iio_device_free(indio_dev); | 1623 | iio_device_free(indio_dev); |
1623 | error_out: | 1624 | error_out: |
@@ -1635,10 +1636,8 @@ static int max1363_remove(struct i2c_client *client) | |||
1635 | iio_buffer_unregister(indio_dev); | 1636 | iio_buffer_unregister(indio_dev); |
1636 | max1363_buffer_cleanup(indio_dev); | 1637 | max1363_buffer_cleanup(indio_dev); |
1637 | kfree(indio_dev->available_scan_masks); | 1638 | kfree(indio_dev->available_scan_masks); |
1638 | if (!IS_ERR(st->reg)) { | 1639 | regulator_disable(st->reg); |
1639 | regulator_disable(st->reg); | 1640 | regulator_put(st->reg); |
1640 | regulator_put(st->reg); | ||
1641 | } | ||
1642 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | 1641 | iio_map_array_unregister(indio_dev, client->dev.platform_data); |
1643 | iio_device_free(indio_dev); | 1642 | iio_device_free(indio_dev); |
1644 | 1643 | ||
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index ae10778da7aa..1178121b55b0 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Hid Sensor IIO Common" | |||
6 | config HID_SENSOR_IIO_COMMON | 6 | config HID_SENSOR_IIO_COMMON |
7 | tristate "Common modules for all HID Sensor IIO drivers" | 7 | tristate "Common modules for all HID Sensor IIO drivers" |
8 | depends on HID_SENSOR_HUB | 8 | depends on HID_SENSOR_HUB |
9 | select IIO_TRIGGER if IIO_BUFFER | 9 | select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER |
10 | help | 10 | help |
11 | Say yes here to build support for HID sensor to use | 11 | Say yes here to build support for HID sensor to use |
12 | HID sensor common processing for attributes and IIO triggers. | 12 | HID sensor common processing for attributes and IIO triggers. |
@@ -14,6 +14,17 @@ config HID_SENSOR_IIO_COMMON | |||
14 | HID sensor drivers, this module contains processing for those | 14 | HID sensor drivers, this module contains processing for those |
15 | attributes. | 15 | attributes. |
16 | 16 | ||
17 | config HID_SENSOR_IIO_TRIGGER | ||
18 | tristate "Common module (trigger) for all HID Sensor IIO drivers" | ||
19 | depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON | ||
20 | select IIO_TRIGGER | ||
21 | help | ||
22 | Say yes here to build trigger support for HID sensors. | ||
23 | Triggers will be send if all requested attributes were read. | ||
24 | |||
25 | If this driver is compiled as a module, it will be named | ||
26 | hid-sensor-trigger. | ||
27 | |||
17 | config HID_SENSOR_ENUM_BASE_QUIRKS | 28 | config HID_SENSOR_ENUM_BASE_QUIRKS |
18 | bool "ENUM base quirks for HID Sensor IIO drivers" | 29 | bool "ENUM base quirks for HID Sensor IIO drivers" |
19 | depends on HID_SENSOR_IIO_COMMON | 30 | depends on HID_SENSOR_IIO_COMMON |
diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile index 1f463e00c242..22e7c5a82325 100644 --- a/drivers/iio/common/hid-sensors/Makefile +++ b/drivers/iio/common/hid-sensors/Makefile | |||
@@ -3,4 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o | 5 | obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o |
6 | hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o | 6 | obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o |
7 | hid-sensor-iio-common-y := hid-sensor-attributes.o | ||
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 6c7898c765d9..483fc379a2da 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c | |||
@@ -406,7 +406,11 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, | |||
406 | goto error_free_reg; | 406 | goto error_free_reg; |
407 | } | 407 | } |
408 | 408 | ||
409 | st->vref = regulator_get_voltage(st->vref_reg); | 409 | ret = regulator_get_voltage(st->vref_reg); |
410 | if (ret < 0) | ||
411 | goto error_disable_reg; | ||
412 | |||
413 | st->vref = ret; | ||
410 | } else { | 414 | } else { |
411 | st->vref = st->chip_info->int_vref; | 415 | st->vref = st->chip_info->int_vref; |
412 | ctrl |= AD5380_CTRL_INT_VREF_EN; | 416 | ctrl |= AD5380_CTRL_INT_VREF_EN; |
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 29f653dab2f7..f5583aedfb59 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c | |||
@@ -226,7 +226,11 @@ static int ad5446_probe(struct device *dev, const char *name, | |||
226 | if (ret) | 226 | if (ret) |
227 | goto error_put_reg; | 227 | goto error_put_reg; |
228 | 228 | ||
229 | voltage_uv = regulator_get_voltage(reg); | 229 | ret = regulator_get_voltage(reg); |
230 | if (ret < 0) | ||
231 | goto error_disable_reg; | ||
232 | |||
233 | voltage_uv = ret; | ||
230 | } | 234 | } |
231 | 235 | ||
232 | indio_dev = iio_device_alloc(sizeof(*st)); | 236 | indio_dev = iio_device_alloc(sizeof(*st)); |
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index b2a31a0468ed..0661829f2773 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c | |||
@@ -296,7 +296,11 @@ static int ad5504_probe(struct spi_device *spi) | |||
296 | if (ret) | 296 | if (ret) |
297 | goto error_put_reg; | 297 | goto error_put_reg; |
298 | 298 | ||
299 | voltage_uv = regulator_get_voltage(reg); | 299 | ret = regulator_get_voltage(reg); |
300 | if (ret < 0) | ||
301 | goto error_disable_reg; | ||
302 | |||
303 | voltage_uv = ret; | ||
300 | } | 304 | } |
301 | 305 | ||
302 | spi_set_drvdata(spi, indio_dev); | 306 | spi_set_drvdata(spi, indio_dev); |
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index e9947969f9fe..f6e116627b71 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c | |||
@@ -238,7 +238,11 @@ static int ad5624r_probe(struct spi_device *spi) | |||
238 | if (ret) | 238 | if (ret) |
239 | goto error_put_reg; | 239 | goto error_put_reg; |
240 | 240 | ||
241 | voltage_uv = regulator_get_voltage(st->reg); | 241 | ret = regulator_get_voltage(st->reg); |
242 | if (ret < 0) | ||
243 | goto error_disable_reg; | ||
244 | |||
245 | voltage_uv = ret; | ||
242 | } | 246 | } |
243 | 247 | ||
244 | spi_set_drvdata(spi, indio_dev); | 248 | spi_set_drvdata(spi, indio_dev); |
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 36e51382ae52..ca9609d7a15c 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c | |||
@@ -332,7 +332,11 @@ static int ad5686_probe(struct spi_device *spi) | |||
332 | if (ret) | 332 | if (ret) |
333 | goto error_put_reg; | 333 | goto error_put_reg; |
334 | 334 | ||
335 | voltage_uv = regulator_get_voltage(st->reg); | 335 | ret = regulator_get_voltage(st->reg); |
336 | if (ret < 0) | ||
337 | goto error_disable_reg; | ||
338 | |||
339 | voltage_uv = ret; | ||
336 | } | 340 | } |
337 | 341 | ||
338 | st->chip_info = | 342 | st->chip_info = |
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index c84180f23139..6407b5407ddd 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c | |||
@@ -365,7 +365,11 @@ static int ad5791_probe(struct spi_device *spi) | |||
365 | if (ret) | 365 | if (ret) |
366 | goto error_put_reg_pos; | 366 | goto error_put_reg_pos; |
367 | 367 | ||
368 | pos_voltage_uv = regulator_get_voltage(st->reg_vdd); | 368 | ret = regulator_get_voltage(st->reg_vdd); |
369 | if (ret < 0) | ||
370 | goto error_disable_reg_pos; | ||
371 | |||
372 | pos_voltage_uv = ret; | ||
369 | } | 373 | } |
370 | 374 | ||
371 | st->reg_vss = regulator_get(&spi->dev, "vss"); | 375 | st->reg_vss = regulator_get(&spi->dev, "vss"); |
@@ -374,7 +378,11 @@ static int ad5791_probe(struct spi_device *spi) | |||
374 | if (ret) | 378 | if (ret) |
375 | goto error_put_reg_neg; | 379 | goto error_put_reg_neg; |
376 | 380 | ||
377 | neg_voltage_uv = regulator_get_voltage(st->reg_vss); | 381 | ret = regulator_get_voltage(st->reg_vss); |
382 | if (ret < 0) | ||
383 | goto error_disable_reg_neg; | ||
384 | |||
385 | neg_voltage_uv = ret; | ||
378 | } | 386 | } |
379 | 387 | ||
380 | st->pwr_down = true; | 388 | st->pwr_down = true; |
@@ -428,6 +436,7 @@ error_put_reg_neg: | |||
428 | if (!IS_ERR(st->reg_vss)) | 436 | if (!IS_ERR(st->reg_vss)) |
429 | regulator_put(st->reg_vss); | 437 | regulator_put(st->reg_vss); |
430 | 438 | ||
439 | error_disable_reg_pos: | ||
431 | if (!IS_ERR(st->reg_vdd)) | 440 | if (!IS_ERR(st->reg_vdd)) |
432 | regulator_disable(st->reg_vdd); | 441 | regulator_disable(st->reg_vdd); |
433 | error_put_reg_pos: | 442 | error_put_reg_pos: |
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index e5033b4cfba0..a884252ac66b 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c | |||
@@ -173,7 +173,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) | |||
173 | } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); | 173 | } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); |
174 | } while (r_cnt == 0); | 174 | } while (r_cnt == 0); |
175 | 175 | ||
176 | tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); | 176 | tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1); |
177 | do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ | 177 | do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ |
178 | st->r0_fract = do_div(tmp, st->r1_mod); | 178 | st->r0_fract = do_div(tmp, st->r1_mod); |
179 | st->r0_int = tmp; | 179 | st->r0_int = tmp; |
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 48ed1483ff27..96b68f63a902 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig | |||
@@ -17,6 +17,7 @@ config HID_SENSOR_GYRO_3D | |||
17 | select IIO_BUFFER | 17 | select IIO_BUFFER |
18 | select IIO_TRIGGERED_BUFFER | 18 | select IIO_TRIGGERED_BUFFER |
19 | select HID_SENSOR_IIO_COMMON | 19 | select HID_SENSOR_IIO_COMMON |
20 | select HID_SENSOR_IIO_TRIGGER | ||
20 | tristate "HID Gyroscope 3D" | 21 | tristate "HID Gyroscope 3D" |
21 | help | 22 | help |
22 | Say yes here to build support for the HID SENSOR | 23 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 1763c9bcb98a..dbf80abc834f 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig | |||
@@ -47,6 +47,7 @@ config HID_SENSOR_ALS | |||
47 | select IIO_BUFFER | 47 | select IIO_BUFFER |
48 | select IIO_TRIGGERED_BUFFER | 48 | select IIO_TRIGGERED_BUFFER |
49 | select HID_SENSOR_IIO_COMMON | 49 | select HID_SENSOR_IIO_COMMON |
50 | select HID_SENSOR_IIO_TRIGGER | ||
50 | tristate "HID ALS" | 51 | tristate "HID ALS" |
51 | help | 52 | help |
52 | Say yes here to build support for the HID SENSOR | 53 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index c1f0cdd57037..ff11d68225cf 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig | |||
@@ -8,6 +8,7 @@ config HID_SENSOR_MAGNETOMETER_3D | |||
8 | select IIO_BUFFER | 8 | select IIO_BUFFER |
9 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
10 | select HID_SENSOR_IIO_COMMON | 10 | select HID_SENSOR_IIO_COMMON |
11 | select HID_SENSOR_IIO_TRIGGER | ||
11 | tristate "HID Magenetometer 3D" | 12 | tristate "HID Magenetometer 3D" |
12 | help | 13 | help |
13 | Say yes here to build support for the HID SENSOR | 14 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 8a8d42fe2633..d4e7567b367c 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
556 | mutex_lock(&info->lock); | 556 | mutex_lock(&info->lock); |
557 | 557 | ||
558 | format = __find_format(info, fh, fmt->which, info->res_type); | 558 | format = __find_format(info, fh, fmt->which, info->res_type); |
559 | if (!format) | 559 | if (format) |
560 | fmt->format = *format; | 560 | fmt->format = *format; |
561 | else | 561 | else |
562 | ret = -EINVAL; | 562 | ret = -EINVAL; |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 1cf8293c0fb0..4a980e029ca7 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/platform_data/imx-iram.h> | ||
26 | 27 | ||
27 | #include <mach/iram.h> | ||
28 | #include <media/v4l2-ctrls.h> | 28 | #include <media/v4l2-ctrls.h> |
29 | #include <media/v4l2-device.h> | 29 | #include <media/v4l2-device.h> |
30 | #include <media/v4l2-ioctl.h> | 30 | #include <media/v4l2-ioctl.h> |
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index e0d73a642186..8dac17511e61 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c | |||
@@ -35,9 +35,6 @@ | |||
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <media/v4l2-dev.h> | 36 | #include <media/v4l2-dev.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include <plat/iommu.h> | ||
39 | #include <plat/iovmm.h> | ||
40 | #include <plat/omap-pm.h> | ||
41 | 38 | ||
42 | #include "ispvideo.h" | 39 | #include "ispvideo.h" |
43 | #include "isp.h" | 40 | #include "isp.h" |
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 4ab99f3a7b09..b4a68ecf0ca7 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c | |||
@@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) | |||
593 | { | 593 | { |
594 | struct media_entity *source, *sink; | 594 | struct media_entity *source, *sink; |
595 | unsigned int flags = MEDIA_LNK_FL_ENABLED; | 595 | unsigned int flags = MEDIA_LNK_FL_ENABLED; |
596 | int i, ret; | 596 | int i, ret = 0; |
597 | 597 | ||
598 | for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { | 598 | for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { |
599 | struct fimc_lite *fimc = fmd->fimc_lite[i]; | 599 | struct fimc_lite *fimc = fmd->fimc_lite[i]; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 379f57433711..681bc6ba149d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -412,62 +412,48 @@ leave_handle_frame: | |||
412 | } | 412 | } |
413 | 413 | ||
414 | /* Error handling for interrupt */ | 414 | /* Error handling for interrupt */ |
415 | static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, | 415 | static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, |
416 | unsigned int reason, unsigned int err) | 416 | struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) |
417 | { | 417 | { |
418 | struct s5p_mfc_dev *dev; | ||
419 | unsigned long flags; | 418 | unsigned long flags; |
420 | 419 | ||
421 | /* If no context is available then all necessary | ||
422 | * processing has been done. */ | ||
423 | if (ctx == NULL) | ||
424 | return; | ||
425 | |||
426 | dev = ctx->dev; | ||
427 | mfc_err("Interrupt Error: %08x\n", err); | 420 | mfc_err("Interrupt Error: %08x\n", err); |
428 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
429 | wake_up_dev(dev, reason, err); | ||
430 | 421 | ||
431 | /* Error recovery is dependent on the state of context */ | 422 | if (ctx != NULL) { |
432 | switch (ctx->state) { | 423 | /* Error recovery is dependent on the state of context */ |
433 | case MFCINST_INIT: | 424 | switch (ctx->state) { |
434 | /* This error had to happen while acquireing instance */ | 425 | case MFCINST_RES_CHANGE_INIT: |
435 | case MFCINST_GOT_INST: | 426 | case MFCINST_RES_CHANGE_FLUSH: |
436 | /* This error had to happen while parsing the header */ | 427 | case MFCINST_RES_CHANGE_END: |
437 | case MFCINST_HEAD_PARSED: | 428 | case MFCINST_FINISHING: |
438 | /* This error had to happen while setting dst buffers */ | 429 | case MFCINST_FINISHED: |
439 | case MFCINST_RETURN_INST: | 430 | case MFCINST_RUNNING: |
440 | /* This error had to happen while releasing instance */ | 431 | /* It is higly probable that an error occured |
441 | clear_work_bit(ctx); | 432 | * while decoding a frame */ |
442 | wake_up_ctx(ctx, reason, err); | 433 | clear_work_bit(ctx); |
443 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 434 | ctx->state = MFCINST_ERROR; |
444 | BUG(); | 435 | /* Mark all dst buffers as having an error */ |
445 | s5p_mfc_clock_off(); | 436 | spin_lock_irqsave(&dev->irqlock, flags); |
446 | ctx->state = MFCINST_ERROR; | 437 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
447 | break; | 438 | &ctx->dst_queue, &ctx->vq_dst); |
448 | case MFCINST_FINISHING: | 439 | /* Mark all src buffers as having an error */ |
449 | case MFCINST_FINISHED: | 440 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
450 | case MFCINST_RUNNING: | 441 | &ctx->src_queue, &ctx->vq_src); |
451 | /* It is higly probable that an error occured | 442 | spin_unlock_irqrestore(&dev->irqlock, flags); |
452 | * while decoding a frame */ | 443 | wake_up_ctx(ctx, reason, err); |
453 | clear_work_bit(ctx); | 444 | break; |
454 | ctx->state = MFCINST_ERROR; | 445 | default: |
455 | /* Mark all dst buffers as having an error */ | 446 | clear_work_bit(ctx); |
456 | spin_lock_irqsave(&dev->irqlock, flags); | 447 | ctx->state = MFCINST_ERROR; |
457 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, | 448 | wake_up_ctx(ctx, reason, err); |
458 | &ctx->vq_dst); | 449 | break; |
459 | /* Mark all src buffers as having an error */ | 450 | } |
460 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, | ||
461 | &ctx->vq_src); | ||
462 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
463 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
464 | BUG(); | ||
465 | s5p_mfc_clock_off(); | ||
466 | break; | ||
467 | default: | ||
468 | mfc_err("Encountered an error interrupt which had not been handled\n"); | ||
469 | break; | ||
470 | } | 451 | } |
452 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
453 | BUG(); | ||
454 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
455 | s5p_mfc_clock_off(); | ||
456 | wake_up_dev(dev, reason, err); | ||
471 | return; | 457 | return; |
472 | } | 458 | } |
473 | 459 | ||
@@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) | |||
632 | dev->warn_start) | 618 | dev->warn_start) |
633 | s5p_mfc_handle_frame(ctx, reason, err); | 619 | s5p_mfc_handle_frame(ctx, reason, err); |
634 | else | 620 | else |
635 | s5p_mfc_handle_error(ctx, reason, err); | 621 | s5p_mfc_handle_error(dev, ctx, reason, err); |
636 | clear_bit(0, &dev->enter_suspend); | 622 | clear_bit(0, &dev->enter_suspend); |
637 | break; | 623 | break; |
638 | 624 | ||
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 40ad6687ee5d..3773a8a745df 100644 --- a/drivers/media/usb/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c | |||
@@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = { | |||
381 | /* -- module initialisation -- */ | 381 | /* -- module initialisation -- */ |
382 | static const struct usb_device_id device_table[] = { | 382 | static const struct usb_device_id device_table[] = { |
383 | {USB_DEVICE(0x045e, 0x02ae)}, | 383 | {USB_DEVICE(0x045e, 0x02ae)}, |
384 | {USB_DEVICE(0x045e, 0x02bf)}, | ||
384 | {} | 385 | {} |
385 | }; | 386 | }; |
386 | 387 | ||
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 70511d5f9538..1220340e7602 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c | |||
@@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
496 | } | 496 | } |
497 | } | 497 | } |
498 | 498 | ||
499 | static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) | 499 | static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) |
500 | { | 500 | { |
501 | int retry = 60; | 501 | int retry = 60; |
502 | 502 | ||
@@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) | |||
504 | return; | 504 | return; |
505 | 505 | ||
506 | /* is i2c ready */ | 506 | /* is i2c ready */ |
507 | reg_w(gspca_dev, 0x08, buffer, 8); | 507 | reg_w(gspca_dev, 0x08, buf, 8); |
508 | while (retry--) { | 508 | while (retry--) { |
509 | if (gspca_dev->usb_err < 0) | 509 | if (gspca_dev->usb_err < 0) |
510 | return; | 510 | return; |
511 | msleep(10); | 511 | msleep(1); |
512 | reg_r(gspca_dev, 0x08); | 512 | reg_r(gspca_dev, 0x08); |
513 | if (gspca_dev->usb_buf[0] & 0x04) { | 513 | if (gspca_dev->usb_buf[0] & 0x04) { |
514 | if (gspca_dev->usb_buf[0] & 0x08) { | 514 | if (gspca_dev->usb_buf[0] & 0x08) { |
515 | dev_err(gspca_dev->v4l2_dev.dev, | 515 | dev_err(gspca_dev->v4l2_dev.dev, |
516 | "i2c write error\n"); | 516 | "i2c error writing %02x %02x %02x %02x" |
517 | " %02x %02x %02x %02x\n", | ||
518 | buf[0], buf[1], buf[2], buf[3], | ||
519 | buf[4], buf[5], buf[6], buf[7]); | ||
517 | gspca_dev->usb_err = -EIO; | 520 | gspca_dev->usb_err = -EIO; |
518 | } | 521 | } |
519 | return; | 522 | return; |
@@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev, | |||
530 | for (;;) { | 533 | for (;;) { |
531 | if (gspca_dev->usb_err < 0) | 534 | if (gspca_dev->usb_err < 0) |
532 | return; | 535 | return; |
533 | reg_w(gspca_dev, 0x08, *buffer, 8); | 536 | i2c_w(gspca_dev, *buffer); |
534 | len -= 8; | 537 | len -= 8; |
535 | if (len <= 0) | 538 | if (len <= 0) |
536 | break; | 539 | break; |
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index 5a86047b846f..36307a9028a9 100644 --- a/drivers/media/usb/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c | |||
@@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1550 | 0, | 1550 | 0, |
1551 | gspca_dev->usb_buf, 8, | 1551 | gspca_dev->usb_buf, 8, |
1552 | 500); | 1552 | 500); |
1553 | msleep(2); | ||
1553 | if (ret < 0) { | 1554 | if (ret < 0) { |
1554 | pr_err("i2c_w1 err %d\n", ret); | 1555 | pr_err("i2c_w1 err %d\n", ret); |
1555 | gspca_dev->usb_err = ret; | 1556 | gspca_dev->usb_err = ret; |
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 2bb7613ddebb..d5baab17a5ef 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c | |||
@@ -1431,8 +1431,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
1431 | int ret; | 1431 | int ret; |
1432 | 1432 | ||
1433 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1433 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
1434 | if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) | 1434 | if (ctrl == NULL) |
1435 | return -EINVAL; | 1435 | return -EINVAL; |
1436 | if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) | ||
1437 | return -EACCES; | ||
1436 | 1438 | ||
1437 | /* Clamp out of range values. */ | 1439 | /* Clamp out of range values. */ |
1438 | switch (mapping->v4l2_type) { | 1440 | switch (mapping->v4l2_type) { |
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f2ee8c6b0d8d..68d59b527492 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c | |||
@@ -657,8 +657,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
657 | ret = uvc_ctrl_get(chain, ctrl); | 657 | ret = uvc_ctrl_get(chain, ctrl); |
658 | if (ret < 0) { | 658 | if (ret < 0) { |
659 | uvc_ctrl_rollback(handle); | 659 | uvc_ctrl_rollback(handle); |
660 | ctrls->error_idx = ret == -ENOENT | 660 | ctrls->error_idx = i; |
661 | ? ctrls->count : i; | ||
662 | return ret; | 661 | return ret; |
663 | } | 662 | } |
664 | } | 663 | } |
@@ -686,8 +685,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
686 | ret = uvc_ctrl_set(chain, ctrl); | 685 | ret = uvc_ctrl_set(chain, ctrl); |
687 | if (ret < 0) { | 686 | if (ret < 0) { |
688 | uvc_ctrl_rollback(handle); | 687 | uvc_ctrl_rollback(handle); |
689 | ctrls->error_idx = (ret == -ENOENT && | 688 | ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS |
690 | cmd == VIDIOC_S_EXT_CTRLS) | ||
691 | ? ctrls->count : i; | 689 | ? ctrls->count : i; |
692 | return ret; | 690 | return ret; |
693 | } | 691 | } |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9f81be23a81f..e02c4797b1c6 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b | |||
921 | * In videobuf we use our internal V4l2_planes struct for | 921 | * In videobuf we use our internal V4l2_planes struct for |
922 | * single-planar buffers as well, for simplicity. | 922 | * single-planar buffers as well, for simplicity. |
923 | */ | 923 | */ |
924 | if (V4L2_TYPE_IS_OUTPUT(b->type)) | 924 | if (V4L2_TYPE_IS_OUTPUT(b->type)) { |
925 | v4l2_planes[0].bytesused = b->bytesused; | 925 | v4l2_planes[0].bytesused = b->bytesused; |
926 | v4l2_planes[0].data_offset = 0; | ||
927 | } | ||
926 | 928 | ||
927 | if (b->memory == V4L2_MEMORY_USERPTR) { | 929 | if (b->memory == V4L2_MEMORY_USERPTR) { |
928 | v4l2_planes[0].m.userptr = b->m.userptr; | 930 | v4l2_planes[0].m.userptr = b->m.userptr; |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4dfc43..47ad4e270877 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -292,6 +292,7 @@ config TWL4030_CORE | |||
292 | bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" | 292 | bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" |
293 | depends on I2C=y && GENERIC_HARDIRQS | 293 | depends on I2C=y && GENERIC_HARDIRQS |
294 | select IRQ_DOMAIN | 294 | select IRQ_DOMAIN |
295 | select REGMAP_I2C | ||
295 | help | 296 | help |
296 | Say yes here if you have TWL4030 / TWL6030 family chip on your board. | 297 | Say yes here if you have TWL4030 / TWL6030 family chip on your board. |
297 | This core driver provides register access and IRQ handling | 298 | This core driver provides register access and IRQ handling |
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index e5d8f63b252a..77048b18439e 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c | |||
@@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data) | |||
313 | } | 313 | } |
314 | 314 | ||
315 | 315 | ||
316 | void __init vexpress_sysreg_early_init(void __iomem *base) | 316 | void __init vexpress_sysreg_setup(struct device_node *node) |
317 | { | 317 | { |
318 | struct device_node *node = of_find_compatible_node(NULL, NULL, | 318 | if (WARN_ON(!vexpress_sysreg_base)) |
319 | "arm,vexpress-sysreg"); | ||
320 | |||
321 | if (node) | ||
322 | base = of_iomap(node, 0); | ||
323 | |||
324 | if (WARN_ON(!base)) | ||
325 | return; | 319 | return; |
326 | 320 | ||
327 | vexpress_sysreg_base = base; | ||
328 | |||
329 | if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) | 321 | if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) |
330 | vexpress_master_site = VEXPRESS_SITE_DB2; | 322 | vexpress_master_site = VEXPRESS_SITE_DB2; |
331 | else | 323 | else |
@@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base) | |||
336 | WARN_ON(!vexpress_sysreg_config_bridge); | 328 | WARN_ON(!vexpress_sysreg_config_bridge); |
337 | } | 329 | } |
338 | 330 | ||
331 | void __init vexpress_sysreg_early_init(void __iomem *base) | ||
332 | { | ||
333 | vexpress_sysreg_base = base; | ||
334 | vexpress_sysreg_setup(NULL); | ||
335 | } | ||
336 | |||
339 | void __init vexpress_sysreg_of_early_init(void) | 337 | void __init vexpress_sysreg_of_early_init(void) |
340 | { | 338 | { |
341 | vexpress_sysreg_early_init(NULL); | 339 | struct device_node *node = of_find_compatible_node(NULL, NULL, |
340 | "arm,vexpress-sysreg"); | ||
341 | |||
342 | if (node) { | ||
343 | vexpress_sysreg_base = of_iomap(node, 0); | ||
344 | vexpress_sysreg_setup(node); | ||
345 | } else { | ||
346 | pr_info("vexpress-sysreg: No Device Tree node found."); | ||
347 | } | ||
342 | } | 348 | } |
343 | 349 | ||
344 | 350 | ||
@@ -426,9 +432,11 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) | |||
426 | return -EBUSY; | 432 | return -EBUSY; |
427 | } | 433 | } |
428 | 434 | ||
429 | if (!vexpress_sysreg_base) | 435 | if (!vexpress_sysreg_base) { |
430 | vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, | 436 | vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, |
431 | resource_size(res)); | 437 | resource_size(res)); |
438 | vexpress_sysreg_setup(pdev->dev.of_node); | ||
439 | } | ||
432 | 440 | ||
433 | if (!vexpress_sysreg_base) { | 441 | if (!vexpress_sysreg_base) { |
434 | dev_err(&pdev->dev, "Failed to obtain base address!\n"); | 442 | dev_err(&pdev->dev, "Failed to obtain base address!\n"); |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 18794aea6062..e40ffd9502d1 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -187,13 +187,13 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, | |||
187 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | 187 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, |
188 | (cb = mei_amthif_find_read_list_entry(dev, file))); | 188 | (cb = mei_amthif_find_read_list_entry(dev, file))); |
189 | 189 | ||
190 | /* Locking again the Mutex */ | ||
191 | mutex_lock(&dev->device_lock); | ||
192 | |||
190 | if (wait_ret) | 193 | if (wait_ret) |
191 | return -ERESTARTSYS; | 194 | return -ERESTARTSYS; |
192 | 195 | ||
193 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | 196 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); |
194 | |||
195 | /* Locking again the Mutex */ | ||
196 | mutex_lock(&dev->device_lock); | ||
197 | } | 197 | } |
198 | 198 | ||
199 | 199 | ||
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9ff942a346ed..83269f1d16e3 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -468,6 +468,11 @@ long st_kim_start(void *kim_data) | |||
468 | if (pdata->chip_enable) | 468 | if (pdata->chip_enable) |
469 | pdata->chip_enable(kim_gdata); | 469 | pdata->chip_enable(kim_gdata); |
470 | 470 | ||
471 | /* Configure BT nShutdown to HIGH state */ | ||
472 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
473 | mdelay(5); /* FIXME: a proper toggle */ | ||
474 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
475 | mdelay(100); | ||
471 | /* re-initialize the completion */ | 476 | /* re-initialize the completion */ |
472 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 477 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
473 | /* send notification to UIM */ | 478 | /* send notification to UIM */ |
@@ -509,7 +514,8 @@ long st_kim_start(void *kim_data) | |||
509 | * (b) upon failure to either install ldisc or download firmware. | 514 | * (b) upon failure to either install ldisc or download firmware. |
510 | * The function is responsible to (a) notify UIM about un-installation, | 515 | * The function is responsible to (a) notify UIM about un-installation, |
511 | * (b) flush UART if the ldisc was installed. | 516 | * (b) flush UART if the ldisc was installed. |
512 | * (c) invoke platform's chip disabling routine. | 517 | * (c) reset BT_EN - pull down nshutdown at the end. |
518 | * (d) invoke platform's chip disabling routine. | ||
513 | */ | 519 | */ |
514 | long st_kim_stop(void *kim_data) | 520 | long st_kim_stop(void *kim_data) |
515 | { | 521 | { |
@@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data) | |||
541 | err = -ETIMEDOUT; | 547 | err = -ETIMEDOUT; |
542 | } | 548 | } |
543 | 549 | ||
550 | /* By default configure BT nShutdown to LOW state */ | ||
551 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
552 | mdelay(1); | ||
553 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
554 | mdelay(1); | ||
555 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
556 | |||
544 | /* platform specific disable */ | 557 | /* platform specific disable */ |
545 | if (pdata->chip_disable) | 558 | if (pdata->chip_disable) |
546 | pdata->chip_disable(kim_gdata); | 559 | pdata->chip_disable(kim_gdata); |
@@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev) | |||
733 | /* refer to itself */ | 746 | /* refer to itself */ |
734 | kim_gdata->core_data->kim_data = kim_gdata; | 747 | kim_gdata->core_data->kim_data = kim_gdata; |
735 | 748 | ||
749 | /* Claim the chip enable nShutdown gpio from the system */ | ||
750 | kim_gdata->nshutdown = pdata->nshutdown_gpio; | ||
751 | err = gpio_request(kim_gdata->nshutdown, "kim"); | ||
752 | if (unlikely(err)) { | ||
753 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | ||
754 | return err; | ||
755 | } | ||
756 | |||
757 | /* Configure nShutdown GPIO as output=0 */ | ||
758 | err = gpio_direction_output(kim_gdata->nshutdown, 0); | ||
759 | if (unlikely(err)) { | ||
760 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); | ||
761 | return err; | ||
762 | } | ||
736 | /* get reference of pdev for request_firmware | 763 | /* get reference of pdev for request_firmware |
737 | */ | 764 | */ |
738 | kim_gdata->kim_pdev = pdev; | 765 | kim_gdata->kim_pdev = pdev; |
@@ -779,10 +806,18 @@ err_core_init: | |||
779 | 806 | ||
780 | static int kim_remove(struct platform_device *pdev) | 807 | static int kim_remove(struct platform_device *pdev) |
781 | { | 808 | { |
809 | /* free the GPIOs requested */ | ||
810 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
782 | struct kim_data_s *kim_gdata; | 811 | struct kim_data_s *kim_gdata; |
783 | 812 | ||
784 | kim_gdata = dev_get_drvdata(&pdev->dev); | 813 | kim_gdata = dev_get_drvdata(&pdev->dev); |
785 | 814 | ||
815 | /* Free the Bluetooth/FM/GPIO | ||
816 | * nShutdown gpio from the system | ||
817 | */ | ||
818 | gpio_free(pdata->nshutdown_gpio); | ||
819 | pr_info("nshutdown GPIO Freed"); | ||
820 | |||
786 | debugfs_remove_recursive(kim_debugfs_dir); | 821 | debugfs_remove_recursive(kim_debugfs_dir); |
787 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | 822 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); |
788 | pr_info("sysfs entries removed"); | 823 | pr_info("sysfs entries removed"); |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index de4c20b3936c..f8dd36102949 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -50,8 +50,6 @@ struct mvsd_host { | |||
50 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | struct mmc_host *mmc; | 51 | struct mmc_host *mmc; |
52 | struct device *dev; | 52 | struct device *dev; |
53 | struct resource *res; | ||
54 | int irq; | ||
55 | struct clk *clk; | 53 | struct clk *clk; |
56 | int gpio_card_detect; | 54 | int gpio_card_detect; |
57 | int gpio_write_protect; | 55 | int gpio_write_protect; |
@@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
718 | if (!r || irq < 0 || !mvsd_data) | 716 | if (!r || irq < 0 || !mvsd_data) |
719 | return -ENXIO; | 717 | return -ENXIO; |
720 | 718 | ||
721 | r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); | ||
722 | if (!r) | ||
723 | return -EBUSY; | ||
724 | |||
725 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); | 719 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); |
726 | if (!mmc) { | 720 | if (!mmc) { |
727 | ret = -ENOMEM; | 721 | ret = -ENOMEM; |
@@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
731 | host = mmc_priv(mmc); | 725 | host = mmc_priv(mmc); |
732 | host->mmc = mmc; | 726 | host->mmc = mmc; |
733 | host->dev = &pdev->dev; | 727 | host->dev = &pdev->dev; |
734 | host->res = r; | ||
735 | host->base_clock = mvsd_data->clock / 2; | 728 | host->base_clock = mvsd_data->clock / 2; |
729 | host->clk = ERR_PTR(-EINVAL); | ||
736 | 730 | ||
737 | mmc->ops = &mvsd_ops; | 731 | mmc->ops = &mvsd_ops; |
738 | 732 | ||
@@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
752 | 746 | ||
753 | spin_lock_init(&host->lock); | 747 | spin_lock_init(&host->lock); |
754 | 748 | ||
755 | host->base = ioremap(r->start, SZ_4K); | 749 | host->base = devm_request_and_ioremap(&pdev->dev, r); |
756 | if (!host->base) { | 750 | if (!host->base) { |
757 | ret = -ENOMEM; | 751 | ret = -ENOMEM; |
758 | goto out; | 752 | goto out; |
@@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
765 | 759 | ||
766 | mvsd_power_down(host); | 760 | mvsd_power_down(host); |
767 | 761 | ||
768 | ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); | 762 | ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); |
769 | if (ret) { | 763 | if (ret) { |
770 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); | 764 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); |
771 | goto out; | 765 | goto out; |
772 | } else | 766 | } |
773 | host->irq = irq; | ||
774 | 767 | ||
775 | /* Not all platforms can gate the clock, so it is not | 768 | /* Not all platforms can gate the clock, so it is not |
776 | an error if the clock does not exists. */ | 769 | an error if the clock does not exists. */ |
777 | host->clk = clk_get(&pdev->dev, NULL); | 770 | host->clk = devm_clk_get(&pdev->dev, NULL); |
778 | if (!IS_ERR(host->clk)) { | 771 | if (!IS_ERR(host->clk)) |
779 | clk_prepare_enable(host->clk); | 772 | clk_prepare_enable(host->clk); |
780 | } | ||
781 | 773 | ||
782 | if (mvsd_data->gpio_card_detect) { | 774 | if (mvsd_data->gpio_card_detect) { |
783 | ret = gpio_request(mvsd_data->gpio_card_detect, | 775 | ret = devm_gpio_request_one(&pdev->dev, |
784 | DRIVER_NAME " cd"); | 776 | mvsd_data->gpio_card_detect, |
777 | GPIOF_IN, DRIVER_NAME " cd"); | ||
785 | if (ret == 0) { | 778 | if (ret == 0) { |
786 | gpio_direction_input(mvsd_data->gpio_card_detect); | ||
787 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); | 779 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); |
788 | ret = request_irq(irq, mvsd_card_detect_irq, | 780 | ret = devm_request_irq(&pdev->dev, irq, |
789 | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, | 781 | mvsd_card_detect_irq, |
790 | DRIVER_NAME " cd", host); | 782 | IRQ_TYPE_EDGE_RISING | |
783 | IRQ_TYPE_EDGE_FALLING, | ||
784 | DRIVER_NAME " cd", host); | ||
791 | if (ret == 0) | 785 | if (ret == 0) |
792 | host->gpio_card_detect = | 786 | host->gpio_card_detect = |
793 | mvsd_data->gpio_card_detect; | 787 | mvsd_data->gpio_card_detect; |
794 | else | 788 | else |
795 | gpio_free(mvsd_data->gpio_card_detect); | 789 | devm_gpio_free(&pdev->dev, |
790 | mvsd_data->gpio_card_detect); | ||
796 | } | 791 | } |
797 | } | 792 | } |
798 | if (!host->gpio_card_detect) | 793 | if (!host->gpio_card_detect) |
799 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 794 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
800 | 795 | ||
801 | if (mvsd_data->gpio_write_protect) { | 796 | if (mvsd_data->gpio_write_protect) { |
802 | ret = gpio_request(mvsd_data->gpio_write_protect, | 797 | ret = devm_gpio_request_one(&pdev->dev, |
803 | DRIVER_NAME " wp"); | 798 | mvsd_data->gpio_write_protect, |
799 | GPIOF_IN, DRIVER_NAME " wp"); | ||
804 | if (ret == 0) { | 800 | if (ret == 0) { |
805 | gpio_direction_input(mvsd_data->gpio_write_protect); | ||
806 | host->gpio_write_protect = | 801 | host->gpio_write_protect = |
807 | mvsd_data->gpio_write_protect; | 802 | mvsd_data->gpio_write_protect; |
808 | } | 803 | } |
@@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
824 | return 0; | 819 | return 0; |
825 | 820 | ||
826 | out: | 821 | out: |
827 | if (host) { | 822 | if (mmc) { |
828 | if (host->irq) | 823 | if (!IS_ERR(host->clk)) |
829 | free_irq(host->irq, host); | ||
830 | if (host->gpio_card_detect) { | ||
831 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | ||
832 | gpio_free(host->gpio_card_detect); | ||
833 | } | ||
834 | if (host->gpio_write_protect) | ||
835 | gpio_free(host->gpio_write_protect); | ||
836 | if (host->base) | ||
837 | iounmap(host->base); | ||
838 | } | ||
839 | if (r) | ||
840 | release_resource(r); | ||
841 | if (mmc) | ||
842 | if (!IS_ERR_OR_NULL(host->clk)) { | ||
843 | clk_disable_unprepare(host->clk); | 824 | clk_disable_unprepare(host->clk); |
844 | clk_put(host->clk); | ||
845 | } | ||
846 | mmc_free_host(mmc); | 825 | mmc_free_host(mmc); |
826 | } | ||
847 | 827 | ||
848 | return ret; | 828 | return ret; |
849 | } | 829 | } |
@@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev) | |||
852 | { | 832 | { |
853 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 833 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
854 | 834 | ||
855 | if (mmc) { | 835 | struct mvsd_host *host = mmc_priv(mmc); |
856 | struct mvsd_host *host = mmc_priv(mmc); | ||
857 | 836 | ||
858 | if (host->gpio_card_detect) { | 837 | mmc_remove_host(mmc); |
859 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | 838 | del_timer_sync(&host->timer); |
860 | gpio_free(host->gpio_card_detect); | 839 | mvsd_power_down(host); |
861 | } | 840 | |
862 | mmc_remove_host(mmc); | 841 | if (!IS_ERR(host->clk)) |
863 | free_irq(host->irq, host); | 842 | clk_disable_unprepare(host->clk); |
864 | if (host->gpio_write_protect) | 843 | mmc_free_host(mmc); |
865 | gpio_free(host->gpio_write_protect); | ||
866 | del_timer_sync(&host->timer); | ||
867 | mvsd_power_down(host); | ||
868 | iounmap(host->base); | ||
869 | release_resource(host->res); | ||
870 | 844 | ||
871 | if (!IS_ERR(host->clk)) { | ||
872 | clk_disable_unprepare(host->clk); | ||
873 | clk_put(host->clk); | ||
874 | } | ||
875 | mmc_free_host(mmc); | ||
876 | } | ||
877 | platform_set_drvdata(pdev, NULL); | 845 | platform_set_drvdata(pdev, NULL); |
878 | return 0; | 846 | return 0; |
879 | } | 847 | } |
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig index e49c0eff040b..a9481606bbcd 100644 --- a/drivers/net/ethernet/adi/Kconfig +++ b/drivers/net/ethernet/adi/Kconfig | |||
@@ -61,6 +61,7 @@ config BFIN_RX_DESC_NUM | |||
61 | 61 | ||
62 | config BFIN_MAC_USE_HWSTAMP | 62 | config BFIN_MAC_USE_HWSTAMP |
63 | bool "Use IEEE 1588 hwstamp" | 63 | bool "Use IEEE 1588 hwstamp" |
64 | depends on BFIN_MAC && BF518 | ||
64 | select PTP_1588_CLOCK | 65 | select PTP_1588_CLOCK |
65 | default y | 66 | default y |
66 | ---help--- | 67 | ---help--- |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 01588b66a38c..f771ddfba646 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) | |||
80 | new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; | 80 | new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; |
81 | } | 81 | } |
82 | 82 | ||
83 | memcpy(&bp->bnx2x_txq[old_txdata_index], | 83 | memcpy(&bp->bnx2x_txq[new_txdata_index], |
84 | &bp->bnx2x_txq[new_txdata_index], | 84 | &bp->bnx2x_txq[old_txdata_index], |
85 | sizeof(struct bnx2x_fp_txdata)); | 85 | sizeof(struct bnx2x_fp_txdata)); |
86 | to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; | 86 | to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; |
87 | } | 87 | } |
88 | 88 | ||
89 | /** | ||
90 | * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact | ||
91 | * | ||
92 | * @bp: driver handle | ||
93 | * @delta: number of eth queues which were not allocated | ||
94 | */ | ||
95 | static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) | ||
96 | { | ||
97 | int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); | ||
98 | |||
99 | /* Queue pointer cannot be re-set on an fp-basis, as moving pointer | ||
100 | * backward along the array could cause memory to be overriden | ||
101 | */ | ||
102 | for (cos = 1; cos < bp->max_cos; cos++) { | ||
103 | for (i = 0; i < old_eth_num - delta; i++) { | ||
104 | struct bnx2x_fastpath *fp = &bp->fp[i]; | ||
105 | int new_idx = cos * (old_eth_num - delta) + i; | ||
106 | |||
107 | memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], | ||
108 | sizeof(struct bnx2x_fp_txdata)); | ||
109 | fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
89 | int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ | 114 | int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ |
90 | 115 | ||
91 | /* free skb in the packet ring at pos idx | 116 | /* free skb in the packet ring at pos idx |
@@ -3863,6 +3888,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) | |||
3863 | int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; | 3888 | int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; |
3864 | 3889 | ||
3865 | WARN_ON(delta < 0); | 3890 | WARN_ON(delta < 0); |
3891 | bnx2x_shrink_eth_fp(bp, delta); | ||
3866 | if (CNIC_SUPPORT(bp)) | 3892 | if (CNIC_SUPPORT(bp)) |
3867 | /* move non eth FPs next to last eth FP | 3893 | /* move non eth FPs next to last eth FP |
3868 | * must be done in that order | 3894 | * must be done in that order |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 277f17e3c8f8..a427b49a886c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
@@ -2777,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) | |||
2777 | } else if ((info->flow_type == UDP_V6_FLOW) && | 2777 | } else if ((info->flow_type == UDP_V6_FLOW) && |
2778 | (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { | 2778 | (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { |
2779 | bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; | 2779 | bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; |
2780 | return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); | ||
2781 | DP(BNX2X_MSG_ETHTOOL, | 2780 | DP(BNX2X_MSG_ETHTOOL, |
2782 | "rss re-configured, UDP 4-tupple %s\n", | 2781 | "rss re-configured, UDP 4-tupple %s\n", |
2783 | udp_rss_requested ? "enabled" : "disabled"); | 2782 | udp_rss_requested ? "enabled" : "disabled"); |
2783 | return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); | ||
2784 | } else { | 2784 | } else { |
2785 | return 0; | 2785 | return 0; |
2786 | } | 2786 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 940ef859dc60..5523da3afcdc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); | |||
127 | 127 | ||
128 | struct workqueue_struct *bnx2x_wq; | 128 | struct workqueue_struct *bnx2x_wq; |
129 | 129 | ||
130 | struct bnx2x_mac_vals { | ||
131 | u32 xmac_addr; | ||
132 | u32 xmac_val; | ||
133 | u32 emac_addr; | ||
134 | u32 emac_val; | ||
135 | u32 umac_addr; | ||
136 | u32 umac_val; | ||
137 | u32 bmac_addr; | ||
138 | u32 bmac_val[2]; | ||
139 | }; | ||
140 | |||
130 | enum bnx2x_board_type { | 141 | enum bnx2x_board_type { |
131 | BCM57710 = 0, | 142 | BCM57710 = 0, |
132 | BCM57711, | 143 | BCM57711, |
@@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) | |||
9420 | bnx2x_undi_int_disable_e1h(bp); | 9431 | bnx2x_undi_int_disable_e1h(bp); |
9421 | } | 9432 | } |
9422 | 9433 | ||
9423 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | 9434 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, |
9435 | struct bnx2x_mac_vals *vals) | ||
9424 | { | 9436 | { |
9425 | u32 val, base_addr, offset, mask, reset_reg; | 9437 | u32 val, base_addr, offset, mask, reset_reg; |
9426 | bool mac_stopped = false; | 9438 | bool mac_stopped = false; |
9427 | u8 port = BP_PORT(bp); | 9439 | u8 port = BP_PORT(bp); |
9428 | 9440 | ||
9441 | /* reset addresses as they also mark which values were changed */ | ||
9442 | vals->bmac_addr = 0; | ||
9443 | vals->umac_addr = 0; | ||
9444 | vals->xmac_addr = 0; | ||
9445 | vals->emac_addr = 0; | ||
9446 | |||
9429 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); | 9447 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); |
9430 | 9448 | ||
9431 | if (!CHIP_IS_E3(bp)) { | 9449 | if (!CHIP_IS_E3(bp)) { |
@@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9447 | */ | 9465 | */ |
9448 | wb_data[0] = REG_RD(bp, base_addr + offset); | 9466 | wb_data[0] = REG_RD(bp, base_addr + offset); |
9449 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); | 9467 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); |
9468 | vals->bmac_addr = base_addr + offset; | ||
9469 | vals->bmac_val[0] = wb_data[0]; | ||
9470 | vals->bmac_val[1] = wb_data[1]; | ||
9450 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; | 9471 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; |
9451 | REG_WR(bp, base_addr + offset, wb_data[0]); | 9472 | REG_WR(bp, vals->bmac_addr, wb_data[0]); |
9452 | REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); | 9473 | REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); |
9453 | 9474 | ||
9454 | } | 9475 | } |
9455 | BNX2X_DEV_INFO("Disable emac Rx\n"); | 9476 | BNX2X_DEV_INFO("Disable emac Rx\n"); |
9456 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); | 9477 | vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; |
9457 | 9478 | vals->emac_val = REG_RD(bp, vals->emac_addr); | |
9479 | REG_WR(bp, vals->emac_addr, 0); | ||
9458 | mac_stopped = true; | 9480 | mac_stopped = true; |
9459 | } else { | 9481 | } else { |
9460 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { | 9482 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { |
@@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9465 | val & ~(1 << 1)); | 9487 | val & ~(1 << 1)); |
9466 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, | 9488 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, |
9467 | val | (1 << 1)); | 9489 | val | (1 << 1)); |
9468 | REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); | 9490 | vals->xmac_addr = base_addr + XMAC_REG_CTRL; |
9491 | vals->xmac_val = REG_RD(bp, vals->xmac_addr); | ||
9492 | REG_WR(bp, vals->xmac_addr, 0); | ||
9469 | mac_stopped = true; | 9493 | mac_stopped = true; |
9470 | } | 9494 | } |
9471 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; | 9495 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; |
9472 | if (mask & reset_reg) { | 9496 | if (mask & reset_reg) { |
9473 | BNX2X_DEV_INFO("Disable umac Rx\n"); | 9497 | BNX2X_DEV_INFO("Disable umac Rx\n"); |
9474 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; | 9498 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; |
9475 | REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); | 9499 | vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; |
9500 | vals->umac_val = REG_RD(bp, vals->umac_addr); | ||
9501 | REG_WR(bp, vals->umac_addr, 0); | ||
9476 | mac_stopped = true; | 9502 | mac_stopped = true; |
9477 | } | 9503 | } |
9478 | } | 9504 | } |
@@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9664 | { | 9690 | { |
9665 | u32 reset_reg, tmp_reg = 0, rc; | 9691 | u32 reset_reg, tmp_reg = 0, rc; |
9666 | bool prev_undi = false; | 9692 | bool prev_undi = false; |
9693 | struct bnx2x_mac_vals mac_vals; | ||
9694 | |||
9667 | /* It is possible a previous function received 'common' answer, | 9695 | /* It is possible a previous function received 'common' answer, |
9668 | * but hasn't loaded yet, therefore creating a scenario of | 9696 | * but hasn't loaded yet, therefore creating a scenario of |
9669 | * multiple functions receiving 'common' on the same path. | 9697 | * multiple functions receiving 'common' on the same path. |
9670 | */ | 9698 | */ |
9671 | BNX2X_DEV_INFO("Common unload Flow\n"); | 9699 | BNX2X_DEV_INFO("Common unload Flow\n"); |
9672 | 9700 | ||
9701 | memset(&mac_vals, 0, sizeof(mac_vals)); | ||
9702 | |||
9673 | if (bnx2x_prev_is_path_marked(bp)) | 9703 | if (bnx2x_prev_is_path_marked(bp)) |
9674 | return bnx2x_prev_mcp_done(bp); | 9704 | return bnx2x_prev_mcp_done(bp); |
9675 | 9705 | ||
@@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9680 | u32 timer_count = 1000; | 9710 | u32 timer_count = 1000; |
9681 | 9711 | ||
9682 | /* Close the MAC Rx to prevent BRB from filling up */ | 9712 | /* Close the MAC Rx to prevent BRB from filling up */ |
9683 | bnx2x_prev_unload_close_mac(bp); | 9713 | bnx2x_prev_unload_close_mac(bp, &mac_vals); |
9714 | |||
9715 | /* close LLH filters towards the BRB */ | ||
9716 | bnx2x_set_rx_filter(&bp->link_params, 0); | ||
9684 | 9717 | ||
9685 | /* Check if the UNDI driver was previously loaded | 9718 | /* Check if the UNDI driver was previously loaded |
9686 | * UNDI driver initializes CID offset for normal bell to 0x7 | 9719 | * UNDI driver initializes CID offset for normal bell to 0x7 |
@@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9727 | /* No packets are in the pipeline, path is ready for reset */ | 9760 | /* No packets are in the pipeline, path is ready for reset */ |
9728 | bnx2x_reset_common(bp); | 9761 | bnx2x_reset_common(bp); |
9729 | 9762 | ||
9763 | if (mac_vals.xmac_addr) | ||
9764 | REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); | ||
9765 | if (mac_vals.umac_addr) | ||
9766 | REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); | ||
9767 | if (mac_vals.emac_addr) | ||
9768 | REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); | ||
9769 | if (mac_vals.bmac_addr) { | ||
9770 | REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); | ||
9771 | REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); | ||
9772 | } | ||
9773 | |||
9730 | rc = bnx2x_prev_mark_path(bp, prev_undi); | 9774 | rc = bnx2x_prev_mark_path(bp, prev_undi); |
9731 | if (rc) { | 9775 | if (rc) { |
9732 | bnx2x_prev_mcp_done(bp); | 9776 | bnx2x_prev_mcp_done(bp); |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 3bc1912afba9..4eba17b83ba8 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -190,6 +190,7 @@ struct be_eq_obj { | |||
190 | 190 | ||
191 | u8 idx; /* array index */ | 191 | u8 idx; /* array index */ |
192 | u16 tx_budget; | 192 | u16 tx_budget; |
193 | u16 spurious_intr; | ||
193 | struct napi_struct napi; | 194 | struct napi_struct napi; |
194 | struct be_adapter *adapter; | 195 | struct be_adapter *adapter; |
195 | } ____cacheline_aligned_in_smp; | 196 | } ____cacheline_aligned_in_smp; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9dca22be8125..5c995700e534 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
2026 | struct be_adapter *adapter = eqo->adapter; | 2026 | struct be_adapter *adapter = eqo->adapter; |
2027 | int num_evts = 0; | 2027 | int num_evts = 0; |
2028 | 2028 | ||
2029 | /* On Lancer, clear-intr bit of the EQ DB does not work. | 2029 | /* IRQ is not expected when NAPI is scheduled as the EQ |
2030 | * INTx is de-asserted only on notifying num evts. | 2030 | * will not be armed. |
2031 | * But, this can happen on Lancer INTx where it takes | ||
2032 | * a while to de-assert INTx or in BE2 where occasionaly | ||
2033 | * an interrupt may be raised even when EQ is unarmed. | ||
2034 | * If NAPI is already scheduled, then counting & notifying | ||
2035 | * events will orphan them. | ||
2031 | */ | 2036 | */ |
2032 | if (lancer_chip(adapter)) | 2037 | if (napi_schedule_prep(&eqo->napi)) { |
2033 | num_evts = events_get(eqo); | 2038 | num_evts = events_get(eqo); |
2039 | __napi_schedule(&eqo->napi); | ||
2040 | if (num_evts) | ||
2041 | eqo->spurious_intr = 0; | ||
2042 | } | ||
2043 | be_eq_notify(adapter, eqo->q.id, false, true, num_evts); | ||
2034 | 2044 | ||
2035 | /* The EQ-notify may not de-assert INTx rightaway, causing | 2045 | /* Return IRQ_HANDLED only for the the first spurious intr |
2036 | * the ISR to be invoked again. So, return HANDLED even when | 2046 | * after a valid intr to stop the kernel from branding |
2037 | * num_evts is zero. | 2047 | * this irq as a bad one! |
2038 | */ | 2048 | */ |
2039 | be_eq_notify(adapter, eqo->q.id, false, true, num_evts); | 2049 | if (num_evts || eqo->spurious_intr++ == 0) |
2040 | napi_schedule(&eqo->napi); | 2050 | return IRQ_HANDLED; |
2041 | return IRQ_HANDLED; | 2051 | else |
2052 | return IRQ_NONE; | ||
2042 | } | 2053 | } |
2043 | 2054 | ||
2044 | static irqreturn_t be_msix(int irq, void *dev) | 2055 | static irqreturn_t be_msix(int irq, void *dev) |
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index f80cd975daed..3e73742024b0 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
@@ -4678,7 +4678,7 @@ static int qlge_probe(struct pci_dev *pdev, | |||
4678 | qdev = netdev_priv(ndev); | 4678 | qdev = netdev_priv(ndev); |
4679 | SET_NETDEV_DEV(ndev, &pdev->dev); | 4679 | SET_NETDEV_DEV(ndev, &pdev->dev); |
4680 | ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | | 4680 | ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | |
4681 | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | | 4681 | NETIF_F_TSO | NETIF_F_TSO_ECN | |
4682 | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; | 4682 | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; |
4683 | ndev->features = ndev->hw_features | | 4683 | ndev->features = ndev->hw_features | |
4684 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; | 4684 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; |
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 5778a4ae1164..122d60c0481b 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig | |||
@@ -27,7 +27,7 @@ config XILINX_EMACLITE | |||
27 | 27 | ||
28 | config XILINX_AXI_EMAC | 28 | config XILINX_AXI_EMAC |
29 | tristate "Xilinx 10/100/1000 AXI Ethernet support" | 29 | tristate "Xilinx 10/100/1000 AXI Ethernet support" |
30 | depends on (PPC32 || MICROBLAZE) | 30 | depends on MICROBLAZE |
31 | select PHYLIB | 31 | select PHYLIB |
32 | ---help--- | 32 | ---help--- |
33 | This driver supports the 10/100/1000 Ethernet from Xilinx for the | 33 | This driver supports the 10/100/1000 Ethernet from Xilinx for the |
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index d9f69b82cc4f..6f47100e58d7 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c | |||
@@ -1590,7 +1590,7 @@ static int axienet_of_probe(struct platform_device *op) | |||
1590 | lp->rx_irq = irq_of_parse_and_map(np, 1); | 1590 | lp->rx_irq = irq_of_parse_and_map(np, 1); |
1591 | lp->tx_irq = irq_of_parse_and_map(np, 0); | 1591 | lp->tx_irq = irq_of_parse_and_map(np, 0); |
1592 | of_node_put(np); | 1592 | of_node_put(np); |
1593 | if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { | 1593 | if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) { |
1594 | dev_err(&op->dev, "could not determine irqs\n"); | 1594 | dev_err(&op->dev, "could not determine irqs\n"); |
1595 | ret = -ENOMEM; | 1595 | ret = -ENOMEM; |
1596 | goto err_iounmap_2; | 1596 | goto err_iounmap_2; |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fbd106edbe59..af372d0957fe 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -404,8 +404,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
404 | struct tun_struct *tun; | 404 | struct tun_struct *tun; |
405 | struct net_device *dev; | 405 | struct net_device *dev; |
406 | 406 | ||
407 | tun = rcu_dereference_protected(tfile->tun, | 407 | tun = rtnl_dereference(tfile->tun); |
408 | lockdep_rtnl_is_held()); | 408 | |
409 | if (tun) { | 409 | if (tun) { |
410 | u16 index = tfile->queue_index; | 410 | u16 index = tfile->queue_index; |
411 | BUG_ON(index >= tun->numqueues); | 411 | BUG_ON(index >= tun->numqueues); |
@@ -414,8 +414,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
414 | rcu_assign_pointer(tun->tfiles[index], | 414 | rcu_assign_pointer(tun->tfiles[index], |
415 | tun->tfiles[tun->numqueues - 1]); | 415 | tun->tfiles[tun->numqueues - 1]); |
416 | rcu_assign_pointer(tfile->tun, NULL); | 416 | rcu_assign_pointer(tfile->tun, NULL); |
417 | ntfile = rcu_dereference_protected(tun->tfiles[index], | 417 | ntfile = rtnl_dereference(tun->tfiles[index]); |
418 | lockdep_rtnl_is_held()); | ||
419 | ntfile->queue_index = index; | 418 | ntfile->queue_index = index; |
420 | 419 | ||
421 | --tun->numqueues; | 420 | --tun->numqueues; |
@@ -429,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
429 | /* Drop read queue */ | 428 | /* Drop read queue */ |
430 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 429 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
431 | tun_set_real_num_queues(tun); | 430 | tun_set_real_num_queues(tun); |
432 | } else if (tfile->detached && clean) | 431 | } else if (tfile->detached && clean) { |
433 | tun = tun_enable_queue(tfile); | 432 | tun = tun_enable_queue(tfile); |
433 | sock_put(&tfile->sk); | ||
434 | } | ||
434 | 435 | ||
435 | if (clean) { | 436 | if (clean) { |
436 | if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && | 437 | if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && |
@@ -458,8 +459,7 @@ static void tun_detach_all(struct net_device *dev) | |||
458 | int i, n = tun->numqueues; | 459 | int i, n = tun->numqueues; |
459 | 460 | ||
460 | for (i = 0; i < n; i++) { | 461 | for (i = 0; i < n; i++) { |
461 | tfile = rcu_dereference_protected(tun->tfiles[i], | 462 | tfile = rtnl_dereference(tun->tfiles[i]); |
462 | lockdep_rtnl_is_held()); | ||
463 | BUG_ON(!tfile); | 463 | BUG_ON(!tfile); |
464 | wake_up_all(&tfile->wq.wait); | 464 | wake_up_all(&tfile->wq.wait); |
465 | rcu_assign_pointer(tfile->tun, NULL); | 465 | rcu_assign_pointer(tfile->tun, NULL); |
@@ -469,8 +469,7 @@ static void tun_detach_all(struct net_device *dev) | |||
469 | 469 | ||
470 | synchronize_net(); | 470 | synchronize_net(); |
471 | for (i = 0; i < n; i++) { | 471 | for (i = 0; i < n; i++) { |
472 | tfile = rcu_dereference_protected(tun->tfiles[i], | 472 | tfile = rtnl_dereference(tun->tfiles[i]); |
473 | lockdep_rtnl_is_held()); | ||
474 | /* Drop read queue */ | 473 | /* Drop read queue */ |
475 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 474 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
476 | sock_put(&tfile->sk); | 475 | sock_put(&tfile->sk); |
@@ -481,6 +480,9 @@ static void tun_detach_all(struct net_device *dev) | |||
481 | sock_put(&tfile->sk); | 480 | sock_put(&tfile->sk); |
482 | } | 481 | } |
483 | BUG_ON(tun->numdisabled != 0); | 482 | BUG_ON(tun->numdisabled != 0); |
483 | |||
484 | if (tun->flags & TUN_PERSIST) | ||
485 | module_put(THIS_MODULE); | ||
484 | } | 486 | } |
485 | 487 | ||
486 | static int tun_attach(struct tun_struct *tun, struct file *file) | 488 | static int tun_attach(struct tun_struct *tun, struct file *file) |
@@ -489,7 +491,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file) | |||
489 | int err; | 491 | int err; |
490 | 492 | ||
491 | err = -EINVAL; | 493 | err = -EINVAL; |
492 | if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held())) | 494 | if (rtnl_dereference(tfile->tun)) |
493 | goto out; | 495 | goto out; |
494 | 496 | ||
495 | err = -EBUSY; | 497 | err = -EBUSY; |
@@ -1544,6 +1546,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1544 | struct net_device *dev; | 1546 | struct net_device *dev; |
1545 | int err; | 1547 | int err; |
1546 | 1548 | ||
1549 | if (tfile->detached) | ||
1550 | return -EINVAL; | ||
1551 | |||
1547 | dev = __dev_get_by_name(net, ifr->ifr_name); | 1552 | dev = __dev_get_by_name(net, ifr->ifr_name); |
1548 | if (dev) { | 1553 | if (dev) { |
1549 | if (ifr->ifr_flags & IFF_TUN_EXCL) | 1554 | if (ifr->ifr_flags & IFF_TUN_EXCL) |
@@ -1738,8 +1743,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n) | |||
1738 | struct tun_file *tfile; | 1743 | struct tun_file *tfile; |
1739 | 1744 | ||
1740 | for (i = 0; i < n; i++) { | 1745 | for (i = 0; i < n; i++) { |
1741 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1746 | tfile = rtnl_dereference(tun->tfiles[i]); |
1742 | lockdep_rtnl_is_held()); | ||
1743 | sk_detach_filter(tfile->socket.sk); | 1747 | sk_detach_filter(tfile->socket.sk); |
1744 | } | 1748 | } |
1745 | 1749 | ||
@@ -1752,8 +1756,7 @@ static int tun_attach_filter(struct tun_struct *tun) | |||
1752 | struct tun_file *tfile; | 1756 | struct tun_file *tfile; |
1753 | 1757 | ||
1754 | for (i = 0; i < tun->numqueues; i++) { | 1758 | for (i = 0; i < tun->numqueues; i++) { |
1755 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1759 | tfile = rtnl_dereference(tun->tfiles[i]); |
1756 | lockdep_rtnl_is_held()); | ||
1757 | ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); | 1760 | ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); |
1758 | if (ret) { | 1761 | if (ret) { |
1759 | tun_detach_filter(tun, i); | 1762 | tun_detach_filter(tun, i); |
@@ -1771,8 +1774,7 @@ static void tun_set_sndbuf(struct tun_struct *tun) | |||
1771 | int i; | 1774 | int i; |
1772 | 1775 | ||
1773 | for (i = 0; i < tun->numqueues; i++) { | 1776 | for (i = 0; i < tun->numqueues; i++) { |
1774 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1777 | tfile = rtnl_dereference(tun->tfiles[i]); |
1775 | lockdep_rtnl_is_held()); | ||
1776 | tfile->socket.sk->sk_sndbuf = tun->sndbuf; | 1778 | tfile->socket.sk->sk_sndbuf = tun->sndbuf; |
1777 | } | 1779 | } |
1778 | } | 1780 | } |
@@ -1789,13 +1791,10 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) | |||
1789 | tun = tfile->detached; | 1791 | tun = tfile->detached; |
1790 | if (!tun) | 1792 | if (!tun) |
1791 | ret = -EINVAL; | 1793 | ret = -EINVAL; |
1792 | else if (tun_not_capable(tun)) | ||
1793 | ret = -EPERM; | ||
1794 | else | 1794 | else |
1795 | ret = tun_attach(tun, file); | 1795 | ret = tun_attach(tun, file); |
1796 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { | 1796 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { |
1797 | tun = rcu_dereference_protected(tfile->tun, | 1797 | tun = rtnl_dereference(tfile->tun); |
1798 | lockdep_rtnl_is_held()); | ||
1799 | if (!tun || !(tun->flags & TUN_TAP_MQ)) | 1798 | if (!tun || !(tun->flags & TUN_TAP_MQ)) |
1800 | ret = -EINVAL; | 1799 | ret = -EINVAL; |
1801 | else | 1800 | else |
@@ -1880,10 +1879,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1880 | /* Disable/Enable persist mode. Keep an extra reference to the | 1879 | /* Disable/Enable persist mode. Keep an extra reference to the |
1881 | * module to prevent the module being unprobed. | 1880 | * module to prevent the module being unprobed. |
1882 | */ | 1881 | */ |
1883 | if (arg) { | 1882 | if (arg && !(tun->flags & TUN_PERSIST)) { |
1884 | tun->flags |= TUN_PERSIST; | 1883 | tun->flags |= TUN_PERSIST; |
1885 | __module_get(THIS_MODULE); | 1884 | __module_get(THIS_MODULE); |
1886 | } else { | 1885 | } |
1886 | if (!arg && (tun->flags & TUN_PERSIST)) { | ||
1887 | tun->flags &= ~TUN_PERSIST; | 1887 | tun->flags &= ~TUN_PERSIST; |
1888 | module_put(THIS_MODULE); | 1888 | module_put(THIS_MODULE); |
1889 | } | 1889 | } |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 1a67a4f829fe..2c02b4e84094 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -30,5 +30,6 @@ source "drivers/net/wireless/ath/ath9k/Kconfig" | |||
30 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" | 31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" |
32 | source "drivers/net/wireless/ath/ar5523/Kconfig" | 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" |
33 | source "drivers/net/wireless/ath/wil6210/Kconfig" | ||
33 | 34 | ||
34 | endif | 35 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 1e18621326dc..97b964ded2be 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATH9K_HW) += ath9k/ | |||
3 | obj-$(CONFIG_CARL9170) += carl9170/ | 3 | obj-$(CONFIG_CARL9170) += carl9170/ |
4 | obj-$(CONFIG_ATH6KL) += ath6kl/ | 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ |
5 | obj-$(CONFIG_AR5523) += ar5523/ | 5 | obj-$(CONFIG_AR5523) += ar5523/ |
6 | obj-$(CONFIG_WIL6210) += wil6210/ | ||
6 | 7 | ||
7 | obj-$(CONFIG_ATH_COMMON) += ath.o | 8 | obj-$(CONFIG_ATH_COMMON) += ath.o |
8 | 9 | ||
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig new file mode 100644 index 000000000000..bac3d98a0cfb --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Kconfig | |||
@@ -0,0 +1,29 @@ | |||
1 | config WIL6210 | ||
2 | tristate "Wilocity 60g WiFi card wil6210 support" | ||
3 | depends on CFG80211 | ||
4 | depends on PCI | ||
5 | default n | ||
6 | ---help--- | ||
7 | This module adds support for wireless adapter based on | ||
8 | wil6210 chip by Wilocity. It supports operation on the | ||
9 | 60 GHz band, covered by the IEEE802.11ad standard. | ||
10 | |||
11 | http://wireless.kernel.org/en/users/Drivers/wil6210 | ||
12 | |||
13 | If you choose to build it as a module, it will be called | ||
14 | wil6210 | ||
15 | |||
16 | config WIL6210_ISR_COR | ||
17 | bool "Use Clear-On-Read mode for ISR registers for wil6210" | ||
18 | depends on WIL6210 | ||
19 | default y | ||
20 | ---help--- | ||
21 | ISR registers on wil6210 chip may operate in either | ||
22 | COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. | ||
23 | For production code, use COR (say y); is default since | ||
24 | it saves extra target transaction; | ||
25 | For ISR debug, use W1C (say n); is allows to monitor ISR | ||
26 | registers with debugfs. If COR were used, ISR would | ||
27 | self-clear when accessed for debug purposes, it makes | ||
28 | such monitoring impossible. | ||
29 | Say y unless you debug interrupts | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile new file mode 100644 index 000000000000..9396dc9fe3c5 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | obj-$(CONFIG_WIL6210) += wil6210.o | ||
2 | |||
3 | wil6210-objs := main.o | ||
4 | wil6210-objs += netdev.o | ||
5 | wil6210-objs += cfg80211.o | ||
6 | wil6210-objs += pcie_bus.o | ||
7 | wil6210-objs += debugfs.o | ||
8 | wil6210-objs += wmi.o | ||
9 | wil6210-objs += interrupt.o | ||
10 | wil6210-objs += txrx.o | ||
11 | |||
12 | subdir-ccflags-y += -Werror | ||
13 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c new file mode 100644 index 000000000000..116f4e807ae1 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/ieee80211.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <net/cfg80211.h> | ||
26 | |||
27 | #include "wil6210.h" | ||
28 | #include "wmi.h" | ||
29 | |||
30 | #define CHAN60G(_channel, _flags) { \ | ||
31 | .band = IEEE80211_BAND_60GHZ, \ | ||
32 | .center_freq = 56160 + (2160 * (_channel)), \ | ||
33 | .hw_value = (_channel), \ | ||
34 | .flags = (_flags), \ | ||
35 | .max_antenna_gain = 0, \ | ||
36 | .max_power = 40, \ | ||
37 | } | ||
38 | |||
39 | static struct ieee80211_channel wil_60ghz_channels[] = { | ||
40 | CHAN60G(1, 0), | ||
41 | CHAN60G(2, 0), | ||
42 | CHAN60G(3, 0), | ||
43 | /* channel 4 not supported yet */ | ||
44 | }; | ||
45 | |||
46 | static struct ieee80211_supported_band wil_band_60ghz = { | ||
47 | .channels = wil_60ghz_channels, | ||
48 | .n_channels = ARRAY_SIZE(wil_60ghz_channels), | ||
49 | .ht_cap = { | ||
50 | .ht_supported = true, | ||
51 | .cap = 0, /* TODO */ | ||
52 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ | ||
53 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ | ||
54 | .mcs = { | ||
55 | /* MCS 1..12 - SC PHY */ | ||
56 | .rx_mask = {0xfe, 0x1f}, /* 1..12 */ | ||
57 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ | ||
58 | }, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static const struct ieee80211_txrx_stypes | ||
63 | wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
64 | [NL80211_IFTYPE_STATION] = { | ||
65 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
66 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
67 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
68 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
69 | }, | ||
70 | [NL80211_IFTYPE_AP] = { | ||
71 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
72 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
73 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
74 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
75 | }, | ||
76 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
77 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
78 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
79 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
80 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
81 | }, | ||
82 | [NL80211_IFTYPE_P2P_GO] = { | ||
83 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
84 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
85 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
86 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | static const u32 wil_cipher_suites[] = { | ||
91 | WLAN_CIPHER_SUITE_GCMP, | ||
92 | }; | ||
93 | |||
94 | int wil_iftype_nl2wmi(enum nl80211_iftype type) | ||
95 | { | ||
96 | static const struct { | ||
97 | enum nl80211_iftype nl; | ||
98 | enum wmi_network_type wmi; | ||
99 | } __nl2wmi[] = { | ||
100 | {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, | ||
101 | {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, | ||
102 | {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, | ||
103 | {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, | ||
104 | {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, | ||
105 | {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ | ||
106 | }; | ||
107 | uint i; | ||
108 | |||
109 | for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { | ||
110 | if (__nl2wmi[i].nl == type) | ||
111 | return __nl2wmi[i].wmi; | ||
112 | } | ||
113 | |||
114 | return -EOPNOTSUPP; | ||
115 | } | ||
116 | |||
117 | static int wil_cfg80211_get_station(struct wiphy *wiphy, | ||
118 | struct net_device *ndev, | ||
119 | u8 *mac, struct station_info *sinfo) | ||
120 | { | ||
121 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
122 | int rc; | ||
123 | struct wmi_notify_req_cmd cmd = { | ||
124 | .cid = 0, | ||
125 | .interval_usec = 0, | ||
126 | }; | ||
127 | |||
128 | if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) | ||
129 | return -ENOENT; | ||
130 | |||
131 | /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ | ||
132 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), | ||
133 | WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); | ||
134 | if (rc) | ||
135 | return rc; | ||
136 | |||
137 | sinfo->generation = wil->sinfo_gen; | ||
138 | |||
139 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
140 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
141 | sinfo->txrate.mcs = wil->stats.bf_mcs; | ||
142 | sinfo->filled |= STATION_INFO_RX_BITRATE; | ||
143 | sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
144 | sinfo->rxrate.mcs = wil->stats.last_mcs_rx; | ||
145 | |||
146 | if (test_bit(wil_status_fwconnected, &wil->status)) { | ||
147 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
148 | sinfo->signal = 12; /* TODO: provide real value */ | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, | ||
155 | struct net_device *ndev, | ||
156 | enum nl80211_iftype type, u32 *flags, | ||
157 | struct vif_params *params) | ||
158 | { | ||
159 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
160 | struct wireless_dev *wdev = wil->wdev; | ||
161 | |||
162 | switch (type) { | ||
163 | case NL80211_IFTYPE_STATION: | ||
164 | case NL80211_IFTYPE_AP: | ||
165 | case NL80211_IFTYPE_P2P_CLIENT: | ||
166 | case NL80211_IFTYPE_P2P_GO: | ||
167 | break; | ||
168 | case NL80211_IFTYPE_MONITOR: | ||
169 | if (flags) | ||
170 | wil->monitor_flags = *flags; | ||
171 | else | ||
172 | wil->monitor_flags = 0; | ||
173 | |||
174 | break; | ||
175 | default: | ||
176 | return -EOPNOTSUPP; | ||
177 | } | ||
178 | |||
179 | wdev->iftype = type; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int wil_cfg80211_scan(struct wiphy *wiphy, | ||
185 | struct cfg80211_scan_request *request) | ||
186 | { | ||
187 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
188 | struct wireless_dev *wdev = wil->wdev; | ||
189 | struct { | ||
190 | struct wmi_start_scan_cmd cmd; | ||
191 | u16 chnl[4]; | ||
192 | } __packed cmd; | ||
193 | uint i, n; | ||
194 | |||
195 | if (wil->scan_request) { | ||
196 | wil_err(wil, "Already scanning\n"); | ||
197 | return -EAGAIN; | ||
198 | } | ||
199 | |||
200 | /* check we are client side */ | ||
201 | switch (wdev->iftype) { | ||
202 | case NL80211_IFTYPE_STATION: | ||
203 | case NL80211_IFTYPE_P2P_CLIENT: | ||
204 | break; | ||
205 | default: | ||
206 | return -EOPNOTSUPP; | ||
207 | |||
208 | } | ||
209 | |||
210 | /* FW don't support scan after connection attempt */ | ||
211 | if (test_bit(wil_status_dontscan, &wil->status)) { | ||
212 | wil_err(wil, "Scan after connect attempt not supported\n"); | ||
213 | return -EBUSY; | ||
214 | } | ||
215 | |||
216 | wil->scan_request = request; | ||
217 | |||
218 | memset(&cmd, 0, sizeof(cmd)); | ||
219 | cmd.cmd.num_channels = 0; | ||
220 | n = min(request->n_channels, 4U); | ||
221 | for (i = 0; i < n; i++) { | ||
222 | int ch = request->channels[i]->hw_value; | ||
223 | if (ch == 0) { | ||
224 | wil_err(wil, | ||
225 | "Scan requested for unknown frequency %dMhz\n", | ||
226 | request->channels[i]->center_freq); | ||
227 | continue; | ||
228 | } | ||
229 | /* 0-based channel indexes */ | ||
230 | cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; | ||
231 | wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, | ||
232 | request->channels[i]->center_freq); | ||
233 | } | ||
234 | |||
235 | return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | ||
236 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | ||
237 | } | ||
238 | |||
239 | static int wil_cfg80211_connect(struct wiphy *wiphy, | ||
240 | struct net_device *ndev, | ||
241 | struct cfg80211_connect_params *sme) | ||
242 | { | ||
243 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
244 | struct cfg80211_bss *bss; | ||
245 | struct wmi_connect_cmd conn; | ||
246 | const u8 *ssid_eid; | ||
247 | const u8 *rsn_eid; | ||
248 | int ch; | ||
249 | int rc = 0; | ||
250 | |||
251 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | ||
252 | sme->ssid, sme->ssid_len, | ||
253 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
254 | if (!bss) { | ||
255 | wil_err(wil, "Unable to find BSS\n"); | ||
256 | return -ENOENT; | ||
257 | } | ||
258 | |||
259 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); | ||
260 | if (!ssid_eid) { | ||
261 | wil_err(wil, "No SSID\n"); | ||
262 | rc = -ENOENT; | ||
263 | goto out; | ||
264 | } | ||
265 | |||
266 | rsn_eid = sme->ie ? | ||
267 | cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : | ||
268 | NULL; | ||
269 | if (rsn_eid) { | ||
270 | if (sme->ie_len > WMI_MAX_IE_LEN) { | ||
271 | rc = -ERANGE; | ||
272 | wil_err(wil, "IE too large (%td bytes)\n", | ||
273 | sme->ie_len); | ||
274 | goto out; | ||
275 | } | ||
276 | /* | ||
277 | * For secure assoc, send: | ||
278 | * (1) WMI_DELETE_CIPHER_KEY_CMD | ||
279 | * (2) WMI_SET_APPIE_CMD | ||
280 | */ | ||
281 | rc = wmi_del_cipher_key(wil, 0, bss->bssid); | ||
282 | if (rc) { | ||
283 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); | ||
284 | goto out; | ||
285 | } | ||
286 | /* WMI_SET_APPIE_CMD */ | ||
287 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | ||
288 | if (rc) { | ||
289 | wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); | ||
290 | goto out; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* WMI_CONNECT_CMD */ | ||
295 | memset(&conn, 0, sizeof(conn)); | ||
296 | switch (bss->capability & 0x03) { | ||
297 | case WLAN_CAPABILITY_DMG_TYPE_AP: | ||
298 | conn.network_type = WMI_NETTYPE_INFRA; | ||
299 | break; | ||
300 | case WLAN_CAPABILITY_DMG_TYPE_PBSS: | ||
301 | conn.network_type = WMI_NETTYPE_P2P; | ||
302 | break; | ||
303 | default: | ||
304 | wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", | ||
305 | bss->capability); | ||
306 | goto out; | ||
307 | } | ||
308 | if (rsn_eid) { | ||
309 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; | ||
310 | conn.auth_mode = WMI_AUTH_WPA2_PSK; | ||
311 | conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; | ||
312 | conn.pairwise_crypto_len = 16; | ||
313 | } else { | ||
314 | conn.dot11_auth_mode = WMI_AUTH11_OPEN; | ||
315 | conn.auth_mode = WMI_AUTH_NONE; | ||
316 | } | ||
317 | |||
318 | conn.ssid_len = min_t(u8, ssid_eid[1], 32); | ||
319 | memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); | ||
320 | |||
321 | ch = bss->channel->hw_value; | ||
322 | if (ch == 0) { | ||
323 | wil_err(wil, "BSS at unknown frequency %dMhz\n", | ||
324 | bss->channel->center_freq); | ||
325 | rc = -EOPNOTSUPP; | ||
326 | goto out; | ||
327 | } | ||
328 | conn.channel = ch - 1; | ||
329 | |||
330 | memcpy(conn.bssid, bss->bssid, 6); | ||
331 | memcpy(conn.dst_mac, bss->bssid, 6); | ||
332 | /* | ||
333 | * FW don't support scan after connection attempt | ||
334 | */ | ||
335 | set_bit(wil_status_dontscan, &wil->status); | ||
336 | |||
337 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | ||
338 | if (rc == 0) { | ||
339 | /* Connect can take lots of time */ | ||
340 | mod_timer(&wil->connect_timer, | ||
341 | jiffies + msecs_to_jiffies(2000)); | ||
342 | } | ||
343 | |||
344 | out: | ||
345 | cfg80211_put_bss(bss); | ||
346 | |||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | static int wil_cfg80211_disconnect(struct wiphy *wiphy, | ||
351 | struct net_device *ndev, | ||
352 | u16 reason_code) | ||
353 | { | ||
354 | int rc; | ||
355 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
356 | |||
357 | rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | ||
358 | |||
359 | return rc; | ||
360 | } | ||
361 | |||
362 | static int wil_cfg80211_set_channel(struct wiphy *wiphy, | ||
363 | struct cfg80211_chan_def *chandef) | ||
364 | { | ||
365 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
366 | struct wireless_dev *wdev = wil->wdev; | ||
367 | |||
368 | wdev->preset_chandef = *chandef; | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int wil_cfg80211_add_key(struct wiphy *wiphy, | ||
374 | struct net_device *ndev, | ||
375 | u8 key_index, bool pairwise, | ||
376 | const u8 *mac_addr, | ||
377 | struct key_params *params) | ||
378 | { | ||
379 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
380 | |||
381 | /* group key is not used */ | ||
382 | if (!pairwise) | ||
383 | return 0; | ||
384 | |||
385 | return wmi_add_cipher_key(wil, key_index, mac_addr, | ||
386 | params->key_len, params->key); | ||
387 | } | ||
388 | |||
389 | static int wil_cfg80211_del_key(struct wiphy *wiphy, | ||
390 | struct net_device *ndev, | ||
391 | u8 key_index, bool pairwise, | ||
392 | const u8 *mac_addr) | ||
393 | { | ||
394 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
395 | |||
396 | /* group key is not used */ | ||
397 | if (!pairwise) | ||
398 | return 0; | ||
399 | |||
400 | return wmi_del_cipher_key(wil, key_index, mac_addr); | ||
401 | } | ||
402 | |||
403 | /* Need to be present or wiphy_new() will WARN */ | ||
404 | static int wil_cfg80211_set_default_key(struct wiphy *wiphy, | ||
405 | struct net_device *ndev, | ||
406 | u8 key_index, bool unicast, | ||
407 | bool multicast) | ||
408 | { | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int wil_cfg80211_start_ap(struct wiphy *wiphy, | ||
413 | struct net_device *ndev, | ||
414 | struct cfg80211_ap_settings *info) | ||
415 | { | ||
416 | int rc = 0; | ||
417 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
418 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
419 | struct ieee80211_channel *channel = info->chandef.chan; | ||
420 | struct cfg80211_beacon_data *bcon = &info->beacon; | ||
421 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
422 | |||
423 | if (!channel) { | ||
424 | wil_err(wil, "AP: No channel???\n"); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, | ||
429 | channel->center_freq, info->privacy ? "secure" : "open"); | ||
430 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, | ||
431 | info->ssid, info->ssid_len); | ||
432 | |||
433 | rc = wil_reset(wil); | ||
434 | if (rc) | ||
435 | return rc; | ||
436 | |||
437 | rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); | ||
438 | if (rc) | ||
439 | return rc; | ||
440 | |||
441 | rc = wmi_set_channel(wil, channel->hw_value); | ||
442 | if (rc) | ||
443 | return rc; | ||
444 | |||
445 | /* MAC address - pre-requisite for other commands */ | ||
446 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
447 | |||
448 | /* IE's */ | ||
449 | /* bcon 'head IE's are not relevant for 60g band */ | ||
450 | wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | ||
451 | bcon->beacon_ies); | ||
452 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | ||
453 | bcon->proberesp_ies); | ||
454 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | ||
455 | bcon->assocresp_ies); | ||
456 | |||
457 | wil->secure_pcp = info->privacy; | ||
458 | |||
459 | rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); | ||
460 | if (rc) | ||
461 | return rc; | ||
462 | |||
463 | /* Rx VRING. After MAC and beacon */ | ||
464 | rc = wil_rx_init(wil); | ||
465 | |||
466 | netif_carrier_on(ndev); | ||
467 | |||
468 | return rc; | ||
469 | } | ||
470 | |||
471 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | ||
472 | struct net_device *ndev) | ||
473 | { | ||
474 | int rc = 0; | ||
475 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
476 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
477 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
478 | |||
479 | /* To stop beaconing, set BI to 0 */ | ||
480 | rc = wmi_set_bcon(wil, 0, wmi_nettype); | ||
481 | |||
482 | return rc; | ||
483 | } | ||
484 | |||
485 | static struct cfg80211_ops wil_cfg80211_ops = { | ||
486 | .scan = wil_cfg80211_scan, | ||
487 | .connect = wil_cfg80211_connect, | ||
488 | .disconnect = wil_cfg80211_disconnect, | ||
489 | .change_virtual_intf = wil_cfg80211_change_iface, | ||
490 | .get_station = wil_cfg80211_get_station, | ||
491 | .set_monitor_channel = wil_cfg80211_set_channel, | ||
492 | .add_key = wil_cfg80211_add_key, | ||
493 | .del_key = wil_cfg80211_del_key, | ||
494 | .set_default_key = wil_cfg80211_set_default_key, | ||
495 | /* AP mode */ | ||
496 | .start_ap = wil_cfg80211_start_ap, | ||
497 | .stop_ap = wil_cfg80211_stop_ap, | ||
498 | }; | ||
499 | |||
500 | static void wil_wiphy_init(struct wiphy *wiphy) | ||
501 | { | ||
502 | /* TODO: set real value */ | ||
503 | wiphy->max_scan_ssids = 10; | ||
504 | wiphy->max_num_pmkids = 0 /* TODO: */; | ||
505 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
506 | BIT(NL80211_IFTYPE_AP) | | ||
507 | BIT(NL80211_IFTYPE_MONITOR); | ||
508 | /* TODO: enable P2P when integrated with supplicant: | ||
509 | * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | ||
510 | */ | ||
511 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | ||
512 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
513 | dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", | ||
514 | __func__, wiphy->flags); | ||
515 | wiphy->probe_resp_offload = | ||
516 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
517 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
518 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | ||
519 | |||
520 | wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; | ||
521 | |||
522 | /* TODO: figure this out */ | ||
523 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
524 | |||
525 | wiphy->cipher_suites = wil_cipher_suites; | ||
526 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); | ||
527 | wiphy->mgmt_stypes = wil_mgmt_stypes; | ||
528 | } | ||
529 | |||
530 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | ||
531 | { | ||
532 | int rc = 0; | ||
533 | struct wireless_dev *wdev; | ||
534 | |||
535 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
536 | if (!wdev) | ||
537 | return ERR_PTR(-ENOMEM); | ||
538 | |||
539 | wdev->wiphy = wiphy_new(&wil_cfg80211_ops, | ||
540 | sizeof(struct wil6210_priv)); | ||
541 | if (!wdev->wiphy) { | ||
542 | rc = -ENOMEM; | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | set_wiphy_dev(wdev->wiphy, dev); | ||
547 | wil_wiphy_init(wdev->wiphy); | ||
548 | |||
549 | rc = wiphy_register(wdev->wiphy); | ||
550 | if (rc < 0) | ||
551 | goto out_failed_reg; | ||
552 | |||
553 | return wdev; | ||
554 | |||
555 | out_failed_reg: | ||
556 | wiphy_free(wdev->wiphy); | ||
557 | out: | ||
558 | kfree(wdev); | ||
559 | |||
560 | return ERR_PTR(rc); | ||
561 | } | ||
562 | |||
563 | void wil_wdev_free(struct wil6210_priv *wil) | ||
564 | { | ||
565 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
566 | |||
567 | if (!wdev) | ||
568 | return; | ||
569 | |||
570 | wiphy_unregister(wdev->wiphy); | ||
571 | wiphy_free(wdev->wiphy); | ||
572 | kfree(wdev); | ||
573 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h new file mode 100644 index 000000000000..6a315ba5aa7d --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef WIL_DBG_HEXDUMP_H_ | ||
2 | #define WIL_DBG_HEXDUMP_H_ | ||
3 | |||
4 | #if defined(CONFIG_DYNAMIC_DEBUG) | ||
5 | #define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
6 | groupsize, buf, len, ascii) \ | ||
7 | do { \ | ||
8 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ | ||
9 | __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ | ||
10 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ | ||
11 | print_hex_dump(KERN_DEBUG, prefix_str, \ | ||
12 | prefix_type, rowsize, groupsize, \ | ||
13 | buf, len, ascii); \ | ||
14 | } while (0) | ||
15 | |||
16 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
17 | groupsize, buf, len, ascii) \ | ||
18 | wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
19 | groupsize, buf, len, ascii) | ||
20 | |||
21 | #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ | ||
22 | wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) | ||
23 | #else /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
24 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
25 | groupsize, buf, len, ascii) \ | ||
26 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ | ||
27 | groupsize, buf, len, ascii) | ||
28 | #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
29 | |||
30 | #endif /* WIL_DBG_HEXDUMP_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c new file mode 100644 index 000000000000..65fc9683bfd8 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -0,0 +1,603 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/rtnetlink.h> | ||
22 | |||
23 | #include "wil6210.h" | ||
24 | #include "txrx.h" | ||
25 | |||
26 | /* Nasty hack. Better have per device instances */ | ||
27 | static u32 mem_addr; | ||
28 | static u32 dbg_txdesc_index; | ||
29 | |||
30 | static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | ||
31 | const char *name, struct vring *vring) | ||
32 | { | ||
33 | void __iomem *x = wmi_addr(wil, vring->hwtail); | ||
34 | |||
35 | seq_printf(s, "VRING %s = {\n", name); | ||
36 | seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); | ||
37 | seq_printf(s, " va = 0x%p\n", vring->va); | ||
38 | seq_printf(s, " size = %d\n", vring->size); | ||
39 | seq_printf(s, " swtail = %d\n", vring->swtail); | ||
40 | seq_printf(s, " swhead = %d\n", vring->swhead); | ||
41 | seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); | ||
42 | if (x) | ||
43 | seq_printf(s, "0x%08x\n", ioread32(x)); | ||
44 | else | ||
45 | seq_printf(s, "???\n"); | ||
46 | |||
47 | if (vring->va && (vring->size < 1025)) { | ||
48 | uint i; | ||
49 | for (i = 0; i < vring->size; i++) { | ||
50 | volatile struct vring_tx_desc *d = &vring->va[i].tx; | ||
51 | if ((i % 64) == 0 && (i != 0)) | ||
52 | seq_printf(s, "\n"); | ||
53 | seq_printf(s, "%s", (d->dma.status & BIT(0)) ? | ||
54 | "S" : (vring->ctx[i] ? "H" : "h")); | ||
55 | } | ||
56 | seq_printf(s, "\n"); | ||
57 | } | ||
58 | seq_printf(s, "}\n"); | ||
59 | } | ||
60 | |||
61 | static int wil_vring_debugfs_show(struct seq_file *s, void *data) | ||
62 | { | ||
63 | uint i; | ||
64 | struct wil6210_priv *wil = s->private; | ||
65 | |||
66 | wil_print_vring(s, wil, "rx", &wil->vring_rx); | ||
67 | |||
68 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
69 | struct vring *vring = &(wil->vring_tx[i]); | ||
70 | if (vring->va) { | ||
71 | char name[10]; | ||
72 | snprintf(name, sizeof(name), "tx_%2d", i); | ||
73 | wil_print_vring(s, wil, name, vring); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int wil_vring_seq_open(struct inode *inode, struct file *file) | ||
81 | { | ||
82 | return single_open(file, wil_vring_debugfs_show, inode->i_private); | ||
83 | } | ||
84 | |||
85 | static const struct file_operations fops_vring = { | ||
86 | .open = wil_vring_seq_open, | ||
87 | .release = single_release, | ||
88 | .read = seq_read, | ||
89 | .llseek = seq_lseek, | ||
90 | }; | ||
91 | |||
92 | static void wil_print_ring(struct seq_file *s, const char *prefix, | ||
93 | void __iomem *off) | ||
94 | { | ||
95 | struct wil6210_priv *wil = s->private; | ||
96 | struct wil6210_mbox_ring r; | ||
97 | int rsize; | ||
98 | uint i; | ||
99 | |||
100 | wil_memcpy_fromio_32(&r, off, sizeof(r)); | ||
101 | wil_mbox_ring_le2cpus(&r); | ||
102 | /* | ||
103 | * we just read memory block from NIC. This memory may be | ||
104 | * garbage. Check validity before using it. | ||
105 | */ | ||
106 | rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); | ||
107 | |||
108 | seq_printf(s, "ring %s = {\n", prefix); | ||
109 | seq_printf(s, " base = 0x%08x\n", r.base); | ||
110 | seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); | ||
111 | seq_printf(s, " tail = 0x%08x\n", r.tail); | ||
112 | seq_printf(s, " head = 0x%08x\n", r.head); | ||
113 | seq_printf(s, " entry size = %d\n", r.entry_size); | ||
114 | |||
115 | if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { | ||
116 | seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", | ||
117 | sizeof(struct wil6210_mbox_ring_desc)); | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | if (!wmi_addr(wil, r.base) || | ||
122 | !wmi_addr(wil, r.tail) || | ||
123 | !wmi_addr(wil, r.head)) { | ||
124 | seq_printf(s, " ??? pointers are garbage?\n"); | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | for (i = 0; i < rsize; i++) { | ||
129 | struct wil6210_mbox_ring_desc d; | ||
130 | struct wil6210_mbox_hdr hdr; | ||
131 | size_t delta = i * sizeof(d); | ||
132 | void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; | ||
133 | |||
134 | wil_memcpy_fromio_32(&d, x, sizeof(d)); | ||
135 | |||
136 | seq_printf(s, " [%2x] %s %s%s 0x%08x", i, | ||
137 | d.sync ? "F" : "E", | ||
138 | (r.tail - r.base == delta) ? "t" : " ", | ||
139 | (r.head - r.base == delta) ? "h" : " ", | ||
140 | le32_to_cpu(d.addr)); | ||
141 | if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { | ||
142 | u16 len = le16_to_cpu(hdr.len); | ||
143 | seq_printf(s, " -> %04x %04x %04x %02x\n", | ||
144 | le16_to_cpu(hdr.seq), len, | ||
145 | le16_to_cpu(hdr.type), hdr.flags); | ||
146 | if (len <= MAX_MBOXITEM_SIZE) { | ||
147 | int n = 0; | ||
148 | unsigned char printbuf[16 * 3 + 2]; | ||
149 | unsigned char databuf[MAX_MBOXITEM_SIZE]; | ||
150 | void __iomem *src = wmi_buffer(wil, d.addr) + | ||
151 | sizeof(struct wil6210_mbox_hdr); | ||
152 | /* | ||
153 | * No need to check @src for validity - | ||
154 | * we already validated @d.addr while | ||
155 | * reading header | ||
156 | */ | ||
157 | wil_memcpy_fromio_32(databuf, src, len); | ||
158 | while (n < len) { | ||
159 | int l = min(len - n, 16); | ||
160 | hex_dump_to_buffer(databuf + n, l, | ||
161 | 16, 1, printbuf, | ||
162 | sizeof(printbuf), | ||
163 | false); | ||
164 | seq_printf(s, " : %s\n", printbuf); | ||
165 | n += l; | ||
166 | } | ||
167 | } | ||
168 | } else { | ||
169 | seq_printf(s, "\n"); | ||
170 | } | ||
171 | } | ||
172 | out: | ||
173 | seq_printf(s, "}\n"); | ||
174 | } | ||
175 | |||
176 | static int wil_mbox_debugfs_show(struct seq_file *s, void *data) | ||
177 | { | ||
178 | struct wil6210_priv *wil = s->private; | ||
179 | |||
180 | wil_print_ring(s, "tx", wil->csr + HOST_MBOX + | ||
181 | offsetof(struct wil6210_mbox_ctl, tx)); | ||
182 | wil_print_ring(s, "rx", wil->csr + HOST_MBOX + | ||
183 | offsetof(struct wil6210_mbox_ctl, rx)); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int wil_mbox_seq_open(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | return single_open(file, wil_mbox_debugfs_show, inode->i_private); | ||
191 | } | ||
192 | |||
193 | static const struct file_operations fops_mbox = { | ||
194 | .open = wil_mbox_seq_open, | ||
195 | .release = single_release, | ||
196 | .read = seq_read, | ||
197 | .llseek = seq_lseek, | ||
198 | }; | ||
199 | |||
200 | static int wil_debugfs_iomem_x32_set(void *data, u64 val) | ||
201 | { | ||
202 | iowrite32(val, (void __iomem *)data); | ||
203 | wmb(); /* make sure write propagated to HW */ | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int wil_debugfs_iomem_x32_get(void *data, u64 *val) | ||
209 | { | ||
210 | *val = ioread32((void __iomem *)data); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, | ||
216 | wil_debugfs_iomem_x32_set, "0x%08llx\n"); | ||
217 | |||
218 | static struct dentry *wil_debugfs_create_iomem_x32(const char *name, | ||
219 | mode_t mode, | ||
220 | struct dentry *parent, | ||
221 | void __iomem *value) | ||
222 | { | ||
223 | return debugfs_create_file(name, mode, parent, (void * __force)value, | ||
224 | &fops_iomem_x32); | ||
225 | } | ||
226 | |||
227 | static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, | ||
228 | const char *name, | ||
229 | struct dentry *parent, u32 off) | ||
230 | { | ||
231 | struct dentry *d = debugfs_create_dir(name, parent); | ||
232 | |||
233 | if (IS_ERR_OR_NULL(d)) | ||
234 | return -ENODEV; | ||
235 | |||
236 | wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, | ||
237 | wil->csr + off); | ||
238 | wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, | ||
239 | wil->csr + off + 4); | ||
240 | wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, | ||
241 | wil->csr + off + 8); | ||
242 | wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, | ||
243 | wil->csr + off + 12); | ||
244 | wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, | ||
245 | wil->csr + off + 16); | ||
246 | wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, | ||
247 | wil->csr + off + 20); | ||
248 | wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, | ||
249 | wil->csr + off + 24); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, | ||
255 | struct dentry *parent) | ||
256 | { | ||
257 | struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); | ||
258 | |||
259 | if (IS_ERR_OR_NULL(d)) | ||
260 | return -ENODEV; | ||
261 | |||
262 | wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + | ||
263 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
264 | wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + | ||
265 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
266 | wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + | ||
267 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, | ||
273 | struct dentry *parent) | ||
274 | { | ||
275 | struct dentry *d = debugfs_create_dir("ITR_CNT", parent); | ||
276 | |||
277 | if (IS_ERR_OR_NULL(d)) | ||
278 | return -ENODEV; | ||
279 | |||
280 | wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + | ||
281 | HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | ||
282 | wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + | ||
283 | HOSTADDR(RGF_DMA_ITR_CNT_DATA)); | ||
284 | wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + | ||
285 | HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int wil_memread_debugfs_show(struct seq_file *s, void *data) | ||
291 | { | ||
292 | struct wil6210_priv *wil = s->private; | ||
293 | void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); | ||
294 | |||
295 | if (a) | ||
296 | seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); | ||
297 | else | ||
298 | seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int wil_memread_seq_open(struct inode *inode, struct file *file) | ||
304 | { | ||
305 | return single_open(file, wil_memread_debugfs_show, inode->i_private); | ||
306 | } | ||
307 | |||
308 | static const struct file_operations fops_memread = { | ||
309 | .open = wil_memread_seq_open, | ||
310 | .release = single_release, | ||
311 | .read = seq_read, | ||
312 | .llseek = seq_lseek, | ||
313 | }; | ||
314 | |||
315 | static int wil_default_open(struct inode *inode, struct file *file) | ||
316 | { | ||
317 | if (inode->i_private) | ||
318 | file->private_data = inode->i_private; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | ||
324 | size_t count, loff_t *ppos) | ||
325 | { | ||
326 | enum { max_count = 4096 }; | ||
327 | struct debugfs_blob_wrapper *blob = file->private_data; | ||
328 | loff_t pos = *ppos; | ||
329 | size_t available = blob->size; | ||
330 | void *buf; | ||
331 | size_t ret; | ||
332 | |||
333 | if (pos < 0) | ||
334 | return -EINVAL; | ||
335 | |||
336 | if (pos >= available || !count) | ||
337 | return 0; | ||
338 | |||
339 | if (count > available - pos) | ||
340 | count = available - pos; | ||
341 | if (count > max_count) | ||
342 | count = max_count; | ||
343 | |||
344 | buf = kmalloc(count, GFP_KERNEL); | ||
345 | if (!buf) | ||
346 | return -ENOMEM; | ||
347 | |||
348 | wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + | ||
349 | pos, count); | ||
350 | |||
351 | ret = copy_to_user(user_buf, buf, count); | ||
352 | kfree(buf); | ||
353 | if (ret == count) | ||
354 | return -EFAULT; | ||
355 | |||
356 | count -= ret; | ||
357 | *ppos = pos + count; | ||
358 | |||
359 | return count; | ||
360 | } | ||
361 | |||
362 | static const struct file_operations fops_ioblob = { | ||
363 | .read = wil_read_file_ioblob, | ||
364 | .open = wil_default_open, | ||
365 | .llseek = default_llseek, | ||
366 | }; | ||
367 | |||
368 | static | ||
369 | struct dentry *wil_debugfs_create_ioblob(const char *name, | ||
370 | mode_t mode, | ||
371 | struct dentry *parent, | ||
372 | struct debugfs_blob_wrapper *blob) | ||
373 | { | ||
374 | return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); | ||
375 | } | ||
376 | /*---reset---*/ | ||
377 | static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | ||
378 | size_t len, loff_t *ppos) | ||
379 | { | ||
380 | struct wil6210_priv *wil = file->private_data; | ||
381 | struct net_device *ndev = wil_to_ndev(wil); | ||
382 | |||
383 | /** | ||
384 | * BUG: | ||
385 | * this code does NOT sync device state with the rest of system | ||
386 | * use with care, debug only!!! | ||
387 | */ | ||
388 | rtnl_lock(); | ||
389 | dev_close(ndev); | ||
390 | ndev->flags &= ~IFF_UP; | ||
391 | rtnl_unlock(); | ||
392 | wil_reset(wil); | ||
393 | |||
394 | return len; | ||
395 | } | ||
396 | |||
397 | static const struct file_operations fops_reset = { | ||
398 | .write = wil_write_file_reset, | ||
399 | .open = wil_default_open, | ||
400 | }; | ||
401 | /*---------Tx descriptor------------*/ | ||
402 | |||
403 | static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) | ||
404 | { | ||
405 | struct wil6210_priv *wil = s->private; | ||
406 | struct vring *vring = &(wil->vring_tx[0]); | ||
407 | |||
408 | if (!vring->va) { | ||
409 | seq_printf(s, "No Tx VRING\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | if (dbg_txdesc_index < vring->size) { | ||
414 | volatile struct vring_tx_desc *d = | ||
415 | &(vring->va[dbg_txdesc_index].tx); | ||
416 | volatile u32 *u = (volatile u32 *)d; | ||
417 | struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; | ||
418 | |||
419 | seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); | ||
420 | seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
421 | u[0], u[1], u[2], u[3]); | ||
422 | seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
423 | u[4], u[5], u[6], u[7]); | ||
424 | seq_printf(s, " SKB = %p\n", skb); | ||
425 | |||
426 | if (skb) { | ||
427 | unsigned char printbuf[16 * 3 + 2]; | ||
428 | int i = 0; | ||
429 | int len = skb_headlen(skb); | ||
430 | void *p = skb->data; | ||
431 | |||
432 | seq_printf(s, " len = %d\n", len); | ||
433 | |||
434 | while (i < len) { | ||
435 | int l = min(len - i, 16); | ||
436 | hex_dump_to_buffer(p + i, l, 16, 1, printbuf, | ||
437 | sizeof(printbuf), false); | ||
438 | seq_printf(s, " : %s\n", printbuf); | ||
439 | i += l; | ||
440 | } | ||
441 | } | ||
442 | seq_printf(s, "}\n"); | ||
443 | } else { | ||
444 | seq_printf(s, "TxDesc index (%d) >= size (%d)\n", | ||
445 | dbg_txdesc_index, vring->size); | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int wil_txdesc_seq_open(struct inode *inode, struct file *file) | ||
452 | { | ||
453 | return single_open(file, wil_txdesc_debugfs_show, inode->i_private); | ||
454 | } | ||
455 | |||
456 | static const struct file_operations fops_txdesc = { | ||
457 | .open = wil_txdesc_seq_open, | ||
458 | .release = single_release, | ||
459 | .read = seq_read, | ||
460 | .llseek = seq_lseek, | ||
461 | }; | ||
462 | |||
463 | /*---------beamforming------------*/ | ||
464 | static int wil_bf_debugfs_show(struct seq_file *s, void *data) | ||
465 | { | ||
466 | struct wil6210_priv *wil = s->private; | ||
467 | seq_printf(s, | ||
468 | "TSF : 0x%016llx\n" | ||
469 | "TxMCS : %d\n" | ||
470 | "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", | ||
471 | wil->stats.tsf, wil->stats.bf_mcs, | ||
472 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
473 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int wil_bf_seq_open(struct inode *inode, struct file *file) | ||
478 | { | ||
479 | return single_open(file, wil_bf_debugfs_show, inode->i_private); | ||
480 | } | ||
481 | |||
482 | static const struct file_operations fops_bf = { | ||
483 | .open = wil_bf_seq_open, | ||
484 | .release = single_release, | ||
485 | .read = seq_read, | ||
486 | .llseek = seq_lseek, | ||
487 | }; | ||
488 | /*---------SSID------------*/ | ||
489 | static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, | ||
490 | size_t count, loff_t *ppos) | ||
491 | { | ||
492 | struct wil6210_priv *wil = file->private_data; | ||
493 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
494 | |||
495 | return simple_read_from_buffer(user_buf, count, ppos, | ||
496 | wdev->ssid, wdev->ssid_len); | ||
497 | } | ||
498 | |||
499 | static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, | ||
500 | size_t count, loff_t *ppos) | ||
501 | { | ||
502 | struct wil6210_priv *wil = file->private_data; | ||
503 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
504 | struct net_device *ndev = wil_to_ndev(wil); | ||
505 | |||
506 | if (*ppos != 0) { | ||
507 | wil_err(wil, "Unable to set SSID substring from [%d]\n", | ||
508 | (int)*ppos); | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | if (count > sizeof(wdev->ssid)) { | ||
513 | wil_err(wil, "SSID too long, len = %d\n", (int)count); | ||
514 | return -EINVAL; | ||
515 | } | ||
516 | if (netif_running(ndev)) { | ||
517 | wil_err(wil, "Unable to change SSID on running interface\n"); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | |||
521 | wdev->ssid_len = count; | ||
522 | return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, | ||
523 | buf, count); | ||
524 | } | ||
525 | |||
526 | static const struct file_operations fops_ssid = { | ||
527 | .read = wil_read_file_ssid, | ||
528 | .write = wil_write_file_ssid, | ||
529 | .open = wil_default_open, | ||
530 | }; | ||
531 | |||
532 | /*----------------*/ | ||
533 | int wil6210_debugfs_init(struct wil6210_priv *wil) | ||
534 | { | ||
535 | struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, | ||
536 | wil_to_wiphy(wil)->debugfsdir); | ||
537 | |||
538 | if (IS_ERR_OR_NULL(dbg)) | ||
539 | return -ENODEV; | ||
540 | |||
541 | debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); | ||
542 | debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); | ||
543 | debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); | ||
544 | debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, | ||
545 | &dbg_txdesc_index); | ||
546 | debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); | ||
547 | debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); | ||
548 | debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, | ||
549 | &wil->secure_pcp); | ||
550 | |||
551 | wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, | ||
552 | HOSTADDR(RGF_USER_USER_ICR)); | ||
553 | wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, | ||
554 | HOSTADDR(RGF_DMA_EP_TX_ICR)); | ||
555 | wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, | ||
556 | HOSTADDR(RGF_DMA_EP_RX_ICR)); | ||
557 | wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, | ||
558 | HOSTADDR(RGF_DMA_EP_MISC_ICR)); | ||
559 | wil6210_debugfs_create_pseudo_ISR(wil, dbg); | ||
560 | wil6210_debugfs_create_ITR_CNT(wil, dbg); | ||
561 | |||
562 | debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); | ||
563 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | ||
564 | |||
565 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); | ||
566 | |||
567 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | ||
568 | wil->rgf_blob.size = 0xa000; | ||
569 | wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); | ||
570 | |||
571 | wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; | ||
572 | wil->fw_code_blob.size = 0x40000; | ||
573 | wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, | ||
574 | &wil->fw_code_blob); | ||
575 | |||
576 | wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; | ||
577 | wil->fw_data_blob.size = 0x8000; | ||
578 | wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, | ||
579 | &wil->fw_data_blob); | ||
580 | |||
581 | wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; | ||
582 | wil->fw_peri_blob.size = 0x18000; | ||
583 | wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, | ||
584 | &wil->fw_peri_blob); | ||
585 | |||
586 | wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; | ||
587 | wil->uc_code_blob.size = 0x10000; | ||
588 | wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, | ||
589 | &wil->uc_code_blob); | ||
590 | |||
591 | wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; | ||
592 | wil->uc_data_blob.size = 0x4000; | ||
593 | wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, | ||
594 | &wil->uc_data_blob); | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | void wil6210_debugfs_remove(struct wil6210_priv *wil) | ||
600 | { | ||
601 | debugfs_remove_recursive(wil->debug); | ||
602 | wil->debug = NULL; | ||
603 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c new file mode 100644 index 000000000000..38049da71049 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | #include "wil6210.h" | ||
20 | |||
21 | /** | ||
22 | * Theory of operation: | ||
23 | * | ||
24 | * There is ISR pseudo-cause register, | ||
25 | * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE | ||
26 | * Its bits represents OR'ed bits from 3 real ISR registers: | ||
27 | * TX, RX, and MISC. | ||
28 | * | ||
29 | * Registers may be configured to either "write 1 to clear" or | ||
30 | * "clear on read" mode | ||
31 | * | ||
32 | * When handling interrupt, one have to mask/unmask interrupts for the | ||
33 | * real ISR registers, or hardware may malfunction. | ||
34 | * | ||
35 | */ | ||
36 | |||
37 | #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) | ||
38 | #define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE | ||
39 | #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ | ||
40 | BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) | ||
41 | #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) | ||
42 | |||
43 | #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ | ||
44 | BIT_DMA_PSEUDO_CAUSE_TX | \ | ||
45 | BIT_DMA_PSEUDO_CAUSE_MISC)) | ||
46 | |||
47 | #if defined(CONFIG_WIL6210_ISR_COR) | ||
48 | /* configure to Clear-On-Read mode */ | ||
49 | #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) | ||
50 | |||
51 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
52 | { | ||
53 | |||
54 | } | ||
55 | #else /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
56 | /* configure to Write-1-to-Clear mode */ | ||
57 | #define WIL_ICR_ICC_VALUE (0UL) | ||
58 | |||
59 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
60 | { | ||
61 | iowrite32(x, addr); | ||
62 | } | ||
63 | #endif /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
64 | |||
65 | static inline u32 wil_ioread32_and_clear(void __iomem *addr) | ||
66 | { | ||
67 | u32 x = ioread32(addr); | ||
68 | |||
69 | wil_icr_clear(x, addr); | ||
70 | |||
71 | return x; | ||
72 | } | ||
73 | |||
74 | static void wil6210_mask_irq_tx(struct wil6210_priv *wil) | ||
75 | { | ||
76 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
77 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
78 | offsetof(struct RGF_ICR, IMS)); | ||
79 | } | ||
80 | |||
81 | static void wil6210_mask_irq_rx(struct wil6210_priv *wil) | ||
82 | { | ||
83 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
84 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
85 | offsetof(struct RGF_ICR, IMS)); | ||
86 | } | ||
87 | |||
88 | static void wil6210_mask_irq_misc(struct wil6210_priv *wil) | ||
89 | { | ||
90 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
91 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
92 | offsetof(struct RGF_ICR, IMS)); | ||
93 | } | ||
94 | |||
95 | static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) | ||
96 | { | ||
97 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
98 | |||
99 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
100 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
101 | |||
102 | clear_bit(wil_status_irqen, &wil->status); | ||
103 | } | ||
104 | |||
105 | static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | ||
106 | { | ||
107 | iowrite32(WIL6210_IMC_TX, wil->csr + | ||
108 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
109 | offsetof(struct RGF_ICR, IMC)); | ||
110 | } | ||
111 | |||
112 | static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) | ||
113 | { | ||
114 | iowrite32(WIL6210_IMC_RX, wil->csr + | ||
115 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
116 | offsetof(struct RGF_ICR, IMC)); | ||
117 | } | ||
118 | |||
119 | static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) | ||
120 | { | ||
121 | iowrite32(WIL6210_IMC_MISC, wil->csr + | ||
122 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
123 | offsetof(struct RGF_ICR, IMC)); | ||
124 | } | ||
125 | |||
126 | static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) | ||
127 | { | ||
128 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
129 | |||
130 | set_bit(wil_status_irqen, &wil->status); | ||
131 | |||
132 | iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + | ||
133 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
134 | } | ||
135 | |||
136 | void wil6210_disable_irq(struct wil6210_priv *wil) | ||
137 | { | ||
138 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
139 | |||
140 | wil6210_mask_irq_tx(wil); | ||
141 | wil6210_mask_irq_rx(wil); | ||
142 | wil6210_mask_irq_misc(wil); | ||
143 | wil6210_mask_irq_pseudo(wil); | ||
144 | } | ||
145 | |||
146 | void wil6210_enable_irq(struct wil6210_priv *wil) | ||
147 | { | ||
148 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
149 | |||
150 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
151 | offsetof(struct RGF_ICR, ICC)); | ||
152 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
153 | offsetof(struct RGF_ICR, ICC)); | ||
154 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
155 | offsetof(struct RGF_ICR, ICC)); | ||
156 | |||
157 | wil6210_unmask_irq_pseudo(wil); | ||
158 | wil6210_unmask_irq_tx(wil); | ||
159 | wil6210_unmask_irq_rx(wil); | ||
160 | wil6210_unmask_irq_misc(wil); | ||
161 | } | ||
162 | |||
163 | static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | ||
164 | { | ||
165 | struct wil6210_priv *wil = cookie; | ||
166 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
167 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
168 | offsetof(struct RGF_ICR, ICR)); | ||
169 | |||
170 | wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); | ||
171 | |||
172 | if (!isr) { | ||
173 | wil_err(wil, "spurious IRQ: RX\n"); | ||
174 | return IRQ_NONE; | ||
175 | } | ||
176 | |||
177 | wil6210_mask_irq_rx(wil); | ||
178 | |||
179 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { | ||
180 | wil_dbg_IRQ(wil, "RX done\n"); | ||
181 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; | ||
182 | wil_rx_handle(wil); | ||
183 | } | ||
184 | |||
185 | if (isr) | ||
186 | wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); | ||
187 | |||
188 | wil6210_unmask_irq_rx(wil); | ||
189 | |||
190 | return IRQ_HANDLED; | ||
191 | } | ||
192 | |||
193 | static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | ||
194 | { | ||
195 | struct wil6210_priv *wil = cookie; | ||
196 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
197 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
198 | offsetof(struct RGF_ICR, ICR)); | ||
199 | |||
200 | wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); | ||
201 | |||
202 | if (!isr) { | ||
203 | wil_err(wil, "spurious IRQ: TX\n"); | ||
204 | return IRQ_NONE; | ||
205 | } | ||
206 | |||
207 | wil6210_mask_irq_tx(wil); | ||
208 | |||
209 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { | ||
210 | uint i; | ||
211 | wil_dbg_IRQ(wil, "TX done\n"); | ||
212 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | ||
213 | for (i = 0; i < 24; i++) { | ||
214 | u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); | ||
215 | if (isr & mask) { | ||
216 | isr &= ~mask; | ||
217 | wil_dbg_IRQ(wil, "TX done(%i)\n", i); | ||
218 | wil_tx_complete(wil, i); | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | if (isr) | ||
224 | wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); | ||
225 | |||
226 | wil6210_unmask_irq_tx(wil); | ||
227 | |||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | |||
231 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | ||
232 | { | ||
233 | struct wil6210_priv *wil = cookie; | ||
234 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
235 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
236 | offsetof(struct RGF_ICR, ICR)); | ||
237 | |||
238 | wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); | ||
239 | |||
240 | if (!isr) { | ||
241 | wil_err(wil, "spurious IRQ: MISC\n"); | ||
242 | return IRQ_NONE; | ||
243 | } | ||
244 | |||
245 | wil6210_mask_irq_misc(wil); | ||
246 | |||
247 | if (isr & ISR_MISC_FW_READY) { | ||
248 | wil_dbg_IRQ(wil, "IRQ: FW ready\n"); | ||
249 | /** | ||
250 | * Actual FW ready indicated by the | ||
251 | * WMI_FW_READY_EVENTID | ||
252 | */ | ||
253 | isr &= ~ISR_MISC_FW_READY; | ||
254 | } | ||
255 | |||
256 | wil->isr_misc = isr; | ||
257 | |||
258 | if (isr) { | ||
259 | return IRQ_WAKE_THREAD; | ||
260 | } else { | ||
261 | wil6210_unmask_irq_misc(wil); | ||
262 | return IRQ_HANDLED; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | ||
267 | { | ||
268 | struct wil6210_priv *wil = cookie; | ||
269 | u32 isr = wil->isr_misc; | ||
270 | |||
271 | wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); | ||
272 | |||
273 | if (isr & ISR_MISC_MBOX_EVT) { | ||
274 | wil_dbg_IRQ(wil, "MBOX event\n"); | ||
275 | wmi_recv_cmd(wil); | ||
276 | isr &= ~ISR_MISC_MBOX_EVT; | ||
277 | } | ||
278 | |||
279 | if (isr) | ||
280 | wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); | ||
281 | |||
282 | wil->isr_misc = 0; | ||
283 | |||
284 | wil6210_unmask_irq_misc(wil); | ||
285 | |||
286 | return IRQ_HANDLED; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * thread IRQ handler | ||
291 | */ | ||
292 | static irqreturn_t wil6210_thread_irq(int irq, void *cookie) | ||
293 | { | ||
294 | struct wil6210_priv *wil = cookie; | ||
295 | |||
296 | wil_dbg_IRQ(wil, "Thread IRQ\n"); | ||
297 | /* Discover real IRQ cause */ | ||
298 | if (wil->isr_misc) | ||
299 | wil6210_irq_misc_thread(irq, cookie); | ||
300 | |||
301 | wil6210_unmask_irq_pseudo(wil); | ||
302 | |||
303 | return IRQ_HANDLED; | ||
304 | } | ||
305 | |||
306 | /* DEBUG | ||
307 | * There is subtle bug in hardware that causes IRQ to raise when it should be | ||
308 | * masked. It is quite rare and hard to debug. | ||
309 | * | ||
310 | * Catch irq issue if it happens and print all I can. | ||
311 | */ | ||
312 | static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) | ||
313 | { | ||
314 | if (!test_bit(wil_status_irqen, &wil->status)) { | ||
315 | u32 icm_rx = wil_ioread32_and_clear(wil->csr + | ||
316 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
317 | offsetof(struct RGF_ICR, ICM)); | ||
318 | u32 icr_rx = wil_ioread32_and_clear(wil->csr + | ||
319 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
320 | offsetof(struct RGF_ICR, ICR)); | ||
321 | u32 imv_rx = ioread32(wil->csr + | ||
322 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
323 | offsetof(struct RGF_ICR, IMV)); | ||
324 | u32 icm_tx = wil_ioread32_and_clear(wil->csr + | ||
325 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
326 | offsetof(struct RGF_ICR, ICM)); | ||
327 | u32 icr_tx = wil_ioread32_and_clear(wil->csr + | ||
328 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
329 | offsetof(struct RGF_ICR, ICR)); | ||
330 | u32 imv_tx = ioread32(wil->csr + | ||
331 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
332 | offsetof(struct RGF_ICR, IMV)); | ||
333 | u32 icm_misc = wil_ioread32_and_clear(wil->csr + | ||
334 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
335 | offsetof(struct RGF_ICR, ICM)); | ||
336 | u32 icr_misc = wil_ioread32_and_clear(wil->csr + | ||
337 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
338 | offsetof(struct RGF_ICR, ICR)); | ||
339 | u32 imv_misc = ioread32(wil->csr + | ||
340 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
341 | offsetof(struct RGF_ICR, IMV)); | ||
342 | wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" | ||
343 | "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
344 | "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
345 | "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", | ||
346 | pseudo_cause, | ||
347 | icm_rx, icr_rx, imv_rx, | ||
348 | icm_tx, icr_tx, imv_tx, | ||
349 | icm_misc, icr_misc, imv_misc); | ||
350 | |||
351 | return -EINVAL; | ||
352 | } | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static irqreturn_t wil6210_hardirq(int irq, void *cookie) | ||
358 | { | ||
359 | irqreturn_t rc = IRQ_HANDLED; | ||
360 | struct wil6210_priv *wil = cookie; | ||
361 | u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
362 | |||
363 | /** | ||
364 | * pseudo_cause is Clear-On-Read, no need to ACK | ||
365 | */ | ||
366 | if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) | ||
367 | return IRQ_NONE; | ||
368 | |||
369 | /* FIXME: IRQ mask debug */ | ||
370 | if (wil6210_debug_irq_mask(wil, pseudo_cause)) | ||
371 | return IRQ_NONE; | ||
372 | |||
373 | wil6210_mask_irq_pseudo(wil); | ||
374 | |||
375 | /* Discover real IRQ cause | ||
376 | * There are 2 possible phases for every IRQ: | ||
377 | * - hard IRQ handler called right here | ||
378 | * - threaded handler called later | ||
379 | * | ||
380 | * Hard IRQ handler reads and clears ISR. | ||
381 | * | ||
382 | * If threaded handler requested, hard IRQ handler | ||
383 | * returns IRQ_WAKE_THREAD and saves ISR register value | ||
384 | * for the threaded handler use. | ||
385 | * | ||
386 | * voting for wake thread - need at least 1 vote | ||
387 | */ | ||
388 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && | ||
389 | (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
390 | rc = IRQ_WAKE_THREAD; | ||
391 | |||
392 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && | ||
393 | (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
394 | rc = IRQ_WAKE_THREAD; | ||
395 | |||
396 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && | ||
397 | (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) | ||
398 | rc = IRQ_WAKE_THREAD; | ||
399 | |||
400 | /* if thread is requested, it will unmask IRQ */ | ||
401 | if (rc != IRQ_WAKE_THREAD) | ||
402 | wil6210_unmask_irq_pseudo(wil); | ||
403 | |||
404 | wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); | ||
405 | |||
406 | return rc; | ||
407 | } | ||
408 | |||
409 | static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) | ||
410 | { | ||
411 | int rc; | ||
412 | /* | ||
413 | * IRQ's are in the following order: | ||
414 | * - Tx | ||
415 | * - Rx | ||
416 | * - Misc | ||
417 | */ | ||
418 | |||
419 | rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, | ||
420 | WIL_NAME"_tx", wil); | ||
421 | if (rc) | ||
422 | return rc; | ||
423 | |||
424 | rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, | ||
425 | WIL_NAME"_rx", wil); | ||
426 | if (rc) | ||
427 | goto free0; | ||
428 | |||
429 | rc = request_threaded_irq(irq + 2, wil6210_irq_misc, | ||
430 | wil6210_irq_misc_thread, | ||
431 | IRQF_SHARED, WIL_NAME"_misc", wil); | ||
432 | if (rc) | ||
433 | goto free1; | ||
434 | |||
435 | return 0; | ||
436 | /* error branch */ | ||
437 | free1: | ||
438 | free_irq(irq + 1, wil); | ||
439 | free0: | ||
440 | free_irq(irq, wil); | ||
441 | |||
442 | return rc; | ||
443 | } | ||
444 | |||
445 | int wil6210_init_irq(struct wil6210_priv *wil, int irq) | ||
446 | { | ||
447 | int rc; | ||
448 | if (wil->n_msi == 3) | ||
449 | rc = wil6210_request_3msi(wil, irq); | ||
450 | else | ||
451 | rc = request_threaded_irq(irq, wil6210_hardirq, | ||
452 | wil6210_thread_irq, | ||
453 | wil->n_msi ? 0 : IRQF_SHARED, | ||
454 | WIL_NAME, wil); | ||
455 | if (rc) | ||
456 | return rc; | ||
457 | |||
458 | wil6210_enable_irq(wil); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq) | ||
464 | { | ||
465 | wil6210_disable_irq(wil); | ||
466 | free_irq(irq, wil); | ||
467 | if (wil->n_msi == 3) { | ||
468 | free_irq(irq + 1, wil); | ||
469 | free_irq(irq + 2, wil); | ||
470 | } | ||
471 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c new file mode 100644 index 000000000000..95fcd361322b --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/ieee80211.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/if_arp.h> | ||
25 | |||
26 | #include "wil6210.h" | ||
27 | |||
28 | /* | ||
29 | * Due to a hardware issue, | ||
30 | * one has to read/write to/from NIC in 32-bit chunks; | ||
31 | * regular memcpy_fromio and siblings will | ||
32 | * not work on 64-bit platform - it uses 64-bit transactions | ||
33 | * | ||
34 | * Force 32-bit transactions to enable NIC on 64-bit platforms | ||
35 | * | ||
36 | * To avoid byte swap on big endian host, __raw_{read|write}l | ||
37 | * should be used - {read|write}l would swap bytes to provide | ||
38 | * little endian on PCI value in host endianness. | ||
39 | */ | ||
40 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
41 | size_t count) | ||
42 | { | ||
43 | u32 *d = dst; | ||
44 | const volatile u32 __iomem *s = src; | ||
45 | |||
46 | /* size_t is unsigned, if (count%4 != 0) it will wrap */ | ||
47 | for (count += 4; count > 4; count -= 4) | ||
48 | *d++ = __raw_readl(s++); | ||
49 | } | ||
50 | |||
51 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
52 | size_t count) | ||
53 | { | ||
54 | volatile u32 __iomem *d = dst; | ||
55 | const u32 *s = src; | ||
56 | |||
57 | for (count += 4; count > 4; count -= 4) | ||
58 | __raw_writel(*s++, d++); | ||
59 | } | ||
60 | |||
61 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
62 | { | ||
63 | uint i; | ||
64 | struct net_device *ndev = wil_to_ndev(wil); | ||
65 | struct wireless_dev *wdev = wil->wdev; | ||
66 | |||
67 | wil_dbg(wil, "%s()\n", __func__); | ||
68 | |||
69 | wil_link_off(wil); | ||
70 | clear_bit(wil_status_fwconnected, &wil->status); | ||
71 | |||
72 | switch (wdev->sme_state) { | ||
73 | case CFG80211_SME_CONNECTED: | ||
74 | cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
75 | NULL, 0, GFP_KERNEL); | ||
76 | break; | ||
77 | case CFG80211_SME_CONNECTING: | ||
78 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, | ||
79 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
80 | GFP_KERNEL); | ||
81 | break; | ||
82 | default: | ||
83 | ; | ||
84 | } | ||
85 | |||
86 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) | ||
87 | wil_vring_fini_tx(wil, i); | ||
88 | } | ||
89 | |||
90 | static void wil_disconnect_worker(struct work_struct *work) | ||
91 | { | ||
92 | struct wil6210_priv *wil = container_of(work, | ||
93 | struct wil6210_priv, disconnect_worker); | ||
94 | |||
95 | _wil6210_disconnect(wil, NULL); | ||
96 | } | ||
97 | |||
98 | static void wil_connect_timer_fn(ulong x) | ||
99 | { | ||
100 | struct wil6210_priv *wil = (void *)x; | ||
101 | |||
102 | wil_dbg(wil, "Connect timeout\n"); | ||
103 | |||
104 | /* reschedule to thread context - disconnect won't | ||
105 | * run from atomic context | ||
106 | */ | ||
107 | schedule_work(&wil->disconnect_worker); | ||
108 | } | ||
109 | |||
110 | int wil_priv_init(struct wil6210_priv *wil) | ||
111 | { | ||
112 | wil_dbg(wil, "%s()\n", __func__); | ||
113 | |||
114 | mutex_init(&wil->mutex); | ||
115 | mutex_init(&wil->wmi_mutex); | ||
116 | |||
117 | init_completion(&wil->wmi_ready); | ||
118 | |||
119 | wil->pending_connect_cid = -1; | ||
120 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | ||
121 | |||
122 | INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); | ||
123 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | ||
124 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | ||
125 | |||
126 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | ||
127 | spin_lock_init(&wil->wmi_ev_lock); | ||
128 | |||
129 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); | ||
130 | if (!wil->wmi_wq) | ||
131 | return -EAGAIN; | ||
132 | |||
133 | wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); | ||
134 | if (!wil->wmi_wq_conn) { | ||
135 | destroy_workqueue(wil->wmi_wq); | ||
136 | return -EAGAIN; | ||
137 | } | ||
138 | |||
139 | /* make shadow copy of registers that should not change on run time */ | ||
140 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
141 | sizeof(struct wil6210_mbox_ctl)); | ||
142 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
143 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
149 | { | ||
150 | del_timer_sync(&wil->connect_timer); | ||
151 | _wil6210_disconnect(wil, bssid); | ||
152 | } | ||
153 | |||
154 | void wil_priv_deinit(struct wil6210_priv *wil) | ||
155 | { | ||
156 | cancel_work_sync(&wil->disconnect_worker); | ||
157 | wil6210_disconnect(wil, NULL); | ||
158 | wmi_event_flush(wil); | ||
159 | destroy_workqueue(wil->wmi_wq_conn); | ||
160 | destroy_workqueue(wil->wmi_wq); | ||
161 | } | ||
162 | |||
163 | static void wil_target_reset(struct wil6210_priv *wil) | ||
164 | { | ||
165 | wil_dbg(wil, "Resetting...\n"); | ||
166 | |||
167 | /* register write */ | ||
168 | #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) | ||
169 | /* register set = read, OR, write */ | ||
170 | #define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ | ||
171 | wil->csr + HOSTADDR(a)) | ||
172 | |||
173 | /* hpal_perst_from_pad_src_n_mask */ | ||
174 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); | ||
175 | /* car_perst_rst_src_n_mask */ | ||
176 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); | ||
177 | |||
178 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | ||
179 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | ||
180 | |||
181 | msleep(100); | ||
182 | |||
183 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | ||
184 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | ||
185 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | ||
186 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | ||
187 | |||
188 | msleep(100); | ||
189 | |||
190 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | ||
191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | ||
192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | ||
193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
194 | |||
195 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | ||
196 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
198 | |||
199 | msleep(2000); | ||
200 | |||
201 | W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ | ||
202 | |||
203 | msleep(2000); | ||
204 | |||
205 | wil_dbg(wil, "Reset completed\n"); | ||
206 | |||
207 | #undef W | ||
208 | #undef S | ||
209 | } | ||
210 | |||
211 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | ||
212 | { | ||
213 | le32_to_cpus(&r->base); | ||
214 | le16_to_cpus(&r->entry_size); | ||
215 | le16_to_cpus(&r->size); | ||
216 | le32_to_cpus(&r->tail); | ||
217 | le32_to_cpus(&r->head); | ||
218 | } | ||
219 | |||
220 | static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | ||
221 | { | ||
222 | ulong to = msecs_to_jiffies(1000); | ||
223 | ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); | ||
224 | if (0 == left) { | ||
225 | wil_err(wil, "Firmware not ready\n"); | ||
226 | return -ETIME; | ||
227 | } else { | ||
228 | wil_dbg(wil, "FW ready after %d ms\n", | ||
229 | jiffies_to_msecs(to-left)); | ||
230 | } | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * We reset all the structures, and we reset the UMAC. | ||
236 | * After calling this routine, you're expected to reload | ||
237 | * the firmware. | ||
238 | */ | ||
239 | int wil_reset(struct wil6210_priv *wil) | ||
240 | { | ||
241 | int rc; | ||
242 | |||
243 | cancel_work_sync(&wil->disconnect_worker); | ||
244 | wil6210_disconnect(wil, NULL); | ||
245 | |||
246 | wmi_event_flush(wil); | ||
247 | |||
248 | flush_workqueue(wil->wmi_wq); | ||
249 | flush_workqueue(wil->wmi_wq_conn); | ||
250 | |||
251 | wil6210_disable_irq(wil); | ||
252 | wil->status = 0; | ||
253 | |||
254 | /* TODO: put MAC in reset */ | ||
255 | wil_target_reset(wil); | ||
256 | |||
257 | /* init after reset */ | ||
258 | wil->pending_connect_cid = -1; | ||
259 | INIT_COMPLETION(wil->wmi_ready); | ||
260 | |||
261 | /* make shadow copy of registers that should not change on run time */ | ||
262 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
263 | sizeof(struct wil6210_mbox_ctl)); | ||
264 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
265 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
266 | |||
267 | /* TODO: release MAC reset */ | ||
268 | wil6210_enable_irq(wil); | ||
269 | |||
270 | /* we just started MAC, wait for FW ready */ | ||
271 | rc = wil_wait_for_fw_ready(wil); | ||
272 | |||
273 | return rc; | ||
274 | } | ||
275 | |||
276 | |||
277 | void wil_link_on(struct wil6210_priv *wil) | ||
278 | { | ||
279 | struct net_device *ndev = wil_to_ndev(wil); | ||
280 | |||
281 | wil_dbg(wil, "%s()\n", __func__); | ||
282 | |||
283 | netif_carrier_on(ndev); | ||
284 | netif_tx_wake_all_queues(ndev); | ||
285 | } | ||
286 | |||
287 | void wil_link_off(struct wil6210_priv *wil) | ||
288 | { | ||
289 | struct net_device *ndev = wil_to_ndev(wil); | ||
290 | |||
291 | wil_dbg(wil, "%s()\n", __func__); | ||
292 | |||
293 | netif_tx_stop_all_queues(ndev); | ||
294 | netif_carrier_off(ndev); | ||
295 | } | ||
296 | |||
297 | static int __wil_up(struct wil6210_priv *wil) | ||
298 | { | ||
299 | struct net_device *ndev = wil_to_ndev(wil); | ||
300 | struct wireless_dev *wdev = wil->wdev; | ||
301 | struct ieee80211_channel *channel = wdev->preset_chandef.chan; | ||
302 | int rc; | ||
303 | int bi; | ||
304 | u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
305 | |||
306 | rc = wil_reset(wil); | ||
307 | if (rc) | ||
308 | return rc; | ||
309 | |||
310 | /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ | ||
311 | wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); | ||
312 | switch (wdev->iftype) { | ||
313 | case NL80211_IFTYPE_STATION: | ||
314 | wil_dbg(wil, "type: STATION\n"); | ||
315 | bi = 0; | ||
316 | ndev->type = ARPHRD_ETHER; | ||
317 | break; | ||
318 | case NL80211_IFTYPE_AP: | ||
319 | wil_dbg(wil, "type: AP\n"); | ||
320 | bi = 100; | ||
321 | ndev->type = ARPHRD_ETHER; | ||
322 | break; | ||
323 | case NL80211_IFTYPE_P2P_CLIENT: | ||
324 | wil_dbg(wil, "type: P2P_CLIENT\n"); | ||
325 | bi = 0; | ||
326 | ndev->type = ARPHRD_ETHER; | ||
327 | break; | ||
328 | case NL80211_IFTYPE_P2P_GO: | ||
329 | wil_dbg(wil, "type: P2P_GO\n"); | ||
330 | bi = 100; | ||
331 | ndev->type = ARPHRD_ETHER; | ||
332 | break; | ||
333 | case NL80211_IFTYPE_MONITOR: | ||
334 | wil_dbg(wil, "type: Monitor\n"); | ||
335 | bi = 0; | ||
336 | ndev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
337 | /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ | ||
338 | break; | ||
339 | default: | ||
340 | return -EOPNOTSUPP; | ||
341 | } | ||
342 | |||
343 | /* Apply profile in the following order: */ | ||
344 | /* SSID and channel for the AP */ | ||
345 | switch (wdev->iftype) { | ||
346 | case NL80211_IFTYPE_AP: | ||
347 | case NL80211_IFTYPE_P2P_GO: | ||
348 | if (wdev->ssid_len == 0) { | ||
349 | wil_err(wil, "SSID not set\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); | ||
353 | if (channel) | ||
354 | wmi_set_channel(wil, channel->hw_value); | ||
355 | break; | ||
356 | default: | ||
357 | ; | ||
358 | } | ||
359 | |||
360 | /* MAC address - pre-requisite for other commands */ | ||
361 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
362 | |||
363 | /* Set up beaconing if required. */ | ||
364 | rc = wmi_set_bcon(wil, bi, wmi_nettype); | ||
365 | if (rc) | ||
366 | return rc; | ||
367 | |||
368 | /* Rx VRING. After MAC and beacon */ | ||
369 | wil_rx_init(wil); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | int wil_up(struct wil6210_priv *wil) | ||
375 | { | ||
376 | int rc; | ||
377 | |||
378 | mutex_lock(&wil->mutex); | ||
379 | rc = __wil_up(wil); | ||
380 | mutex_unlock(&wil->mutex); | ||
381 | |||
382 | return rc; | ||
383 | } | ||
384 | |||
385 | static int __wil_down(struct wil6210_priv *wil) | ||
386 | { | ||
387 | if (wil->scan_request) { | ||
388 | cfg80211_scan_done(wil->scan_request, true); | ||
389 | wil->scan_request = NULL; | ||
390 | } | ||
391 | |||
392 | wil6210_disconnect(wil, NULL); | ||
393 | wil_rx_fini(wil); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | int wil_down(struct wil6210_priv *wil) | ||
399 | { | ||
400 | int rc; | ||
401 | |||
402 | mutex_lock(&wil->mutex); | ||
403 | rc = __wil_down(wil); | ||
404 | mutex_unlock(&wil->mutex); | ||
405 | |||
406 | return rc; | ||
407 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c new file mode 100644 index 000000000000..3068b5cb53a7 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "wil6210.h" | ||
23 | |||
24 | static int wil_open(struct net_device *ndev) | ||
25 | { | ||
26 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
27 | |||
28 | return wil_up(wil); | ||
29 | } | ||
30 | |||
31 | static int wil_stop(struct net_device *ndev) | ||
32 | { | ||
33 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
34 | |||
35 | return wil_down(wil); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * AC to queue mapping | ||
40 | * | ||
41 | * AC_VO -> queue 3 | ||
42 | * AC_VI -> queue 2 | ||
43 | * AC_BE -> queue 1 | ||
44 | * AC_BK -> queue 0 | ||
45 | */ | ||
46 | static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) | ||
47 | { | ||
48 | static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; | ||
49 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
50 | u16 rc; | ||
51 | |||
52 | skb->priority = cfg80211_classify8021d(skb); | ||
53 | |||
54 | rc = wil_1d_to_queue[skb->priority]; | ||
55 | |||
56 | wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, | ||
57 | (int)rc); | ||
58 | |||
59 | return rc; | ||
60 | } | ||
61 | |||
62 | static const struct net_device_ops wil_netdev_ops = { | ||
63 | .ndo_open = wil_open, | ||
64 | .ndo_stop = wil_stop, | ||
65 | .ndo_start_xmit = wil_start_xmit, | ||
66 | .ndo_select_queue = wil_select_queue, | ||
67 | .ndo_set_mac_address = eth_mac_addr, | ||
68 | .ndo_validate_addr = eth_validate_addr, | ||
69 | }; | ||
70 | |||
71 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | ||
72 | { | ||
73 | struct net_device *ndev; | ||
74 | struct wireless_dev *wdev; | ||
75 | struct wil6210_priv *wil; | ||
76 | struct ieee80211_channel *ch; | ||
77 | int rc = 0; | ||
78 | |||
79 | wdev = wil_cfg80211_init(dev); | ||
80 | if (IS_ERR(wdev)) { | ||
81 | dev_err(dev, "wil_cfg80211_init failed\n"); | ||
82 | return wdev; | ||
83 | } | ||
84 | |||
85 | wil = wdev_to_wil(wdev); | ||
86 | wil->csr = csr; | ||
87 | wil->wdev = wdev; | ||
88 | |||
89 | rc = wil_priv_init(wil); | ||
90 | if (rc) { | ||
91 | dev_err(dev, "wil_priv_init failed\n"); | ||
92 | goto out_wdev; | ||
93 | } | ||
94 | |||
95 | wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ | ||
96 | /* default monitor channel */ | ||
97 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; | ||
98 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); | ||
99 | |||
100 | ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); | ||
101 | if (!ndev) { | ||
102 | dev_err(dev, "alloc_netdev_mqs failed\n"); | ||
103 | rc = -ENOMEM; | ||
104 | goto out_priv; | ||
105 | } | ||
106 | |||
107 | ndev->netdev_ops = &wil_netdev_ops; | ||
108 | ndev->ieee80211_ptr = wdev; | ||
109 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | ||
110 | wdev->netdev = ndev; | ||
111 | |||
112 | wil_link_off(wil); | ||
113 | |||
114 | return wil; | ||
115 | |||
116 | out_priv: | ||
117 | wil_priv_deinit(wil); | ||
118 | |||
119 | out_wdev: | ||
120 | wil_wdev_free(wil); | ||
121 | |||
122 | return ERR_PTR(rc); | ||
123 | } | ||
124 | |||
125 | void wil_if_free(struct wil6210_priv *wil) | ||
126 | { | ||
127 | struct net_device *ndev = wil_to_ndev(wil); | ||
128 | if (!ndev) | ||
129 | return; | ||
130 | |||
131 | free_netdev(ndev); | ||
132 | wil_priv_deinit(wil); | ||
133 | wil_wdev_free(wil); | ||
134 | } | ||
135 | |||
136 | int wil_if_add(struct wil6210_priv *wil) | ||
137 | { | ||
138 | struct net_device *ndev = wil_to_ndev(wil); | ||
139 | int rc; | ||
140 | |||
141 | rc = register_netdev(ndev); | ||
142 | if (rc < 0) { | ||
143 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); | ||
144 | return rc; | ||
145 | } | ||
146 | |||
147 | wil_link_off(wil); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | void wil_if_remove(struct wil6210_priv *wil) | ||
153 | { | ||
154 | struct net_device *ndev = wil_to_ndev(wil); | ||
155 | |||
156 | unregister_netdev(ndev); | ||
157 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c new file mode 100644 index 000000000000..0fc83edd6bad --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | |||
25 | #include "wil6210.h" | ||
26 | |||
27 | static int use_msi = 1; | ||
28 | module_param(use_msi, int, S_IRUGO); | ||
29 | MODULE_PARM_DESC(use_msi, | ||
30 | " Use MSI interrupt: " | ||
31 | "0 - don't, 1 - (default) - single, or 3"); | ||
32 | |||
33 | /* Bus ops */ | ||
34 | static int wil_if_pcie_enable(struct wil6210_priv *wil) | ||
35 | { | ||
36 | struct pci_dev *pdev = wil->pdev; | ||
37 | int rc; | ||
38 | |||
39 | pci_set_master(pdev); | ||
40 | |||
41 | /* | ||
42 | * how many MSI interrupts to request? | ||
43 | */ | ||
44 | switch (use_msi) { | ||
45 | case 3: | ||
46 | case 1: | ||
47 | case 0: | ||
48 | break; | ||
49 | default: | ||
50 | wil_err(wil, "Invalid use_msi=%d, default to 1\n", | ||
51 | use_msi); | ||
52 | use_msi = 1; | ||
53 | } | ||
54 | wil->n_msi = use_msi; | ||
55 | if (wil->n_msi) { | ||
56 | wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); | ||
57 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
58 | if (rc && (wil->n_msi == 3)) { | ||
59 | wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); | ||
60 | wil->n_msi = 1; | ||
61 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
62 | } | ||
63 | if (rc) { | ||
64 | wil_err(wil, "pci_enable_msi failed, use INTx\n"); | ||
65 | wil->n_msi = 0; | ||
66 | } | ||
67 | } else { | ||
68 | wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); | ||
69 | } | ||
70 | |||
71 | rc = wil6210_init_irq(wil, pdev->irq); | ||
72 | if (rc) | ||
73 | goto stop_master; | ||
74 | |||
75 | /* need reset here to obtain MAC */ | ||
76 | rc = wil_reset(wil); | ||
77 | if (rc) | ||
78 | goto release_irq; | ||
79 | |||
80 | return 0; | ||
81 | |||
82 | release_irq: | ||
83 | wil6210_fini_irq(wil, pdev->irq); | ||
84 | /* safe to call if no MSI */ | ||
85 | pci_disable_msi(pdev); | ||
86 | stop_master: | ||
87 | pci_clear_master(pdev); | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | static int wil_if_pcie_disable(struct wil6210_priv *wil) | ||
92 | { | ||
93 | struct pci_dev *pdev = wil->pdev; | ||
94 | |||
95 | pci_clear_master(pdev); | ||
96 | /* disable and release IRQ */ | ||
97 | wil6210_fini_irq(wil, pdev->irq); | ||
98 | /* safe to call if no MSI */ | ||
99 | pci_disable_msi(pdev); | ||
100 | /* TODO: disable HW */ | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
106 | { | ||
107 | struct wil6210_priv *wil; | ||
108 | struct device *dev = &pdev->dev; | ||
109 | void __iomem *csr; | ||
110 | int rc; | ||
111 | |||
112 | /* check HW */ | ||
113 | dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", | ||
114 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); | ||
115 | |||
116 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { | ||
117 | dev_err(&pdev->dev, "Not " WIL_NAME "? " | ||
118 | "BAR0 size is %lu while expecting %lu\n", | ||
119 | (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); | ||
120 | return -ENODEV; | ||
121 | } | ||
122 | |||
123 | rc = pci_enable_device(pdev); | ||
124 | if (rc) { | ||
125 | dev_err(&pdev->dev, "pci_enable_device failed\n"); | ||
126 | return -ENODEV; | ||
127 | } | ||
128 | /* rollback to err_disable_pdev */ | ||
129 | |||
130 | rc = pci_request_region(pdev, 0, WIL_NAME); | ||
131 | if (rc) { | ||
132 | dev_err(&pdev->dev, "pci_request_region failed\n"); | ||
133 | goto err_disable_pdev; | ||
134 | } | ||
135 | /* rollback to err_release_reg */ | ||
136 | |||
137 | csr = pci_ioremap_bar(pdev, 0); | ||
138 | if (!csr) { | ||
139 | dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); | ||
140 | rc = -ENODEV; | ||
141 | goto err_release_reg; | ||
142 | } | ||
143 | /* rollback to err_iounmap */ | ||
144 | dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); | ||
145 | |||
146 | wil = wil_if_alloc(dev, csr); | ||
147 | if (IS_ERR(wil)) { | ||
148 | rc = (int)PTR_ERR(wil); | ||
149 | dev_err(dev, "wil_if_alloc failed: %d\n", rc); | ||
150 | goto err_iounmap; | ||
151 | } | ||
152 | /* rollback to if_free */ | ||
153 | |||
154 | pci_set_drvdata(pdev, wil); | ||
155 | wil->pdev = pdev; | ||
156 | |||
157 | /* FW should raise IRQ when ready */ | ||
158 | rc = wil_if_pcie_enable(wil); | ||
159 | if (rc) { | ||
160 | wil_err(wil, "Enable device failed\n"); | ||
161 | goto if_free; | ||
162 | } | ||
163 | /* rollback to bus_disable */ | ||
164 | |||
165 | rc = wil_if_add(wil); | ||
166 | if (rc) { | ||
167 | wil_err(wil, "wil_if_add failed: %d\n", rc); | ||
168 | goto bus_disable; | ||
169 | } | ||
170 | |||
171 | wil6210_debugfs_init(wil); | ||
172 | |||
173 | /* check FW is alive */ | ||
174 | wmi_echo(wil); | ||
175 | |||
176 | return 0; | ||
177 | |||
178 | bus_disable: | ||
179 | wil_if_pcie_disable(wil); | ||
180 | if_free: | ||
181 | wil_if_free(wil); | ||
182 | err_iounmap: | ||
183 | pci_iounmap(pdev, csr); | ||
184 | err_release_reg: | ||
185 | pci_release_region(pdev, 0); | ||
186 | err_disable_pdev: | ||
187 | pci_disable_device(pdev); | ||
188 | |||
189 | return rc; | ||
190 | } | ||
191 | |||
192 | static void wil_pcie_remove(struct pci_dev *pdev) | ||
193 | { | ||
194 | struct wil6210_priv *wil = pci_get_drvdata(pdev); | ||
195 | |||
196 | wil6210_debugfs_remove(wil); | ||
197 | wil_if_pcie_disable(wil); | ||
198 | wil_if_remove(wil); | ||
199 | wil_if_free(wil); | ||
200 | pci_iounmap(pdev, wil->csr); | ||
201 | pci_release_region(pdev, 0); | ||
202 | pci_disable_device(pdev); | ||
203 | pci_set_drvdata(pdev, NULL); | ||
204 | } | ||
205 | |||
206 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { | ||
207 | { PCI_DEVICE(0x1ae9, 0x0301) }, | ||
208 | { /* end: all zeroes */ }, | ||
209 | }; | ||
210 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | ||
211 | |||
212 | static struct pci_driver wil6210_driver = { | ||
213 | .probe = wil_pcie_probe, | ||
214 | .remove = wil_pcie_remove, | ||
215 | .id_table = wil6210_pcie_ids, | ||
216 | .name = WIL_NAME, | ||
217 | }; | ||
218 | |||
219 | module_pci_driver(wil6210_driver); | ||
220 | |||
221 | MODULE_LICENSE("Dual BSD/GPL"); | ||
222 | MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); | ||
223 | MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c new file mode 100644 index 000000000000..f29c294413cf --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -0,0 +1,871 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/hardirq.h> | ||
21 | #include <net/ieee80211_radiotap.h> | ||
22 | #include <linux/if_arp.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | |||
25 | #include "wil6210.h" | ||
26 | #include "wmi.h" | ||
27 | #include "txrx.h" | ||
28 | |||
29 | static bool rtap_include_phy_info; | ||
30 | module_param(rtap_include_phy_info, bool, S_IRUGO); | ||
31 | MODULE_PARM_DESC(rtap_include_phy_info, | ||
32 | " Include PHY info in the radiotap header, default - no"); | ||
33 | |||
34 | static inline int wil_vring_is_empty(struct vring *vring) | ||
35 | { | ||
36 | return vring->swhead == vring->swtail; | ||
37 | } | ||
38 | |||
39 | static inline u32 wil_vring_next_tail(struct vring *vring) | ||
40 | { | ||
41 | return (vring->swtail + 1) % vring->size; | ||
42 | } | ||
43 | |||
44 | static inline void wil_vring_advance_head(struct vring *vring, int n) | ||
45 | { | ||
46 | vring->swhead = (vring->swhead + n) % vring->size; | ||
47 | } | ||
48 | |||
49 | static inline int wil_vring_is_full(struct vring *vring) | ||
50 | { | ||
51 | return wil_vring_next_tail(vring) == vring->swhead; | ||
52 | } | ||
53 | /* | ||
54 | * Available space in Tx Vring | ||
55 | */ | ||
56 | static inline int wil_vring_avail_tx(struct vring *vring) | ||
57 | { | ||
58 | u32 swhead = vring->swhead; | ||
59 | u32 swtail = vring->swtail; | ||
60 | int used = (vring->size + swhead - swtail) % vring->size; | ||
61 | |||
62 | return vring->size - used - 1; | ||
63 | } | ||
64 | |||
65 | static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) | ||
66 | { | ||
67 | struct device *dev = wil_to_dev(wil); | ||
68 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
69 | uint i; | ||
70 | |||
71 | BUILD_BUG_ON(sizeof(vring->va[0]) != 32); | ||
72 | |||
73 | vring->swhead = 0; | ||
74 | vring->swtail = 0; | ||
75 | vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); | ||
76 | if (!vring->ctx) { | ||
77 | wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", | ||
78 | vring->size); | ||
79 | vring->va = NULL; | ||
80 | return -ENOMEM; | ||
81 | } | ||
82 | /* | ||
83 | * vring->va should be aligned on its size rounded up to power of 2 | ||
84 | * This is granted by the dma_alloc_coherent | ||
85 | */ | ||
86 | vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); | ||
87 | if (!vring->va) { | ||
88 | wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", | ||
89 | vring->size); | ||
90 | kfree(vring->ctx); | ||
91 | vring->ctx = NULL; | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | /* initially, all descriptors are SW owned | ||
95 | * For Tx and Rx, ownership bit is at the same location, thus | ||
96 | * we can use any | ||
97 | */ | ||
98 | for (i = 0; i < vring->size; i++) { | ||
99 | volatile struct vring_tx_desc *d = &(vring->va[i].tx); | ||
100 | d->dma.status = TX_DMA_STATUS_DU; | ||
101 | } | ||
102 | |||
103 | wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, | ||
104 | vring->va, (unsigned long long)vring->pa, vring->ctx); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, | ||
110 | int tx) | ||
111 | { | ||
112 | struct device *dev = wil_to_dev(wil); | ||
113 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
114 | |||
115 | while (!wil_vring_is_empty(vring)) { | ||
116 | if (tx) { | ||
117 | volatile struct vring_tx_desc *d = | ||
118 | &vring->va[vring->swtail].tx; | ||
119 | dma_addr_t pa = d->dma.addr_low | | ||
120 | ((u64)d->dma.addr_high << 32); | ||
121 | struct sk_buff *skb = vring->ctx[vring->swtail]; | ||
122 | if (skb) { | ||
123 | dma_unmap_single(dev, pa, d->dma.length, | ||
124 | DMA_TO_DEVICE); | ||
125 | dev_kfree_skb_any(skb); | ||
126 | vring->ctx[vring->swtail] = NULL; | ||
127 | } else { | ||
128 | dma_unmap_page(dev, pa, d->dma.length, | ||
129 | DMA_TO_DEVICE); | ||
130 | } | ||
131 | vring->swtail = wil_vring_next_tail(vring); | ||
132 | } else { /* rx */ | ||
133 | volatile struct vring_rx_desc *d = | ||
134 | &vring->va[vring->swtail].rx; | ||
135 | dma_addr_t pa = d->dma.addr_low | | ||
136 | ((u64)d->dma.addr_high << 32); | ||
137 | struct sk_buff *skb = vring->ctx[vring->swhead]; | ||
138 | dma_unmap_single(dev, pa, d->dma.length, | ||
139 | DMA_FROM_DEVICE); | ||
140 | kfree_skb(skb); | ||
141 | wil_vring_advance_head(vring, 1); | ||
142 | } | ||
143 | } | ||
144 | dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); | ||
145 | kfree(vring->ctx); | ||
146 | vring->pa = 0; | ||
147 | vring->va = NULL; | ||
148 | vring->ctx = NULL; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Allocate one skb for Rx VRING | ||
153 | * | ||
154 | * Safe to call from IRQ | ||
155 | */ | ||
156 | static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | ||
157 | u32 i, int headroom) | ||
158 | { | ||
159 | struct device *dev = wil_to_dev(wil); | ||
160 | unsigned int sz = RX_BUF_LEN; | ||
161 | volatile struct vring_rx_desc *d = &(vring->va[i].rx); | ||
162 | dma_addr_t pa; | ||
163 | |||
164 | /* TODO align */ | ||
165 | struct sk_buff *skb = dev_alloc_skb(sz + headroom); | ||
166 | if (unlikely(!skb)) | ||
167 | return -ENOMEM; | ||
168 | |||
169 | skb_reserve(skb, headroom); | ||
170 | skb_put(skb, sz); | ||
171 | |||
172 | pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); | ||
173 | if (unlikely(dma_mapping_error(dev, pa))) { | ||
174 | kfree_skb(skb); | ||
175 | return -ENOMEM; | ||
176 | } | ||
177 | |||
178 | d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; | ||
179 | d->dma.addr_low = lower_32_bits(pa); | ||
180 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
181 | /* ip_length don't care */ | ||
182 | /* b11 don't care */ | ||
183 | /* error don't care */ | ||
184 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
185 | d->dma.length = sz; | ||
186 | vring->ctx[i] = skb; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * Adds radiotap header | ||
193 | * | ||
194 | * Any error indicated as "Bad FCS" | ||
195 | * | ||
196 | * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: | ||
197 | * - Rx descriptor: 32 bytes | ||
198 | * - Phy info | ||
199 | */ | ||
200 | static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, | ||
201 | struct sk_buff *skb, | ||
202 | volatile struct vring_rx_desc *d) | ||
203 | { | ||
204 | struct wireless_dev *wdev = wil->wdev; | ||
205 | struct wil6210_rtap { | ||
206 | struct ieee80211_radiotap_header rthdr; | ||
207 | /* fields should be in the order of bits in rthdr.it_present */ | ||
208 | /* flags */ | ||
209 | u8 flags; | ||
210 | /* channel */ | ||
211 | __le16 chnl_freq __aligned(2); | ||
212 | __le16 chnl_flags; | ||
213 | /* MCS */ | ||
214 | u8 mcs_present; | ||
215 | u8 mcs_flags; | ||
216 | u8 mcs_index; | ||
217 | } __packed; | ||
218 | struct wil6210_rtap_vendor { | ||
219 | struct wil6210_rtap rtap; | ||
220 | /* vendor */ | ||
221 | u8 vendor_oui[3] __aligned(2); | ||
222 | u8 vendor_ns; | ||
223 | __le16 vendor_skip; | ||
224 | u8 vendor_data[0]; | ||
225 | } __packed; | ||
226 | struct wil6210_rtap_vendor *rtap_vendor; | ||
227 | int rtap_len = sizeof(struct wil6210_rtap); | ||
228 | int phy_length = 0; /* phy info header size, bytes */ | ||
229 | static char phy_data[128]; | ||
230 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
231 | |||
232 | if (rtap_include_phy_info) { | ||
233 | rtap_len = sizeof(*rtap_vendor) + sizeof(*d); | ||
234 | /* calculate additional length */ | ||
235 | if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { | ||
236 | /** | ||
237 | * PHY info starts from 8-byte boundary | ||
238 | * there are 8-byte lines, last line may be partially | ||
239 | * written (HW bug), thus FW configures for last line | ||
240 | * to be excessive. Driver skips this last line. | ||
241 | */ | ||
242 | int len = min_t(int, 8 + sizeof(phy_data), | ||
243 | wil_rxdesc_phy_length(d)); | ||
244 | if (len > 8) { | ||
245 | void *p = skb_tail_pointer(skb); | ||
246 | void *pa = PTR_ALIGN(p, 8); | ||
247 | if (skb_tailroom(skb) >= len + (pa - p)) { | ||
248 | phy_length = len - 8; | ||
249 | memcpy(phy_data, pa, phy_length); | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | rtap_len += phy_length; | ||
254 | } | ||
255 | |||
256 | if (skb_headroom(skb) < rtap_len && | ||
257 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { | ||
258 | wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | rtap_vendor = (void *)skb_push(skb, rtap_len); | ||
263 | memset(rtap_vendor, 0, rtap_len); | ||
264 | |||
265 | rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
266 | rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); | ||
267 | rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( | ||
268 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
269 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
270 | (1 << IEEE80211_RADIOTAP_MCS)); | ||
271 | if (d->dma.status & RX_DMA_STATUS_ERROR) | ||
272 | rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; | ||
273 | |||
274 | rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); | ||
275 | rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); | ||
276 | |||
277 | rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; | ||
278 | rtap_vendor->rtap.mcs_flags = 0; | ||
279 | rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); | ||
280 | |||
281 | if (rtap_include_phy_info) { | ||
282 | rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << | ||
283 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE); | ||
284 | /* OUI for Wilocity 04:ce:14 */ | ||
285 | rtap_vendor->vendor_oui[0] = 0x04; | ||
286 | rtap_vendor->vendor_oui[1] = 0xce; | ||
287 | rtap_vendor->vendor_oui[2] = 0x14; | ||
288 | rtap_vendor->vendor_ns = 1; | ||
289 | /* Rx descriptor + PHY data */ | ||
290 | rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + | ||
291 | phy_length); | ||
292 | memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); | ||
293 | memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, | ||
294 | phy_length); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Fast swap in place between 2 registers | ||
300 | */ | ||
301 | static void wil_swap_u16(u16 *a, u16 *b) | ||
302 | { | ||
303 | *a ^= *b; | ||
304 | *b ^= *a; | ||
305 | *a ^= *b; | ||
306 | } | ||
307 | |||
308 | static void wil_swap_ethaddr(void *data) | ||
309 | { | ||
310 | struct ethhdr *eth = data; | ||
311 | u16 *s = (u16 *)eth->h_source; | ||
312 | u16 *d = (u16 *)eth->h_dest; | ||
313 | |||
314 | wil_swap_u16(s++, d++); | ||
315 | wil_swap_u16(s++, d++); | ||
316 | wil_swap_u16(s, d); | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * reap 1 frame from @swhead | ||
321 | * | ||
322 | * Safe to call from IRQ | ||
323 | */ | ||
324 | static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | ||
325 | struct vring *vring) | ||
326 | { | ||
327 | struct device *dev = wil_to_dev(wil); | ||
328 | struct net_device *ndev = wil_to_ndev(wil); | ||
329 | volatile struct vring_rx_desc *d; | ||
330 | struct sk_buff *skb; | ||
331 | dma_addr_t pa; | ||
332 | unsigned int sz = RX_BUF_LEN; | ||
333 | u8 ftype; | ||
334 | u8 ds_bits; | ||
335 | |||
336 | if (wil_vring_is_empty(vring)) | ||
337 | return NULL; | ||
338 | |||
339 | d = &(vring->va[vring->swhead].rx); | ||
340 | if (!(d->dma.status & RX_DMA_STATUS_DU)) { | ||
341 | /* it is not error, we just reached end of Rx done area */ | ||
342 | return NULL; | ||
343 | } | ||
344 | |||
345 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
346 | skb = vring->ctx[vring->swhead]; | ||
347 | dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); | ||
348 | skb_trim(skb, d->dma.length); | ||
349 | |||
350 | wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); | ||
351 | |||
352 | /* use radiotap header only if required */ | ||
353 | if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) | ||
354 | wil_rx_add_radiotap_header(wil, skb, d); | ||
355 | |||
356 | wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); | ||
357 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, | ||
358 | (const void *)d, sizeof(*d), false); | ||
359 | |||
360 | wil_vring_advance_head(vring, 1); | ||
361 | |||
362 | /* no extra checks if in sniffer mode */ | ||
363 | if (ndev->type != ARPHRD_ETHER) | ||
364 | return skb; | ||
365 | /* | ||
366 | * Non-data frames may be delivered through Rx DMA channel (ex: BAR) | ||
367 | * Driver should recognize it by frame type, that is found | ||
368 | * in Rx descriptor. If type is not data, it is 802.11 frame as is | ||
369 | */ | ||
370 | ftype = wil_rxdesc_ftype(d) << 2; | ||
371 | if (ftype != IEEE80211_FTYPE_DATA) { | ||
372 | wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); | ||
373 | /* TODO: process it */ | ||
374 | kfree_skb(skb); | ||
375 | return NULL; | ||
376 | } | ||
377 | |||
378 | if (skb->len < ETH_HLEN) { | ||
379 | wil_err(wil, "Short frame, len = %d\n", skb->len); | ||
380 | /* TODO: process it (i.e. BAR) */ | ||
381 | kfree_skb(skb); | ||
382 | return NULL; | ||
383 | } | ||
384 | |||
385 | ds_bits = wil_rxdesc_ds_bits(d); | ||
386 | if (ds_bits == 1) { | ||
387 | /* | ||
388 | * HW bug - in ToDS mode, i.e. Rx on AP side, | ||
389 | * addresses get swapped | ||
390 | */ | ||
391 | wil_swap_ethaddr(skb->data); | ||
392 | } | ||
393 | |||
394 | return skb; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * allocate and fill up to @count buffers in rx ring | ||
399 | * buffers posted at @swtail | ||
400 | */ | ||
401 | static int wil_rx_refill(struct wil6210_priv *wil, int count) | ||
402 | { | ||
403 | struct net_device *ndev = wil_to_ndev(wil); | ||
404 | struct vring *v = &wil->vring_rx; | ||
405 | u32 next_tail; | ||
406 | int rc = 0; | ||
407 | int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? | ||
408 | WIL6210_RTAP_SIZE : 0; | ||
409 | |||
410 | for (; next_tail = wil_vring_next_tail(v), | ||
411 | (next_tail != v->swhead) && (count-- > 0); | ||
412 | v->swtail = next_tail) { | ||
413 | rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); | ||
414 | if (rc) { | ||
415 | wil_err(wil, "Error %d in wil_rx_refill[%d]\n", | ||
416 | rc, v->swtail); | ||
417 | break; | ||
418 | } | ||
419 | } | ||
420 | iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); | ||
421 | |||
422 | return rc; | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * Pass Rx packet to the netif. Update statistics. | ||
427 | */ | ||
428 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | ||
429 | { | ||
430 | int rc; | ||
431 | unsigned int len = skb->len; | ||
432 | |||
433 | if (in_interrupt()) | ||
434 | rc = netif_rx(skb); | ||
435 | else | ||
436 | rc = netif_rx_ni(skb); | ||
437 | |||
438 | if (likely(rc == NET_RX_SUCCESS)) { | ||
439 | ndev->stats.rx_packets++; | ||
440 | ndev->stats.rx_bytes += len; | ||
441 | |||
442 | } else { | ||
443 | ndev->stats.rx_dropped++; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * Proceed all completed skb's from Rx VRING | ||
449 | * | ||
450 | * Safe to call from IRQ | ||
451 | */ | ||
452 | void wil_rx_handle(struct wil6210_priv *wil) | ||
453 | { | ||
454 | struct net_device *ndev = wil_to_ndev(wil); | ||
455 | struct vring *v = &wil->vring_rx; | ||
456 | struct sk_buff *skb; | ||
457 | |||
458 | if (!v->va) { | ||
459 | wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); | ||
460 | return; | ||
461 | } | ||
462 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
463 | while (NULL != (skb = wil_vring_reap_rx(wil, v))) { | ||
464 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb_headlen(skb), false); | ||
466 | |||
467 | skb_orphan(skb); | ||
468 | |||
469 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
470 | skb->dev = ndev; | ||
471 | skb_reset_mac_header(skb); | ||
472 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
473 | skb->pkt_type = PACKET_OTHERHOST; | ||
474 | skb->protocol = htons(ETH_P_802_2); | ||
475 | |||
476 | } else { | ||
477 | skb->protocol = eth_type_trans(skb, ndev); | ||
478 | } | ||
479 | |||
480 | wil_netif_rx_any(skb, ndev); | ||
481 | } | ||
482 | wil_rx_refill(wil, v->size); | ||
483 | } | ||
484 | |||
485 | int wil_rx_init(struct wil6210_priv *wil) | ||
486 | { | ||
487 | struct net_device *ndev = wil_to_ndev(wil); | ||
488 | struct wireless_dev *wdev = wil->wdev; | ||
489 | struct vring *vring = &wil->vring_rx; | ||
490 | int rc; | ||
491 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
492 | .action = WMI_RX_CHAIN_ADD, | ||
493 | .rx_sw_ring = { | ||
494 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
495 | }, | ||
496 | .mid = 0, /* TODO - what is it? */ | ||
497 | .decap_trans_type = WMI_DECAP_TYPE_802_3, | ||
498 | }; | ||
499 | struct { | ||
500 | struct wil6210_mbox_hdr_wmi wmi; | ||
501 | struct wmi_cfg_rx_chain_done_event evt; | ||
502 | } __packed evt; | ||
503 | |||
504 | vring->size = WIL6210_RX_RING_SIZE; | ||
505 | rc = wil_vring_alloc(wil, vring); | ||
506 | if (rc) | ||
507 | return rc; | ||
508 | |||
509 | cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
510 | cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
511 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
512 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
513 | |||
514 | cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); | ||
515 | if (ch) | ||
516 | cmd.sniffer_cfg.channel = ch->hw_value - 1; | ||
517 | cmd.sniffer_cfg.phy_info_mode = | ||
518 | cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); | ||
519 | cmd.sniffer_cfg.phy_support = | ||
520 | cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) | ||
521 | ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); | ||
522 | } | ||
523 | /* typical time for secure PCP is 840ms */ | ||
524 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
525 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | ||
526 | if (rc) | ||
527 | goto err_free; | ||
528 | |||
529 | vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); | ||
530 | |||
531 | wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", | ||
532 | le32_to_cpu(evt.evt.status), vring->hwtail); | ||
533 | |||
534 | rc = wil_rx_refill(wil, vring->size); | ||
535 | if (rc) | ||
536 | goto err_free; | ||
537 | |||
538 | return 0; | ||
539 | err_free: | ||
540 | wil_vring_free(wil, vring, 0); | ||
541 | |||
542 | return rc; | ||
543 | } | ||
544 | |||
545 | void wil_rx_fini(struct wil6210_priv *wil) | ||
546 | { | ||
547 | struct vring *vring = &wil->vring_rx; | ||
548 | |||
549 | if (vring->va) { | ||
550 | int rc; | ||
551 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
552 | .action = cpu_to_le32(WMI_RX_CHAIN_DEL), | ||
553 | .rx_sw_ring = { | ||
554 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
555 | }, | ||
556 | }; | ||
557 | struct { | ||
558 | struct wil6210_mbox_hdr_wmi wmi; | ||
559 | struct wmi_cfg_rx_chain_done_event cfg; | ||
560 | } __packed wmi_rx_cfg_reply; | ||
561 | |||
562 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
563 | WMI_CFG_RX_CHAIN_DONE_EVENTID, | ||
564 | &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), | ||
565 | 100); | ||
566 | wil_vring_free(wil, vring, 0); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
571 | int cid, int tid) | ||
572 | { | ||
573 | int rc; | ||
574 | struct wmi_vring_cfg_cmd cmd = { | ||
575 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | ||
576 | .vring_cfg = { | ||
577 | .tx_sw_ring = { | ||
578 | .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), | ||
579 | }, | ||
580 | .ringid = id, | ||
581 | .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), | ||
582 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | ||
583 | .mac_ctrl = 0, | ||
584 | .to_resolution = 0, | ||
585 | .agg_max_wsize = 16, | ||
586 | .schd_params = { | ||
587 | .priority = cpu_to_le16(0), | ||
588 | .timeslot_us = cpu_to_le16(0xfff), | ||
589 | }, | ||
590 | }, | ||
591 | }; | ||
592 | struct { | ||
593 | struct wil6210_mbox_hdr_wmi wmi; | ||
594 | struct wmi_vring_cfg_done_event cmd; | ||
595 | } __packed reply; | ||
596 | struct vring *vring = &wil->vring_tx[id]; | ||
597 | |||
598 | if (vring->va) { | ||
599 | wil_err(wil, "Tx ring [%d] already allocated\n", id); | ||
600 | rc = -EINVAL; | ||
601 | goto out; | ||
602 | } | ||
603 | |||
604 | vring->size = size; | ||
605 | rc = wil_vring_alloc(wil, vring); | ||
606 | if (rc) | ||
607 | goto out; | ||
608 | |||
609 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
610 | cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
611 | |||
612 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), | ||
613 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
614 | if (rc) | ||
615 | goto out_free; | ||
616 | |||
617 | if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { | ||
618 | wil_err(wil, "Tx config failed, status 0x%02x\n", | ||
619 | reply.cmd.status); | ||
620 | goto out_free; | ||
621 | } | ||
622 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | ||
623 | |||
624 | return 0; | ||
625 | out_free: | ||
626 | wil_vring_free(wil, vring, 1); | ||
627 | out: | ||
628 | |||
629 | return rc; | ||
630 | } | ||
631 | |||
632 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | ||
633 | { | ||
634 | struct vring *vring = &wil->vring_tx[id]; | ||
635 | |||
636 | if (!vring->va) | ||
637 | return; | ||
638 | |||
639 | wil_vring_free(wil, vring, 1); | ||
640 | } | ||
641 | |||
642 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | ||
643 | struct sk_buff *skb) | ||
644 | { | ||
645 | struct vring *v = &wil->vring_tx[0]; | ||
646 | |||
647 | if (v->va) | ||
648 | return v; | ||
649 | |||
650 | return NULL; | ||
651 | } | ||
652 | |||
653 | static int wil_tx_desc_map(volatile struct vring_tx_desc *d, | ||
654 | dma_addr_t pa, u32 len) | ||
655 | { | ||
656 | d->dma.addr_low = lower_32_bits(pa); | ||
657 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
658 | d->dma.ip_length = 0; | ||
659 | /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ | ||
660 | d->dma.b11 = 0/*14 | BIT(7)*/; | ||
661 | d->dma.error = 0; | ||
662 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
663 | d->dma.length = len; | ||
664 | d->dma.d0 = 0; | ||
665 | d->mac.d[0] = 0; | ||
666 | d->mac.d[1] = 0; | ||
667 | d->mac.d[2] = 0; | ||
668 | d->mac.ucode_cmd = 0; | ||
669 | /* use dst index 0 */ | ||
670 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | | ||
671 | (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); | ||
672 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ | ||
673 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | | ||
674 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | ||
680 | struct sk_buff *skb) | ||
681 | { | ||
682 | struct device *dev = wil_to_dev(wil); | ||
683 | volatile struct vring_tx_desc *d; | ||
684 | u32 swhead = vring->swhead; | ||
685 | int avail = wil_vring_avail_tx(vring); | ||
686 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
687 | uint f; | ||
688 | int vring_index = vring - wil->vring_tx; | ||
689 | uint i = swhead; | ||
690 | dma_addr_t pa; | ||
691 | |||
692 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
693 | |||
694 | if (avail < vring->size/8) | ||
695 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
696 | if (avail < 1 + nr_frags) { | ||
697 | wil_err(wil, "Tx ring full. No space for %d fragments\n", | ||
698 | 1 + nr_frags); | ||
699 | return -ENOMEM; | ||
700 | } | ||
701 | d = &(vring->va[i].tx); | ||
702 | |||
703 | /* FIXME FW can accept only unicast frames for the peer */ | ||
704 | memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); | ||
705 | |||
706 | pa = dma_map_single(dev, skb->data, | ||
707 | skb_headlen(skb), DMA_TO_DEVICE); | ||
708 | |||
709 | wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), | ||
710 | skb->data, (unsigned long long)pa); | ||
711 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
712 | skb->data, skb_headlen(skb), false); | ||
713 | |||
714 | if (unlikely(dma_mapping_error(dev, pa))) | ||
715 | return -EINVAL; | ||
716 | /* 1-st segment */ | ||
717 | wil_tx_desc_map(d, pa, skb_headlen(skb)); | ||
718 | d->mac.d[2] |= ((nr_frags + 1) << | ||
719 | MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); | ||
720 | /* middle segments */ | ||
721 | for (f = 0; f < nr_frags; f++) { | ||
722 | const struct skb_frag_struct *frag = | ||
723 | &skb_shinfo(skb)->frags[f]; | ||
724 | int len = skb_frag_size(frag); | ||
725 | i = (swhead + f + 1) % vring->size; | ||
726 | d = &(vring->va[i].tx); | ||
727 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | ||
728 | DMA_TO_DEVICE); | ||
729 | if (unlikely(dma_mapping_error(dev, pa))) | ||
730 | goto dma_error; | ||
731 | wil_tx_desc_map(d, pa, len); | ||
732 | vring->ctx[i] = NULL; | ||
733 | } | ||
734 | /* for the last seg only */ | ||
735 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); | ||
736 | d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ | ||
737 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); | ||
738 | d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); | ||
739 | |||
740 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, | ||
741 | (const void *)d, sizeof(*d), false); | ||
742 | |||
743 | /* advance swhead */ | ||
744 | wil_vring_advance_head(vring, nr_frags + 1); | ||
745 | wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); | ||
746 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); | ||
747 | /* hold reference to skb | ||
748 | * to prevent skb release before accounting | ||
749 | * in case of immediate "tx done" | ||
750 | */ | ||
751 | vring->ctx[i] = skb_get(skb); | ||
752 | |||
753 | return 0; | ||
754 | dma_error: | ||
755 | /* unmap what we have mapped */ | ||
756 | /* Note: increment @f to operate with positive index */ | ||
757 | for (f++; f > 0; f--) { | ||
758 | i = (swhead + f) % vring->size; | ||
759 | d = &(vring->va[i].tx); | ||
760 | d->dma.status = TX_DMA_STATUS_DU; | ||
761 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
762 | if (vring->ctx[i]) | ||
763 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
764 | else | ||
765 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
766 | } | ||
767 | |||
768 | return -EINVAL; | ||
769 | } | ||
770 | |||
771 | |||
772 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
773 | { | ||
774 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
775 | struct vring *vring; | ||
776 | int rc; | ||
777 | |||
778 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
779 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
780 | wil_err(wil, "FW not ready\n"); | ||
781 | goto drop; | ||
782 | } | ||
783 | if (!test_bit(wil_status_fwconnected, &wil->status)) { | ||
784 | wil_err(wil, "FW not connected\n"); | ||
785 | goto drop; | ||
786 | } | ||
787 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
788 | wil_err(wil, "Xmit in monitor mode not supported\n"); | ||
789 | goto drop; | ||
790 | } | ||
791 | if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { | ||
792 | rc = wmi_tx_eapol(wil, skb); | ||
793 | } else { | ||
794 | /* find vring */ | ||
795 | vring = wil_find_tx_vring(wil, skb); | ||
796 | if (!vring) { | ||
797 | wil_err(wil, "No Tx VRING available\n"); | ||
798 | goto drop; | ||
799 | } | ||
800 | /* set up vring entry */ | ||
801 | rc = wil_tx_vring(wil, vring, skb); | ||
802 | } | ||
803 | switch (rc) { | ||
804 | case 0: | ||
805 | ndev->stats.tx_packets++; | ||
806 | ndev->stats.tx_bytes += skb->len; | ||
807 | dev_kfree_skb_any(skb); | ||
808 | return NETDEV_TX_OK; | ||
809 | case -ENOMEM: | ||
810 | return NETDEV_TX_BUSY; | ||
811 | default: | ||
812 | ; /* goto drop; */ | ||
813 | break; | ||
814 | } | ||
815 | drop: | ||
816 | netif_tx_stop_all_queues(ndev); | ||
817 | ndev->stats.tx_dropped++; | ||
818 | dev_kfree_skb_any(skb); | ||
819 | |||
820 | return NET_XMIT_DROP; | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * Clean up transmitted skb's from the Tx VRING | ||
825 | * | ||
826 | * Safe to call from IRQ | ||
827 | */ | ||
828 | void wil_tx_complete(struct wil6210_priv *wil, int ringid) | ||
829 | { | ||
830 | struct device *dev = wil_to_dev(wil); | ||
831 | struct vring *vring = &wil->vring_tx[ringid]; | ||
832 | |||
833 | if (!vring->va) { | ||
834 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); | ||
835 | return; | ||
836 | } | ||
837 | |||
838 | wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); | ||
839 | |||
840 | while (!wil_vring_is_empty(vring)) { | ||
841 | volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; | ||
842 | dma_addr_t pa; | ||
843 | struct sk_buff *skb; | ||
844 | if (!(d->dma.status & TX_DMA_STATUS_DU)) | ||
845 | break; | ||
846 | |||
847 | wil_dbg_TXRX(wil, | ||
848 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | ||
849 | vring->swtail, d->dma.length, d->dma.status, | ||
850 | d->dma.error); | ||
851 | wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, | ||
852 | (const void *)d, sizeof(*d), false); | ||
853 | |||
854 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
855 | skb = vring->ctx[vring->swtail]; | ||
856 | if (skb) { | ||
857 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
858 | dev_kfree_skb_any(skb); | ||
859 | vring->ctx[vring->swtail] = NULL; | ||
860 | } else { | ||
861 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
862 | } | ||
863 | d->dma.addr_low = 0; | ||
864 | d->dma.addr_high = 0; | ||
865 | d->dma.length = 0; | ||
866 | d->dma.status = TX_DMA_STATUS_DU; | ||
867 | vring->swtail = wil_vring_next_tail(vring); | ||
868 | } | ||
869 | if (wil_vring_avail_tx(vring) > vring->size/4) | ||
870 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | ||
871 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h new file mode 100644 index 000000000000..45a61f597c5c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef WIL6210_TXRX_H | ||
18 | #define WIL6210_TXRX_H | ||
19 | |||
20 | #define BUF_SW_OWNED (1) | ||
21 | #define BUF_HW_OWNED (0) | ||
22 | |||
23 | /* size of max. Rx packet */ | ||
24 | #define RX_BUF_LEN (2048) | ||
25 | #define TX_BUF_LEN (2048) | ||
26 | /* how many bytes to reserve for rtap header? */ | ||
27 | #define WIL6210_RTAP_SIZE (128) | ||
28 | |||
29 | /* Tx/Rx path */ | ||
30 | /* | ||
31 | * Tx descriptor - MAC part | ||
32 | * [dword 0] | ||
33 | * bit 0.. 9 : lifetime_expiry_value:10 | ||
34 | * bit 10 : interrup_en:1 | ||
35 | * bit 11 : status_en:1 | ||
36 | * bit 12..13 : txss_override:2 | ||
37 | * bit 14 : timestamp_insertion:1 | ||
38 | * bit 15 : duration_preserve:1 | ||
39 | * bit 16..21 : reserved0:6 | ||
40 | * bit 22..26 : mcs_index:5 | ||
41 | * bit 27 : mcs_en:1 | ||
42 | * bit 28..29 : reserved1:2 | ||
43 | * bit 30 : reserved2:1 | ||
44 | * bit 31 : sn_preserved:1 | ||
45 | * [dword 1] | ||
46 | * bit 0.. 3 : pkt_mode:4 | ||
47 | * bit 4 : pkt_mode_en:1 | ||
48 | * bit 5.. 7 : reserved0:3 | ||
49 | * bit 8..13 : reserved1:6 | ||
50 | * bit 14 : reserved2:1 | ||
51 | * bit 15 : ack_policy_en:1 | ||
52 | * bit 16..19 : dst_index:4 | ||
53 | * bit 20 : dst_index_en:1 | ||
54 | * bit 21..22 : ack_policy:2 | ||
55 | * bit 23 : lifetime_en:1 | ||
56 | * bit 24..30 : max_retry:7 | ||
57 | * bit 31 : max_retry_en:1 | ||
58 | * [dword 2] | ||
59 | * bit 0.. 7 : num_of_descriptors:8 | ||
60 | * bit 8..17 : reserved:10 | ||
61 | * bit 18..19 : l2_translation_type:2 | ||
62 | * bit 20 : snap_hdr_insertion_en:1 | ||
63 | * bit 21 : vlan_removal_en:1 | ||
64 | * bit 22..31 : reserved0:10 | ||
65 | * [dword 3] | ||
66 | * bit 0.. 31: ucode_cmd:32 | ||
67 | */ | ||
68 | struct vring_tx_mac { | ||
69 | u32 d[3]; | ||
70 | u32 ucode_cmd; | ||
71 | } __packed; | ||
72 | |||
73 | /* TX MAC Dword 0 */ | ||
74 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 | ||
75 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 | ||
76 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF | ||
77 | |||
78 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 | ||
79 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 | ||
80 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 | ||
81 | |||
82 | #define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 | ||
83 | #define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 | ||
84 | #define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 | ||
85 | |||
86 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 | ||
87 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 | ||
88 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 | ||
89 | |||
90 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 | ||
91 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 | ||
92 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 | ||
93 | |||
94 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 | ||
95 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 | ||
96 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 | ||
97 | |||
98 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 | ||
99 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 | ||
100 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 | ||
101 | |||
102 | #define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 | ||
103 | #define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 | ||
104 | #define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 | ||
105 | |||
106 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 | ||
107 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 | ||
108 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 | ||
109 | |||
110 | /* TX MAC Dword 1 */ | ||
111 | #define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 | ||
112 | #define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 | ||
113 | #define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF | ||
114 | |||
115 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 | ||
116 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 | ||
117 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 | ||
118 | |||
119 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 | ||
120 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 | ||
121 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 | ||
122 | |||
123 | #define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 | ||
124 | #define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 | ||
125 | #define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 | ||
126 | |||
127 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 | ||
128 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 | ||
129 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 | ||
130 | |||
131 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 | ||
132 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 | ||
133 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 | ||
134 | |||
135 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 | ||
136 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 | ||
137 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 | ||
138 | |||
139 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 | ||
140 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 | ||
141 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 | ||
142 | |||
143 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 | ||
144 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 | ||
145 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 | ||
146 | |||
147 | /* TX MAC Dword 2 */ | ||
148 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 | ||
149 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 | ||
150 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF | ||
151 | |||
152 | #define MAC_CFG_DESC_TX_2_RESERVED_POS 8 | ||
153 | #define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 | ||
154 | #define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 | ||
155 | |||
156 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 | ||
157 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 | ||
158 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 | ||
159 | |||
160 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 | ||
161 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 | ||
162 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 | ||
163 | |||
164 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 | ||
165 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 | ||
166 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 | ||
167 | |||
168 | /* TX MAC Dword 3 */ | ||
169 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 | ||
170 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 | ||
171 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF | ||
172 | |||
173 | /* TX DMA Dword 0 */ | ||
174 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 | ||
175 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 | ||
176 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF | ||
177 | |||
178 | #define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 | ||
179 | #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 | ||
180 | #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 | ||
181 | |||
182 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 | ||
183 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 | ||
184 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 | ||
185 | |||
186 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 | ||
187 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 | ||
188 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 | ||
189 | |||
190 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 | ||
191 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 | ||
192 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 | ||
193 | |||
194 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 | ||
195 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 | ||
196 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 | ||
197 | |||
198 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 | ||
199 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 | ||
200 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 | ||
201 | |||
202 | #define DMA_CFG_DESC_TX_0_QID_POS 16 | ||
203 | #define DMA_CFG_DESC_TX_0_QID_LEN 5 | ||
204 | #define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 | ||
205 | |||
206 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 | ||
207 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 | ||
208 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 | ||
209 | |||
210 | #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 | ||
211 | #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 | ||
212 | #define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 | ||
213 | |||
214 | |||
215 | #define TX_DMA_STATUS_DU BIT(0) | ||
216 | |||
217 | struct vring_tx_dma { | ||
218 | u32 d0; | ||
219 | u32 addr_low; | ||
220 | u16 addr_high; | ||
221 | u8 ip_length; | ||
222 | u8 b11; /* 0..6: mac_length; 7:ip_version */ | ||
223 | u8 error; /* 0..2: err; 3..7: reserved; */ | ||
224 | u8 status; /* 0: used; 1..7; reserved */ | ||
225 | u16 length; | ||
226 | } __packed; | ||
227 | |||
228 | /* | ||
229 | * Rx descriptor - MAC part | ||
230 | * [dword 0] | ||
231 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field | ||
232 | * bit 4.. 6 : connection_id:3 :The Source index that was found during | ||
233 | * Parsing the TA. This field is used to define the source of the packet | ||
234 | * bit 7 : reserved:1 | ||
235 | * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) | ||
236 | * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type | ||
237 | * (management, data, control and extension) | ||
238 | * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype | ||
239 | * bit 16..27 : seq_number:12 The received Sequence number field | ||
240 | * bit 28..31 : extended:4 extended subtype | ||
241 | * [dword 1] | ||
242 | * bit 0.. 3 : reserved | ||
243 | * bit 4.. 5 : key_id:2 | ||
244 | * bit 6 : decrypt_bypass:1 | ||
245 | * bit 7 : security:1 | ||
246 | * bit 8.. 9 : ds_bits:2 | ||
247 | * bit 10 : a_msdu_present:1 from qos header | ||
248 | * bit 11 : a_msdu_type:1 from qos header | ||
249 | * bit 12 : a_mpdu:1 part of AMPDU aggregation | ||
250 | * bit 13 : broadcast:1 | ||
251 | * bit 14 : mutlicast:1 | ||
252 | * bit 15 : reserved:1 | ||
253 | * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet | ||
254 | * is received from | ||
255 | * bit 21..24 : mcs:4 | ||
256 | * bit 25..28 : mic_icr:4 | ||
257 | * bit 29..31 : reserved:3 | ||
258 | * [dword 2] | ||
259 | * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received | ||
260 | * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version | ||
261 | * bit 4 : fc_order:1 The FC Control (b15) -Order | ||
262 | * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field | ||
263 | * bit 8 : esop:1 The QoS (b4) ESOP field | ||
264 | * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field | ||
265 | * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field | ||
266 | * bit 15 : qos_ac_constraint:1 | ||
267 | * bit 16..31 : pn_15_0:16 low 2 bytes of PN | ||
268 | * [dword 3] | ||
269 | * bit 0..31 : pn_47_16:32 high 4 bytes of PN | ||
270 | */ | ||
271 | struct vring_rx_mac { | ||
272 | u32 d0; | ||
273 | u32 d1; | ||
274 | u16 w4; | ||
275 | u16 pn_15_0; | ||
276 | u32 pn_47_16; | ||
277 | } __packed; | ||
278 | |||
279 | /* | ||
280 | * Rx descriptor - DMA part | ||
281 | * [dword 0] | ||
282 | * bit 0.. 7 : l4_length:8 layer 4 length | ||
283 | * bit 8.. 9 : reserved:2 | ||
284 | * bit 10 : cmd_dma_it:1 | ||
285 | * bit 11..15 : reserved:5 | ||
286 | * bit 16..29 : phy_info_length:14 | ||
287 | * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field | ||
288 | * [dword 1] | ||
289 | * bit 0..31 : addr_low:32 The payload buffer low address | ||
290 | * [dword 2] | ||
291 | * bit 0..15 : addr_high:16 The payload buffer high address | ||
292 | * bit 16..23 : ip_length:8 | ||
293 | * bit 24..30 : mac_length:7 | ||
294 | * bit 31 : ip_version:1 | ||
295 | * [dword 3] | ||
296 | * [byte 12] error | ||
297 | * [byte 13] status | ||
298 | * bit 0 : du:1 | ||
299 | * bit 1 : eop:1 | ||
300 | * bit 2 : error:1 | ||
301 | * bit 3 : mi:1 | ||
302 | * bit 4 : l3_identified:1 | ||
303 | * bit 5 : l4_identified:1 | ||
304 | * bit 6 : phy_info_included:1 | ||
305 | * bit 7 : reserved:1 | ||
306 | * [word 7] length | ||
307 | * | ||
308 | */ | ||
309 | |||
310 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) | ||
311 | |||
312 | #define RX_DMA_STATUS_DU BIT(0) | ||
313 | #define RX_DMA_STATUS_ERROR BIT(2) | ||
314 | #define RX_DMA_STATUS_PHY_INFO BIT(6) | ||
315 | |||
316 | struct vring_rx_dma { | ||
317 | u32 d0; | ||
318 | u32 addr_low; | ||
319 | u16 addr_high; | ||
320 | u8 ip_length; | ||
321 | u8 b11; | ||
322 | u8 error; | ||
323 | u8 status; | ||
324 | u16 length; | ||
325 | } __packed; | ||
326 | |||
327 | struct vring_tx_desc { | ||
328 | struct vring_tx_mac mac; | ||
329 | struct vring_tx_dma dma; | ||
330 | } __packed; | ||
331 | |||
332 | struct vring_rx_desc { | ||
333 | struct vring_rx_mac mac; | ||
334 | struct vring_rx_dma dma; | ||
335 | } __packed; | ||
336 | |||
337 | union vring_desc { | ||
338 | struct vring_tx_desc tx; | ||
339 | struct vring_rx_desc rx; | ||
340 | } __packed; | ||
341 | |||
342 | static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) | ||
343 | { | ||
344 | return WIL_GET_BITS(d->dma.d0, 16, 29); | ||
345 | } | ||
346 | |||
347 | static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) | ||
348 | { | ||
349 | return WIL_GET_BITS(d->mac.d1, 21, 24); | ||
350 | } | ||
351 | |||
352 | static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) | ||
353 | { | ||
354 | return WIL_GET_BITS(d->mac.d1, 8, 9); | ||
355 | } | ||
356 | |||
357 | static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) | ||
358 | { | ||
359 | return WIL_GET_BITS(d->mac.d0, 10, 11); | ||
360 | } | ||
361 | |||
362 | #endif /* WIL6210_TXRX_H */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h new file mode 100644 index 000000000000..9bcfffa4006c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __WIL6210_H__ | ||
18 | #define __WIL6210_H__ | ||
19 | |||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <net/cfg80211.h> | ||
23 | |||
24 | #include "dbg_hexdump.h" | ||
25 | |||
26 | #define WIL_NAME "wil6210" | ||
27 | |||
28 | /** | ||
29 | * extract bits [@b0:@b1] (inclusive) from the value @x | ||
30 | * it should be @b0 <= @b1, or result is incorrect | ||
31 | */ | ||
32 | static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | ||
33 | { | ||
34 | return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); | ||
35 | } | ||
36 | |||
37 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | ||
38 | |||
39 | #define WIL6210_TX_QUEUES (4) | ||
40 | |||
41 | #define WIL6210_RX_RING_SIZE (128) | ||
42 | #define WIL6210_TX_RING_SIZE (128) | ||
43 | #define WIL6210_MAX_TX_RINGS (24) | ||
44 | |||
45 | /* Hardware definitions begin */ | ||
46 | |||
47 | /* | ||
48 | * Mapping | ||
49 | * RGF File | Host addr | FW addr | ||
50 | * | | | ||
51 | * user_rgf | 0x000000 | 0x880000 | ||
52 | * dma_rgf | 0x001000 | 0x881000 | ||
53 | * pcie_rgf | 0x002000 | 0x882000 | ||
54 | * | | | ||
55 | */ | ||
56 | |||
57 | /* Where various structures placed in host address space */ | ||
58 | #define WIL6210_FW_HOST_OFF (0x880000UL) | ||
59 | |||
60 | #define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) | ||
61 | |||
62 | /* | ||
63 | * Interrupt control registers block | ||
64 | * | ||
65 | * each interrupt controlled by the same bit in all registers | ||
66 | */ | ||
67 | struct RGF_ICR { | ||
68 | u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ | ||
69 | u32 ICR; /* Cause, W1C/COR depending on ICC */ | ||
70 | u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ | ||
71 | u32 ICS; /* Cause Set, WO */ | ||
72 | u32 IMV; /* Mask, RW+S/C */ | ||
73 | u32 IMS; /* Mask Set, write 1 to set */ | ||
74 | u32 IMC; /* Mask Clear, write 1 to clear */ | ||
75 | } __packed; | ||
76 | |||
77 | /* registers - FW addresses */ | ||
78 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | ||
79 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ | ||
80 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | ||
81 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | ||
82 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | ||
83 | #define RGF_USER_USER_CPU_0 (0x8801e0) | ||
84 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) | ||
85 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) | ||
86 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) | ||
87 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) | ||
88 | |||
89 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | ||
90 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | ||
91 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | ||
92 | #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) | ||
93 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | ||
94 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | ||
95 | |||
96 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | ||
97 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | ||
98 | #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ | ||
99 | #define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ | ||
100 | #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) | ||
101 | #define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ | ||
102 | #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) | ||
103 | #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) | ||
104 | #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) | ||
105 | #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) | ||
106 | |||
107 | /* Interrupt moderation control */ | ||
108 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) | ||
109 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) | ||
110 | #define RGF_DMA_ITR_CNT_CRL (0x881C64) | ||
111 | #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) | ||
112 | #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) | ||
113 | #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) | ||
114 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) | ||
115 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) | ||
116 | |||
117 | /* popular locations */ | ||
118 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | ||
119 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ | ||
120 | offsetof(struct RGF_ICR, ICS)) | ||
121 | #define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 | ||
122 | |||
123 | /* ISR register bits */ | ||
124 | #define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 | ||
125 | #define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 | ||
126 | |||
127 | /* Hardware definitions end */ | ||
128 | |||
129 | struct wil6210_mbox_ring { | ||
130 | u32 base; | ||
131 | u16 entry_size; /* max. size of mbox entry, incl. all headers */ | ||
132 | u16 size; | ||
133 | u32 tail; | ||
134 | u32 head; | ||
135 | } __packed; | ||
136 | |||
137 | struct wil6210_mbox_ring_desc { | ||
138 | __le32 sync; | ||
139 | __le32 addr; | ||
140 | } __packed; | ||
141 | |||
142 | /* at HOST_OFF_WIL6210_MBOX_CTL */ | ||
143 | struct wil6210_mbox_ctl { | ||
144 | struct wil6210_mbox_ring tx; | ||
145 | struct wil6210_mbox_ring rx; | ||
146 | } __packed; | ||
147 | |||
148 | struct wil6210_mbox_hdr { | ||
149 | __le16 seq; | ||
150 | __le16 len; /* payload, bytes after this header */ | ||
151 | __le16 type; | ||
152 | u8 flags; | ||
153 | u8 reserved; | ||
154 | } __packed; | ||
155 | |||
156 | #define WIL_MBOX_HDR_TYPE_WMI (0) | ||
157 | |||
158 | /* max. value for wil6210_mbox_hdr.len */ | ||
159 | #define MAX_MBOXITEM_SIZE (240) | ||
160 | |||
161 | struct wil6210_mbox_hdr_wmi { | ||
162 | u8 reserved0[2]; | ||
163 | __le16 id; | ||
164 | __le16 info1; /* bits [0..3] - device_id, rest - unused */ | ||
165 | u8 reserved1[2]; | ||
166 | } __packed; | ||
167 | |||
168 | struct pending_wmi_event { | ||
169 | struct list_head list; | ||
170 | struct { | ||
171 | struct wil6210_mbox_hdr hdr; | ||
172 | struct wil6210_mbox_hdr_wmi wmi; | ||
173 | u8 data[0]; | ||
174 | } __packed event; | ||
175 | }; | ||
176 | |||
177 | union vring_desc; | ||
178 | |||
179 | struct vring { | ||
180 | dma_addr_t pa; | ||
181 | volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ | ||
182 | u16 size; /* number of vring_desc elements */ | ||
183 | u32 swtail; | ||
184 | u32 swhead; | ||
185 | u32 hwtail; /* write here to inform hw */ | ||
186 | void **ctx; /* void *ctx[size] - software context */ | ||
187 | }; | ||
188 | |||
189 | enum { /* for wil6210_priv.status */ | ||
190 | wil_status_fwready = 0, | ||
191 | wil_status_fwconnected, | ||
192 | wil_status_dontscan, | ||
193 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | ||
194 | }; | ||
195 | |||
196 | struct pci_dev; | ||
197 | |||
198 | struct wil6210_stats { | ||
199 | u64 tsf; | ||
200 | u32 snr; | ||
201 | u16 last_mcs_rx; | ||
202 | u16 bf_mcs; /* last BF, used for Tx */ | ||
203 | u16 my_rx_sector; | ||
204 | u16 my_tx_sector; | ||
205 | u16 peer_rx_sector; | ||
206 | u16 peer_tx_sector; | ||
207 | }; | ||
208 | |||
209 | struct wil6210_priv { | ||
210 | struct pci_dev *pdev; | ||
211 | int n_msi; | ||
212 | struct wireless_dev *wdev; | ||
213 | void __iomem *csr; | ||
214 | ulong status; | ||
215 | /* profile */ | ||
216 | u32 monitor_flags; | ||
217 | u32 secure_pcp; /* create secure PCP? */ | ||
218 | int sinfo_gen; | ||
219 | /* cached ISR registers */ | ||
220 | u32 isr_misc; | ||
221 | /* mailbox related */ | ||
222 | struct mutex wmi_mutex; | ||
223 | struct wil6210_mbox_ctl mbox_ctl; | ||
224 | struct completion wmi_ready; | ||
225 | u16 wmi_seq; | ||
226 | u16 reply_id; /**< wait for this WMI event */ | ||
227 | void *reply_buf; | ||
228 | u16 reply_size; | ||
229 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | ||
230 | struct work_struct wmi_event_worker; | ||
231 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | ||
232 | struct work_struct wmi_connect_worker; | ||
233 | struct work_struct disconnect_worker; | ||
234 | struct timer_list connect_timer; | ||
235 | int pending_connect_cid; | ||
236 | struct list_head pending_wmi_ev; | ||
237 | /* | ||
238 | * protect pending_wmi_ev | ||
239 | * - fill in IRQ from wil6210_irq_misc, | ||
240 | * - consumed in thread by wmi_event_worker | ||
241 | */ | ||
242 | spinlock_t wmi_ev_lock; | ||
243 | /* DMA related */ | ||
244 | struct vring vring_rx; | ||
245 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | ||
246 | u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; | ||
247 | /* scan */ | ||
248 | struct cfg80211_scan_request *scan_request; | ||
249 | |||
250 | struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ | ||
251 | /* statistics */ | ||
252 | struct wil6210_stats stats; | ||
253 | /* debugfs */ | ||
254 | struct dentry *debug; | ||
255 | struct debugfs_blob_wrapper fw_code_blob; | ||
256 | struct debugfs_blob_wrapper fw_data_blob; | ||
257 | struct debugfs_blob_wrapper fw_peri_blob; | ||
258 | struct debugfs_blob_wrapper uc_code_blob; | ||
259 | struct debugfs_blob_wrapper uc_data_blob; | ||
260 | struct debugfs_blob_wrapper rgf_blob; | ||
261 | }; | ||
262 | |||
263 | #define wil_to_wiphy(i) (i->wdev->wiphy) | ||
264 | #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) | ||
265 | #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) | ||
266 | #define wil_to_wdev(i) (i->wdev) | ||
267 | #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) | ||
268 | #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) | ||
269 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) | ||
270 | |||
271 | #define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) | ||
272 | #define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) | ||
273 | #define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) | ||
274 | |||
275 | #define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) | ||
276 | #define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) | ||
277 | #define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) | ||
278 | |||
279 | #define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ | ||
280 | groupsize, buf, len, ascii) \ | ||
281 | wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ | ||
282 | prefix_type, rowsize, \ | ||
283 | groupsize, buf, len, ascii) | ||
284 | |||
285 | #define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ | ||
286 | groupsize, buf, len, ascii) \ | ||
287 | wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ | ||
288 | prefix_type, rowsize, \ | ||
289 | groupsize, buf, len, ascii) | ||
290 | |||
291 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
292 | size_t count); | ||
293 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
294 | size_t count); | ||
295 | |||
296 | void *wil_if_alloc(struct device *dev, void __iomem *csr); | ||
297 | void wil_if_free(struct wil6210_priv *wil); | ||
298 | int wil_if_add(struct wil6210_priv *wil); | ||
299 | void wil_if_remove(struct wil6210_priv *wil); | ||
300 | int wil_priv_init(struct wil6210_priv *wil); | ||
301 | void wil_priv_deinit(struct wil6210_priv *wil); | ||
302 | int wil_reset(struct wil6210_priv *wil); | ||
303 | void wil_link_on(struct wil6210_priv *wil); | ||
304 | void wil_link_off(struct wil6210_priv *wil); | ||
305 | int wil_up(struct wil6210_priv *wil); | ||
306 | int wil_down(struct wil6210_priv *wil); | ||
307 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); | ||
308 | |||
309 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); | ||
310 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); | ||
311 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
312 | struct wil6210_mbox_hdr *hdr); | ||
313 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | ||
314 | void wmi_recv_cmd(struct wil6210_priv *wil); | ||
315 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
316 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | ||
317 | void wmi_connect_worker(struct work_struct *work); | ||
318 | void wmi_event_worker(struct work_struct *work); | ||
319 | void wmi_event_flush(struct wil6210_priv *wil); | ||
320 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | ||
321 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); | ||
322 | int wmi_set_channel(struct wil6210_priv *wil, int channel); | ||
323 | int wmi_get_channel(struct wil6210_priv *wil, int *channel); | ||
324 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); | ||
325 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
326 | const void *mac_addr); | ||
327 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
328 | const void *mac_addr, int key_len, const void *key); | ||
329 | int wmi_echo(struct wil6210_priv *wil); | ||
330 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | ||
331 | |||
332 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | ||
333 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | ||
334 | void wil6210_disable_irq(struct wil6210_priv *wil); | ||
335 | void wil6210_enable_irq(struct wil6210_priv *wil); | ||
336 | |||
337 | int wil6210_debugfs_init(struct wil6210_priv *wil); | ||
338 | void wil6210_debugfs_remove(struct wil6210_priv *wil); | ||
339 | |||
340 | struct wireless_dev *wil_cfg80211_init(struct device *dev); | ||
341 | void wil_wdev_free(struct wil6210_priv *wil); | ||
342 | |||
343 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | ||
344 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); | ||
345 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | ||
346 | |||
347 | int wil_rx_init(struct wil6210_priv *wil); | ||
348 | void wil_rx_fini(struct wil6210_priv *wil); | ||
349 | |||
350 | /* TX API */ | ||
351 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
352 | int cid, int tid); | ||
353 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | ||
354 | |||
355 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | ||
356 | void wil_tx_complete(struct wil6210_priv *wil, int ringid); | ||
357 | |||
358 | /* RX API */ | ||
359 | void wil_rx_handle(struct wil6210_priv *wil); | ||
360 | |||
361 | int wil_iftype_nl2wmi(enum nl80211_iftype type); | ||
362 | |||
363 | #endif /* __WIL6210_H__ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c new file mode 100644 index 000000000000..12915f6e7617 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -0,0 +1,975 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/pci.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | |||
22 | #include "wil6210.h" | ||
23 | #include "wmi.h" | ||
24 | |||
25 | /** | ||
26 | * WMI event receiving - theory of operations | ||
27 | * | ||
28 | * When firmware about to report WMI event, it fills memory area | ||
29 | * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for | ||
30 | * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. | ||
31 | * | ||
32 | * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the | ||
33 | * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up | ||
34 | * and handles events within the @wmi_event_worker. Every event get detached | ||
35 | * from list, processed and deleted. | ||
36 | * | ||
37 | * Purpose for this mechanism is to release IRQ thread; otherwise, | ||
38 | * if WMI event handling involves another WMI command flow, this 2-nd flow | ||
39 | * won't be completed because of blocked IRQ thread. | ||
40 | */ | ||
41 | |||
42 | /** | ||
43 | * Addressing - theory of operations | ||
44 | * | ||
45 | * There are several buses present on the WIL6210 card. | ||
46 | * Same memory areas are visible at different address on | ||
47 | * the different busses. There are 3 main bus masters: | ||
48 | * - MAC CPU (ucode) | ||
49 | * - User CPU (firmware) | ||
50 | * - AHB (host) | ||
51 | * | ||
52 | * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing | ||
53 | * AHB addresses starting from 0x880000 | ||
54 | * | ||
55 | * Internally, firmware uses addresses that allows faster access but | ||
56 | * are invisible from the host. To read from these addresses, alternative | ||
57 | * AHB address must be used. | ||
58 | * | ||
59 | * Memory mapping | ||
60 | * Linker address PCI/Host address | ||
61 | * 0x880000 .. 0xa80000 2Mb BAR0 | ||
62 | * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM | ||
63 | * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * @fw_mapping provides memory remapping table | ||
68 | */ | ||
69 | static const struct { | ||
70 | u32 from; /* linker address - from, inclusive */ | ||
71 | u32 to; /* linker address - to, exclusive */ | ||
72 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | ||
73 | } fw_mapping[] = { | ||
74 | {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ | ||
75 | {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ | ||
76 | {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ | ||
77 | {0x880000, 0x88a000, 0x880000}, /* various RGF */ | ||
78 | {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ | ||
79 | /* | ||
80 | * 920000..930000 ucode code RAM | ||
81 | * 930000..932000 ucode data RAM | ||
82 | */ | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * return AHB address for given firmware/ucode internal (linker) address | ||
87 | * @x - internal address | ||
88 | * If address have no valid AHB mapping, return 0 | ||
89 | */ | ||
90 | static u32 wmi_addr_remap(u32 x) | ||
91 | { | ||
92 | uint i; | ||
93 | |||
94 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | ||
95 | if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) | ||
96 | return x + fw_mapping[i].host - fw_mapping[i].from; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Check address validity for WMI buffer; remap if needed | ||
104 | * @ptr - internal (linker) fw/ucode address | ||
105 | * | ||
106 | * Valid buffer should be DWORD aligned | ||
107 | * | ||
108 | * return address for accessing buffer from the host; | ||
109 | * if buffer is not valid, return NULL. | ||
110 | */ | ||
111 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) | ||
112 | { | ||
113 | u32 off; | ||
114 | u32 ptr = le32_to_cpu(ptr_); | ||
115 | |||
116 | if (ptr % 4) | ||
117 | return NULL; | ||
118 | |||
119 | ptr = wmi_addr_remap(ptr); | ||
120 | if (ptr < WIL6210_FW_HOST_OFF) | ||
121 | return NULL; | ||
122 | |||
123 | off = HOSTADDR(ptr); | ||
124 | if (off > WIL6210_MEM_SIZE - 4) | ||
125 | return NULL; | ||
126 | |||
127 | return wil->csr + off; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Check address validity | ||
132 | */ | ||
133 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) | ||
134 | { | ||
135 | u32 off; | ||
136 | |||
137 | if (ptr % 4) | ||
138 | return NULL; | ||
139 | |||
140 | if (ptr < WIL6210_FW_HOST_OFF) | ||
141 | return NULL; | ||
142 | |||
143 | off = HOSTADDR(ptr); | ||
144 | if (off > WIL6210_MEM_SIZE - 4) | ||
145 | return NULL; | ||
146 | |||
147 | return wil->csr + off; | ||
148 | } | ||
149 | |||
150 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
151 | struct wil6210_mbox_hdr *hdr) | ||
152 | { | ||
153 | void __iomem *src = wmi_buffer(wil, ptr); | ||
154 | if (!src) | ||
155 | return -EINVAL; | ||
156 | |||
157 | wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
163 | { | ||
164 | struct { | ||
165 | struct wil6210_mbox_hdr hdr; | ||
166 | struct wil6210_mbox_hdr_wmi wmi; | ||
167 | } __packed cmd = { | ||
168 | .hdr = { | ||
169 | .type = WIL_MBOX_HDR_TYPE_WMI, | ||
170 | .flags = 0, | ||
171 | .len = cpu_to_le16(sizeof(cmd.wmi) + len), | ||
172 | }, | ||
173 | .wmi = { | ||
174 | .id = cpu_to_le16(cmdid), | ||
175 | .info1 = 0, | ||
176 | }, | ||
177 | }; | ||
178 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; | ||
179 | struct wil6210_mbox_ring_desc d_head; | ||
180 | u32 next_head; | ||
181 | void __iomem *dst; | ||
182 | void __iomem *head = wmi_addr(wil, r->head); | ||
183 | uint retry; | ||
184 | |||
185 | if (sizeof(cmd) + len > r->entry_size) { | ||
186 | wil_err(wil, "WMI size too large: %d bytes, max is %d\n", | ||
187 | (int)(sizeof(cmd) + len), r->entry_size); | ||
188 | return -ERANGE; | ||
189 | |||
190 | } | ||
191 | |||
192 | might_sleep(); | ||
193 | |||
194 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
195 | wil_err(wil, "FW not ready\n"); | ||
196 | return -EAGAIN; | ||
197 | } | ||
198 | |||
199 | if (!head) { | ||
200 | wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | /* read Tx head till it is not busy */ | ||
204 | for (retry = 5; retry > 0; retry--) { | ||
205 | wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); | ||
206 | if (d_head.sync == 0) | ||
207 | break; | ||
208 | msleep(20); | ||
209 | } | ||
210 | if (d_head.sync != 0) { | ||
211 | wil_err(wil, "WMI head busy\n"); | ||
212 | return -EBUSY; | ||
213 | } | ||
214 | /* next head */ | ||
215 | next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); | ||
216 | wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); | ||
217 | /* wait till FW finish with previous command */ | ||
218 | for (retry = 5; retry > 0; retry--) { | ||
219 | r->tail = ioread32(wil->csr + HOST_MBOX + | ||
220 | offsetof(struct wil6210_mbox_ctl, tx.tail)); | ||
221 | if (next_head != r->tail) | ||
222 | break; | ||
223 | msleep(20); | ||
224 | } | ||
225 | if (next_head == r->tail) { | ||
226 | wil_err(wil, "WMI ring full\n"); | ||
227 | return -EBUSY; | ||
228 | } | ||
229 | dst = wmi_buffer(wil, d_head.addr); | ||
230 | if (!dst) { | ||
231 | wil_err(wil, "invalid WMI buffer: 0x%08x\n", | ||
232 | le32_to_cpu(d_head.addr)); | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); | ||
236 | /* set command */ | ||
237 | wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); | ||
238 | wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, | ||
239 | sizeof(cmd), true); | ||
240 | wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, | ||
241 | len, true); | ||
242 | wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); | ||
243 | wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); | ||
244 | /* mark entry as full */ | ||
245 | iowrite32(1, wil->csr + HOSTADDR(r->head) + | ||
246 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
247 | /* advance next ptr */ | ||
248 | iowrite32(r->head = next_head, wil->csr + HOST_MBOX + | ||
249 | offsetof(struct wil6210_mbox_ctl, tx.head)); | ||
250 | |||
251 | /* interrupt to FW */ | ||
252 | iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
258 | { | ||
259 | int rc; | ||
260 | |||
261 | mutex_lock(&wil->wmi_mutex); | ||
262 | rc = __wmi_send(wil, cmdid, buf, len); | ||
263 | mutex_unlock(&wil->wmi_mutex); | ||
264 | |||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | /*=== Event handlers ===*/ | ||
269 | static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | ||
270 | { | ||
271 | struct net_device *ndev = wil_to_ndev(wil); | ||
272 | struct wireless_dev *wdev = wil->wdev; | ||
273 | struct wmi_ready_event *evt = d; | ||
274 | u32 ver = le32_to_cpu(evt->sw_version); | ||
275 | |||
276 | wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); | ||
277 | |||
278 | if (!is_valid_ether_addr(ndev->dev_addr)) { | ||
279 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); | ||
280 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); | ||
281 | } | ||
282 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | ||
283 | "%d", ver); | ||
284 | } | ||
285 | |||
286 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | ||
287 | int len) | ||
288 | { | ||
289 | wil_dbg_WMI(wil, "WMI: FW ready\n"); | ||
290 | |||
291 | set_bit(wil_status_fwready, &wil->status); | ||
292 | /* reuse wmi_ready for the firmware ready indication */ | ||
293 | complete(&wil->wmi_ready); | ||
294 | } | ||
295 | |||
296 | static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | ||
297 | { | ||
298 | struct wmi_rx_mgmt_packet_event *data = d; | ||
299 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
300 | struct ieee80211_mgmt *rx_mgmt_frame = | ||
301 | (struct ieee80211_mgmt *)data->payload; | ||
302 | int ch_no = data->info.channel+1; | ||
303 | u32 freq = ieee80211_channel_to_frequency(ch_no, | ||
304 | IEEE80211_BAND_60GHZ); | ||
305 | struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); | ||
306 | /* TODO convert LE to CPU */ | ||
307 | s32 signal = 0; /* TODO */ | ||
308 | __le16 fc = rx_mgmt_frame->frame_control; | ||
309 | u32 d_len = le32_to_cpu(data->info.len); | ||
310 | u16 d_status = le16_to_cpu(data->info.status); | ||
311 | |||
312 | wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", | ||
313 | data->info.channel, data->info.mcs, data->info.snr); | ||
314 | wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, | ||
315 | le16_to_cpu(data->info.stype)); | ||
316 | wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", | ||
317 | data->info.qid, data->info.mid, data->info.cid); | ||
318 | |||
319 | if (!channel) { | ||
320 | wil_err(wil, "Frame on unsupported channel\n"); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { | ||
325 | struct cfg80211_bss *bss; | ||
326 | u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); | ||
327 | u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); | ||
328 | u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); | ||
329 | const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; | ||
330 | size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, | ||
331 | u.beacon.variable); | ||
332 | wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); | ||
333 | |||
334 | bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, | ||
335 | tsf, cap, bi, ie_buf, ie_len, | ||
336 | signal, GFP_KERNEL); | ||
337 | if (bss) { | ||
338 | wil_dbg_WMI(wil, "Added BSS %pM\n", | ||
339 | rx_mgmt_frame->bssid); | ||
340 | cfg80211_put_bss(bss); | ||
341 | } else { | ||
342 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | ||
348 | void *d, int len) | ||
349 | { | ||
350 | if (wil->scan_request) { | ||
351 | struct wmi_scan_complete_event *data = d; | ||
352 | bool aborted = (data->status != 0); | ||
353 | |||
354 | wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); | ||
355 | cfg80211_scan_done(wil->scan_request, aborted); | ||
356 | wil->scan_request = NULL; | ||
357 | } else { | ||
358 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | ||
363 | { | ||
364 | struct net_device *ndev = wil_to_ndev(wil); | ||
365 | struct wireless_dev *wdev = wil->wdev; | ||
366 | struct wmi_connect_event *evt = d; | ||
367 | int ch; /* channel number */ | ||
368 | struct station_info sinfo; | ||
369 | u8 *assoc_req_ie, *assoc_resp_ie; | ||
370 | size_t assoc_req_ielen, assoc_resp_ielen; | ||
371 | /* capinfo(u16) + listen_interval(u16) + IEs */ | ||
372 | const size_t assoc_req_ie_offset = sizeof(u16) * 2; | ||
373 | /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ | ||
374 | const size_t assoc_resp_ie_offset = sizeof(u16) * 3; | ||
375 | |||
376 | if (len < sizeof(*evt)) { | ||
377 | wil_err(wil, "Connect event too short : %d bytes\n", len); | ||
378 | return; | ||
379 | } | ||
380 | if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + | ||
381 | evt->assoc_resp_len) { | ||
382 | wil_err(wil, | ||
383 | "Connect event corrupted : %d != %d + %d + %d + %d\n", | ||
384 | len, (int)sizeof(*evt), evt->beacon_ie_len, | ||
385 | evt->assoc_req_len, evt->assoc_resp_len); | ||
386 | return; | ||
387 | } | ||
388 | ch = evt->channel + 1; | ||
389 | wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", | ||
390 | evt->bssid, ch, evt->cid); | ||
391 | wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, | ||
392 | evt->assoc_info, len - sizeof(*evt), true); | ||
393 | |||
394 | /* figure out IE's */ | ||
395 | assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
396 | assoc_req_ie_offset]; | ||
397 | assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; | ||
398 | if (evt->assoc_req_len <= assoc_req_ie_offset) { | ||
399 | assoc_req_ie = NULL; | ||
400 | assoc_req_ielen = 0; | ||
401 | } | ||
402 | |||
403 | assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
404 | evt->assoc_req_len + | ||
405 | assoc_resp_ie_offset]; | ||
406 | assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; | ||
407 | if (evt->assoc_resp_len <= assoc_resp_ie_offset) { | ||
408 | assoc_resp_ie = NULL; | ||
409 | assoc_resp_ielen = 0; | ||
410 | } | ||
411 | |||
412 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | ||
413 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | ||
414 | if (wdev->sme_state != CFG80211_SME_CONNECTING) { | ||
415 | wil_err(wil, "Not in connecting state\n"); | ||
416 | return; | ||
417 | } | ||
418 | del_timer_sync(&wil->connect_timer); | ||
419 | cfg80211_connect_result(ndev, evt->bssid, | ||
420 | assoc_req_ie, assoc_req_ielen, | ||
421 | assoc_resp_ie, assoc_resp_ielen, | ||
422 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
423 | |||
424 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | ||
425 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
426 | memset(&sinfo, 0, sizeof(sinfo)); | ||
427 | |||
428 | sinfo.generation = wil->sinfo_gen++; | ||
429 | |||
430 | if (assoc_req_ie) { | ||
431 | sinfo.assoc_req_ies = assoc_req_ie; | ||
432 | sinfo.assoc_req_ies_len = assoc_req_ielen; | ||
433 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
434 | } | ||
435 | |||
436 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); | ||
437 | } | ||
438 | set_bit(wil_status_fwconnected, &wil->status); | ||
439 | |||
440 | /* FIXME FW can transmit only ucast frames to peer */ | ||
441 | /* FIXME real ring_id instead of hard coded 0 */ | ||
442 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); | ||
443 | |||
444 | wil->pending_connect_cid = evt->cid; | ||
445 | queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); | ||
446 | } | ||
447 | |||
448 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | ||
449 | void *d, int len) | ||
450 | { | ||
451 | struct wmi_disconnect_event *evt = d; | ||
452 | |||
453 | wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", | ||
454 | evt->bssid, | ||
455 | evt->protocol_reason_status, evt->disconnect_reason); | ||
456 | |||
457 | wil->sinfo_gen++; | ||
458 | |||
459 | wil6210_disconnect(wil, evt->bssid); | ||
460 | clear_bit(wil_status_dontscan, &wil->status); | ||
461 | } | ||
462 | |||
463 | static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) | ||
464 | { | ||
465 | struct wmi_notify_req_done_event *evt = d; | ||
466 | |||
467 | if (len < sizeof(*evt)) { | ||
468 | wil_err(wil, "Short NOTIFY event\n"); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | wil->stats.tsf = le64_to_cpu(evt->tsf); | ||
473 | wil->stats.snr = le32_to_cpu(evt->snr_val); | ||
474 | wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); | ||
475 | wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); | ||
476 | wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); | ||
477 | wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); | ||
478 | wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); | ||
479 | wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" | ||
480 | "BF status 0x%08x SNR 0x%08x\n" | ||
481 | "Tx Tpt %d goodput %d Rx goodput %d\n" | ||
482 | "Sectors(rx:tx) my %d:%d peer %d:%d\n", | ||
483 | wil->stats.bf_mcs, wil->stats.tsf, evt->status, | ||
484 | wil->stats.snr, le32_to_cpu(evt->tx_tpt), | ||
485 | le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), | ||
486 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
487 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Firmware reports EAPOL frame using WME event. | ||
492 | * Reconstruct Ethernet frame and deliver it via normal Rx | ||
493 | */ | ||
494 | static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | ||
495 | void *d, int len) | ||
496 | { | ||
497 | struct net_device *ndev = wil_to_ndev(wil); | ||
498 | struct wmi_eapol_rx_event *evt = d; | ||
499 | u16 eapol_len = le16_to_cpu(evt->eapol_len); | ||
500 | int sz = eapol_len + ETH_HLEN; | ||
501 | struct sk_buff *skb; | ||
502 | struct ethhdr *eth; | ||
503 | |||
504 | wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, | ||
505 | evt->src_mac); | ||
506 | |||
507 | if (eapol_len > 196) { /* TODO: revisit size limit */ | ||
508 | wil_err(wil, "EAPOL too large\n"); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | skb = alloc_skb(sz, GFP_KERNEL); | ||
513 | if (!skb) { | ||
514 | wil_err(wil, "Failed to allocate skb\n"); | ||
515 | return; | ||
516 | } | ||
517 | eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); | ||
518 | memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); | ||
519 | memcpy(eth->h_source, evt->src_mac, ETH_ALEN); | ||
520 | eth->h_proto = cpu_to_be16(ETH_P_PAE); | ||
521 | memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); | ||
522 | skb->protocol = eth_type_trans(skb, ndev); | ||
523 | if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { | ||
524 | ndev->stats.rx_packets++; | ||
525 | ndev->stats.rx_bytes += skb->len; | ||
526 | } else { | ||
527 | ndev->stats.rx_dropped++; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | static const struct { | ||
532 | int eventid; | ||
533 | void (*handler)(struct wil6210_priv *wil, int eventid, | ||
534 | void *data, int data_len); | ||
535 | } wmi_evt_handlers[] = { | ||
536 | {WMI_READY_EVENTID, wmi_evt_ready}, | ||
537 | {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, | ||
538 | {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, | ||
539 | {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, | ||
540 | {WMI_CONNECT_EVENTID, wmi_evt_connect}, | ||
541 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, | ||
542 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, | ||
543 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, | ||
544 | }; | ||
545 | |||
546 | /* | ||
547 | * Run in IRQ context | ||
548 | * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev | ||
549 | * that will be eventually handled by the @wmi_event_worker in the thread | ||
550 | * context of thread "wil6210_wmi" | ||
551 | */ | ||
552 | void wmi_recv_cmd(struct wil6210_priv *wil) | ||
553 | { | ||
554 | struct wil6210_mbox_ring_desc d_tail; | ||
555 | struct wil6210_mbox_hdr hdr; | ||
556 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; | ||
557 | struct pending_wmi_event *evt; | ||
558 | u8 *cmd; | ||
559 | void __iomem *src; | ||
560 | ulong flags; | ||
561 | |||
562 | for (;;) { | ||
563 | u16 len; | ||
564 | |||
565 | r->head = ioread32(wil->csr + HOST_MBOX + | ||
566 | offsetof(struct wil6210_mbox_ctl, rx.head)); | ||
567 | if (r->tail == r->head) | ||
568 | return; | ||
569 | |||
570 | /* read cmd from tail */ | ||
571 | wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), | ||
572 | sizeof(struct wil6210_mbox_ring_desc)); | ||
573 | if (d_tail.sync == 0) { | ||
574 | wil_err(wil, "Mbox evt not owned by FW?\n"); | ||
575 | return; | ||
576 | } | ||
577 | |||
578 | if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { | ||
579 | wil_err(wil, "Mbox evt at 0x%08x?\n", | ||
580 | le32_to_cpu(d_tail.addr)); | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | len = le16_to_cpu(hdr.len); | ||
585 | src = wmi_buffer(wil, d_tail.addr) + | ||
586 | sizeof(struct wil6210_mbox_hdr); | ||
587 | evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, | ||
588 | event.wmi) + len, 4), | ||
589 | GFP_KERNEL); | ||
590 | if (!evt) { | ||
591 | wil_err(wil, "kmalloc for WMI event (%d) failed\n", | ||
592 | len); | ||
593 | return; | ||
594 | } | ||
595 | evt->event.hdr = hdr; | ||
596 | cmd = (void *)&evt->event.wmi; | ||
597 | wil_memcpy_fromio_32(cmd, src, len); | ||
598 | /* mark entry as empty */ | ||
599 | iowrite32(0, wil->csr + HOSTADDR(r->tail) + | ||
600 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
601 | /* indicate */ | ||
602 | wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", | ||
603 | le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), | ||
604 | hdr.flags); | ||
605 | if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && | ||
606 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
607 | wil_dbg_WMI(wil, "WMI event 0x%04x\n", | ||
608 | evt->event.wmi.id); | ||
609 | } | ||
610 | wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, | ||
611 | &evt->event.hdr, sizeof(hdr) + len, true); | ||
612 | |||
613 | /* advance tail */ | ||
614 | r->tail = r->base + ((r->tail - r->base + | ||
615 | sizeof(struct wil6210_mbox_ring_desc)) % r->size); | ||
616 | iowrite32(r->tail, wil->csr + HOST_MBOX + | ||
617 | offsetof(struct wil6210_mbox_ctl, rx.tail)); | ||
618 | |||
619 | /* add to the pending list */ | ||
620 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
621 | list_add_tail(&evt->list, &wil->pending_wmi_ev); | ||
622 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
623 | { | ||
624 | int q = queue_work(wil->wmi_wq, | ||
625 | &wil->wmi_event_worker); | ||
626 | wil_dbg_WMI(wil, "queue_work -> %d\n", q); | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | |||
631 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
632 | u16 reply_id, void *reply, u8 reply_size, int to_msec) | ||
633 | { | ||
634 | int rc; | ||
635 | int remain; | ||
636 | |||
637 | mutex_lock(&wil->wmi_mutex); | ||
638 | |||
639 | rc = __wmi_send(wil, cmdid, buf, len); | ||
640 | if (rc) | ||
641 | goto out; | ||
642 | |||
643 | wil->reply_id = reply_id; | ||
644 | wil->reply_buf = reply; | ||
645 | wil->reply_size = reply_size; | ||
646 | remain = wait_for_completion_timeout(&wil->wmi_ready, | ||
647 | msecs_to_jiffies(to_msec)); | ||
648 | if (0 == remain) { | ||
649 | wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", | ||
650 | cmdid, reply_id, to_msec); | ||
651 | rc = -ETIME; | ||
652 | } else { | ||
653 | wil_dbg_WMI(wil, | ||
654 | "wmi_call(0x%04x->0x%04x) completed in %d msec\n", | ||
655 | cmdid, reply_id, | ||
656 | to_msec - jiffies_to_msecs(remain)); | ||
657 | } | ||
658 | wil->reply_id = 0; | ||
659 | wil->reply_buf = NULL; | ||
660 | wil->reply_size = 0; | ||
661 | out: | ||
662 | mutex_unlock(&wil->wmi_mutex); | ||
663 | |||
664 | return rc; | ||
665 | } | ||
666 | |||
667 | int wmi_echo(struct wil6210_priv *wil) | ||
668 | { | ||
669 | struct wmi_echo_cmd cmd = { | ||
670 | .value = cpu_to_le32(0x12345678), | ||
671 | }; | ||
672 | |||
673 | return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), | ||
674 | WMI_ECHO_RSP_EVENTID, NULL, 0, 20); | ||
675 | } | ||
676 | |||
677 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | ||
678 | { | ||
679 | struct wmi_set_mac_address_cmd cmd; | ||
680 | |||
681 | memcpy(cmd.mac, addr, ETH_ALEN); | ||
682 | |||
683 | wil_dbg_WMI(wil, "Set MAC %pM\n", addr); | ||
684 | |||
685 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | ||
686 | } | ||
687 | |||
688 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) | ||
689 | { | ||
690 | struct wmi_bcon_ctrl_cmd cmd = { | ||
691 | .bcon_interval = cpu_to_le16(bi), | ||
692 | .network_type = wmi_nettype, | ||
693 | .disable_sec_offload = 1, | ||
694 | }; | ||
695 | |||
696 | if (!wil->secure_pcp) | ||
697 | cmd.disable_sec = 1; | ||
698 | |||
699 | return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); | ||
700 | } | ||
701 | |||
702 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | ||
703 | { | ||
704 | struct wmi_set_ssid_cmd cmd = { | ||
705 | .ssid_len = cpu_to_le32(ssid_len), | ||
706 | }; | ||
707 | |||
708 | if (ssid_len > sizeof(cmd.ssid)) | ||
709 | return -EINVAL; | ||
710 | |||
711 | memcpy(cmd.ssid, ssid, ssid_len); | ||
712 | |||
713 | return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); | ||
714 | } | ||
715 | |||
716 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | ||
717 | { | ||
718 | int rc; | ||
719 | struct { | ||
720 | struct wil6210_mbox_hdr_wmi wmi; | ||
721 | struct wmi_set_ssid_cmd cmd; | ||
722 | } __packed reply; | ||
723 | int len; /* reply.cmd.ssid_len in CPU order */ | ||
724 | |||
725 | rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, | ||
726 | &reply, sizeof(reply), 20); | ||
727 | if (rc) | ||
728 | return rc; | ||
729 | |||
730 | len = le32_to_cpu(reply.cmd.ssid_len); | ||
731 | if (len > sizeof(reply.cmd.ssid)) | ||
732 | return -EINVAL; | ||
733 | |||
734 | *ssid_len = len; | ||
735 | memcpy(ssid, reply.cmd.ssid, len); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | int wmi_set_channel(struct wil6210_priv *wil, int channel) | ||
741 | { | ||
742 | struct wmi_set_pcp_channel_cmd cmd = { | ||
743 | .channel = channel - 1, | ||
744 | }; | ||
745 | |||
746 | return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); | ||
747 | } | ||
748 | |||
749 | int wmi_get_channel(struct wil6210_priv *wil, int *channel) | ||
750 | { | ||
751 | int rc; | ||
752 | struct { | ||
753 | struct wil6210_mbox_hdr_wmi wmi; | ||
754 | struct wmi_set_pcp_channel_cmd cmd; | ||
755 | } __packed reply; | ||
756 | |||
757 | rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, | ||
758 | WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); | ||
759 | if (rc) | ||
760 | return rc; | ||
761 | |||
762 | if (reply.cmd.channel > 3) | ||
763 | return -EINVAL; | ||
764 | |||
765 | *channel = reply.cmd.channel + 1; | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) | ||
771 | { | ||
772 | struct wmi_eapol_tx_cmd *cmd; | ||
773 | struct ethhdr *eth; | ||
774 | u16 eapol_len = skb->len - ETH_HLEN; | ||
775 | void *eapol = skb->data + ETH_HLEN; | ||
776 | uint i; | ||
777 | int rc; | ||
778 | |||
779 | skb_set_mac_header(skb, 0); | ||
780 | eth = eth_hdr(skb); | ||
781 | wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); | ||
782 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
783 | if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) | ||
784 | goto found_dest; | ||
785 | } | ||
786 | |||
787 | return -EINVAL; | ||
788 | |||
789 | found_dest: | ||
790 | /* find out eapol data & len */ | ||
791 | cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); | ||
792 | if (!cmd) | ||
793 | return -EINVAL; | ||
794 | |||
795 | memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); | ||
796 | cmd->eapol_len = cpu_to_le16(eapol_len); | ||
797 | memcpy(cmd->eapol, eapol, eapol_len); | ||
798 | rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); | ||
799 | kfree(cmd); | ||
800 | |||
801 | return rc; | ||
802 | } | ||
803 | |||
804 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
805 | const void *mac_addr) | ||
806 | { | ||
807 | struct wmi_delete_cipher_key_cmd cmd = { | ||
808 | .key_index = key_index, | ||
809 | }; | ||
810 | |||
811 | if (mac_addr) | ||
812 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
813 | |||
814 | return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
815 | } | ||
816 | |||
817 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
818 | const void *mac_addr, int key_len, const void *key) | ||
819 | { | ||
820 | struct wmi_add_cipher_key_cmd cmd = { | ||
821 | .key_index = key_index, | ||
822 | .key_usage = WMI_KEY_USE_PAIRWISE, | ||
823 | .key_len = key_len, | ||
824 | }; | ||
825 | |||
826 | if (!key || (key_len > sizeof(cmd.key))) | ||
827 | return -EINVAL; | ||
828 | |||
829 | memcpy(cmd.key, key, key_len); | ||
830 | if (mac_addr) | ||
831 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
832 | |||
833 | return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
834 | } | ||
835 | |||
836 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | ||
837 | { | ||
838 | int rc; | ||
839 | u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; | ||
840 | struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); | ||
841 | if (!cmd) { | ||
842 | wil_err(wil, "kmalloc(%d) failed\n", len); | ||
843 | return -ENOMEM; | ||
844 | } | ||
845 | |||
846 | cmd->mgmt_frm_type = type; | ||
847 | /* BUG: FW API define ieLen as u8. Will fix FW */ | ||
848 | cmd->ie_len = cpu_to_le16(ie_len); | ||
849 | memcpy(cmd->ie_info, ie, ie_len); | ||
850 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); | ||
851 | kfree(cmd); | ||
852 | |||
853 | return rc; | ||
854 | } | ||
855 | |||
856 | void wmi_event_flush(struct wil6210_priv *wil) | ||
857 | { | ||
858 | struct pending_wmi_event *evt, *t; | ||
859 | |||
860 | wil_dbg_WMI(wil, "%s()\n", __func__); | ||
861 | |||
862 | list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { | ||
863 | list_del(&evt->list); | ||
864 | kfree(evt); | ||
865 | } | ||
866 | } | ||
867 | |||
868 | static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, | ||
869 | void *d, int len) | ||
870 | { | ||
871 | uint i; | ||
872 | |||
873 | for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { | ||
874 | if (wmi_evt_handlers[i].eventid == id) { | ||
875 | wmi_evt_handlers[i].handler(wil, id, d, len); | ||
876 | return true; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | return false; | ||
881 | } | ||
882 | |||
883 | static void wmi_event_handle(struct wil6210_priv *wil, | ||
884 | struct wil6210_mbox_hdr *hdr) | ||
885 | { | ||
886 | u16 len = le16_to_cpu(hdr->len); | ||
887 | |||
888 | if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && | ||
889 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
890 | struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); | ||
891 | void *evt_data = (void *)(&wmi[1]); | ||
892 | u16 id = le16_to_cpu(wmi->id); | ||
893 | /* check if someone waits for this event */ | ||
894 | if (wil->reply_id && wil->reply_id == id) { | ||
895 | if (wil->reply_buf) { | ||
896 | memcpy(wil->reply_buf, wmi, | ||
897 | min(len, wil->reply_size)); | ||
898 | } else { | ||
899 | wmi_evt_call_handler(wil, id, evt_data, | ||
900 | len - sizeof(*wmi)); | ||
901 | } | ||
902 | wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); | ||
903 | complete(&wil->wmi_ready); | ||
904 | return; | ||
905 | } | ||
906 | /* unsolicited event */ | ||
907 | /* search for handler */ | ||
908 | if (!wmi_evt_call_handler(wil, id, evt_data, | ||
909 | len - sizeof(*wmi))) { | ||
910 | wil_err(wil, "Unhandled event 0x%04x\n", id); | ||
911 | } | ||
912 | } else { | ||
913 | wil_err(wil, "Unknown event type\n"); | ||
914 | print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, | ||
915 | hdr, sizeof(*hdr) + len, true); | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * Retrieve next WMI event from the pending list | ||
921 | */ | ||
922 | static struct list_head *next_wmi_ev(struct wil6210_priv *wil) | ||
923 | { | ||
924 | ulong flags; | ||
925 | struct list_head *ret = NULL; | ||
926 | |||
927 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
928 | |||
929 | if (!list_empty(&wil->pending_wmi_ev)) { | ||
930 | ret = wil->pending_wmi_ev.next; | ||
931 | list_del(ret); | ||
932 | } | ||
933 | |||
934 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
935 | |||
936 | return ret; | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Handler for the WMI events | ||
941 | */ | ||
942 | void wmi_event_worker(struct work_struct *work) | ||
943 | { | ||
944 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
945 | wmi_event_worker); | ||
946 | struct pending_wmi_event *evt; | ||
947 | struct list_head *lh; | ||
948 | |||
949 | while ((lh = next_wmi_ev(wil)) != NULL) { | ||
950 | evt = list_entry(lh, struct pending_wmi_event, list); | ||
951 | wmi_event_handle(wil, &evt->event.hdr); | ||
952 | kfree(evt); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | void wmi_connect_worker(struct work_struct *work) | ||
957 | { | ||
958 | int rc; | ||
959 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
960 | wmi_connect_worker); | ||
961 | |||
962 | if (wil->pending_connect_cid < 0) { | ||
963 | wil_err(wil, "No connection pending\n"); | ||
964 | return; | ||
965 | } | ||
966 | |||
967 | wil_dbg_WMI(wil, "Configure for connection CID %d\n", | ||
968 | wil->pending_connect_cid); | ||
969 | |||
970 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, | ||
971 | wil->pending_connect_cid, 0); | ||
972 | wil->pending_connect_cid = -1; | ||
973 | if (rc == 0) | ||
974 | wil_link_on(wil); | ||
975 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h new file mode 100644 index 000000000000..3bbf87572b07 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -0,0 +1,1116 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * Copyright (c) 2006-2012 Wilocity . | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * This file contains the definitions of the WMI protocol specified in the | ||
20 | * Wireless Module Interface (WMI) for the Wilocity | ||
21 | * MARLON 60 Gigabit wireless solution. | ||
22 | * It includes definitions of all the commands and events. | ||
23 | * Commands are messages from the host to the WM. | ||
24 | * Events are messages from the WM to the host. | ||
25 | */ | ||
26 | |||
27 | #ifndef __WILOCITY_WMI_H__ | ||
28 | #define __WILOCITY_WMI_H__ | ||
29 | |||
30 | /* General */ | ||
31 | |||
32 | #define WMI_MAC_LEN (6) | ||
33 | #define WMI_PROX_RANGE_NUM (3) | ||
34 | |||
35 | /* List of Commands */ | ||
36 | enum wmi_command_id { | ||
37 | WMI_CONNECT_CMDID = 0x0001, | ||
38 | WMI_DISCONNECT_CMDID = 0x0003, | ||
39 | WMI_START_SCAN_CMDID = 0x0007, | ||
40 | WMI_SET_BSS_FILTER_CMDID = 0x0009, | ||
41 | WMI_SET_PROBED_SSID_CMDID = 0x000a, | ||
42 | WMI_SET_LISTEN_INT_CMDID = 0x000b, | ||
43 | WMI_BCON_CTRL_CMDID = 0x000f, | ||
44 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, | ||
45 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, | ||
46 | WMI_SET_APPIE_CMDID = 0x003f, | ||
47 | WMI_GET_APPIE_CMDID = 0x0040, | ||
48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | ||
49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | ||
50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | ||
51 | WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, | ||
52 | WMI_MEM_READ_CMDID = 0x0800, | ||
53 | WMI_MEM_WR_CMDID = 0x0801, | ||
54 | WMI_ECHO_CMDID = 0x0803, | ||
55 | WMI_DEEP_ECHO_CMDID = 0x0804, | ||
56 | WMI_CONFIG_MAC_CMDID = 0x0805, | ||
57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, | ||
58 | WMI_ADD_STATION_CMDID = 0x0807, | ||
59 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, | ||
60 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, | ||
61 | WMI_FS_TUNE_CMDID = 0x080a, | ||
62 | WMI_CORR_MEASURE_CMDID = 0x080b, | ||
63 | WMI_TEMP_SENSE_CMDID = 0x080e, | ||
64 | WMI_DC_CALIB_CMDID = 0x080f, | ||
65 | WMI_SEND_TONE_CMDID = 0x0810, | ||
66 | WMI_IQ_TX_CALIB_CMDID = 0x0811, | ||
67 | WMI_IQ_RX_CALIB_CMDID = 0x0812, | ||
68 | WMI_SET_UCODE_IDLE_CMDID = 0x0813, | ||
69 | WMI_SET_WORK_MODE_CMDID = 0x0815, | ||
70 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, | ||
71 | WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, | ||
72 | WMI_MARLON_R_READ_CMDID = 0x0818, | ||
73 | WMI_MARLON_R_WRITE_CMDID = 0x0819, | ||
74 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, | ||
75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, | ||
76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, | ||
77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, | ||
78 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | ||
79 | WMI_VRING_CFG_CMDID = 0x0821, | ||
80 | WMI_RX_ON_CMDID = 0x0822, | ||
81 | WMI_VRING_BA_EN_CMDID = 0x0823, | ||
82 | WMI_VRING_BA_DIS_CMDID = 0x0824, | ||
83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | ||
84 | WMI_RCP_DELBA_CMDID = 0x0826, | ||
85 | WMI_SET_SSID_CMDID = 0x0827, | ||
86 | WMI_GET_SSID_CMDID = 0x0828, | ||
87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, | ||
88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, | ||
89 | WMI_SW_TX_REQ_CMDID = 0x082b, | ||
90 | WMI_RX_OFF_CMDID = 0x082c, | ||
91 | WMI_READ_MAC_RXQ_CMDID = 0x0830, | ||
92 | WMI_READ_MAC_TXQ_CMDID = 0x0831, | ||
93 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, | ||
94 | WMI_WRITE_MAC_TXQ_CMDID = 0x0833, | ||
95 | WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, | ||
96 | WMI_MLME_PUSH_CMDID = 0x0835, | ||
97 | WMI_BEAMFORMING_MGMT_CMDID = 0x0836, | ||
98 | WMI_BF_TXSS_MGMT_CMDID = 0x0837, | ||
99 | WMI_BF_SM_MGMT_CMDID = 0x0838, | ||
100 | WMI_BF_RXSS_MGMT_CMDID = 0x0839, | ||
101 | WMI_SET_SECTORS_CMDID = 0x0849, | ||
102 | WMI_MAINTAIN_PAUSE_CMDID = 0x0850, | ||
103 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | ||
104 | WMI_RS_MGMT_CMDID = 0x0852, | ||
105 | WMI_RF_MGMT_CMDID = 0x0853, | ||
106 | /* Performance monitoring commands */ | ||
107 | WMI_BF_CTRL_CMDID = 0x0862, | ||
108 | WMI_NOTIFY_REQ_CMDID = 0x0863, | ||
109 | WMI_GET_STATUS_CMDID = 0x0864, | ||
110 | WMI_UNIT_TEST_CMDID = 0x0900, | ||
111 | WMI_HICCUP_CMDID = 0x0901, | ||
112 | WMI_FLASH_READ_CMDID = 0x0902, | ||
113 | WMI_FLASH_WRITE_CMDID = 0x0903, | ||
114 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, | ||
115 | |||
116 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, | ||
117 | WMI_ABORT_SCAN_CMDID = 0xf007, | ||
118 | WMI_SET_PMK_CMDID = 0xf028, | ||
119 | |||
120 | WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, | ||
121 | WMI_GET_PMK_CMDID = 0xf048, | ||
122 | WMI_SET_PASSPHRASE_CMDID = 0xf049, | ||
123 | WMI_SEND_ASSOC_RES_CMDID = 0xf04a, | ||
124 | WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, | ||
125 | WMI_EAPOL_TX_CMDID = 0xf04c, | ||
126 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, | ||
127 | WMI_FW_VER_CMDID = 0xf04e, | ||
128 | }; | ||
129 | |||
130 | /* | ||
131 | * Commands data structures | ||
132 | */ | ||
133 | |||
134 | /* | ||
135 | * Frame Types | ||
136 | */ | ||
137 | enum wmi_mgmt_frame_type { | ||
138 | WMI_FRAME_BEACON = 0, | ||
139 | WMI_FRAME_PROBE_REQ = 1, | ||
140 | WMI_FRAME_PROBE_RESP = 2, | ||
141 | WMI_FRAME_ASSOC_REQ = 3, | ||
142 | WMI_FRAME_ASSOC_RESP = 4, | ||
143 | WMI_NUM_MGMT_FRAME, | ||
144 | }; | ||
145 | |||
146 | /* | ||
147 | * WMI_CONNECT_CMDID | ||
148 | */ | ||
149 | enum wmi_network_type { | ||
150 | WMI_NETTYPE_INFRA = 0x01, | ||
151 | WMI_NETTYPE_ADHOC = 0x02, | ||
152 | WMI_NETTYPE_ADHOC_CREATOR = 0x04, | ||
153 | WMI_NETTYPE_AP = 0x10, | ||
154 | WMI_NETTYPE_P2P = 0x20, | ||
155 | WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ | ||
156 | }; | ||
157 | |||
158 | enum wmi_dot11_auth_mode { | ||
159 | WMI_AUTH11_OPEN = 0x01, | ||
160 | WMI_AUTH11_SHARED = 0x02, | ||
161 | WMI_AUTH11_LEAP = 0x04, | ||
162 | WMI_AUTH11_WSC = 0x08, | ||
163 | }; | ||
164 | |||
165 | enum wmi_auth_mode { | ||
166 | WMI_AUTH_NONE = 0x01, | ||
167 | WMI_AUTH_WPA = 0x02, | ||
168 | WMI_AUTH_WPA2 = 0x04, | ||
169 | WMI_AUTH_WPA_PSK = 0x08, | ||
170 | WMI_AUTH_WPA2_PSK = 0x10, | ||
171 | WMI_AUTH_WPA_CCKM = 0x20, | ||
172 | WMI_AUTH_WPA2_CCKM = 0x40, | ||
173 | }; | ||
174 | |||
175 | enum wmi_crypto_type { | ||
176 | WMI_CRYPT_NONE = 0x01, | ||
177 | WMI_CRYPT_WEP = 0x02, | ||
178 | WMI_CRYPT_TKIP = 0x04, | ||
179 | WMI_CRYPT_AES = 0x08, | ||
180 | WMI_CRYPT_AES_GCMP = 0x20, | ||
181 | }; | ||
182 | |||
183 | |||
184 | enum wmi_connect_ctrl_flag_bits { | ||
185 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, | ||
186 | WMI_CONNECT_SEND_REASSOC = 0x0002, | ||
187 | WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, | ||
188 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, | ||
189 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, | ||
190 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, | ||
191 | WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, | ||
192 | WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, | ||
193 | }; | ||
194 | |||
195 | #define WMI_MAX_SSID_LEN (32) | ||
196 | |||
197 | struct wmi_connect_cmd { | ||
198 | u8 network_type; | ||
199 | u8 dot11_auth_mode; | ||
200 | u8 auth_mode; | ||
201 | u8 pairwise_crypto_type; | ||
202 | u8 pairwise_crypto_len; | ||
203 | u8 group_crypto_type; | ||
204 | u8 group_crypto_len; | ||
205 | u8 ssid_len; | ||
206 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
207 | u8 channel; | ||
208 | u8 reserved0; | ||
209 | u8 bssid[WMI_MAC_LEN]; | ||
210 | __le32 ctrl_flags; | ||
211 | u8 dst_mac[WMI_MAC_LEN]; | ||
212 | u8 reserved1[2]; | ||
213 | } __packed; | ||
214 | |||
215 | |||
216 | /* | ||
217 | * WMI_RECONNECT_CMDID | ||
218 | */ | ||
219 | struct wmi_reconnect_cmd { | ||
220 | u8 channel; /* hint */ | ||
221 | u8 reserved; | ||
222 | u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ | ||
223 | } __packed; | ||
224 | |||
225 | |||
226 | /* | ||
227 | * WMI_SET_PMK_CMDID | ||
228 | */ | ||
229 | |||
230 | #define WMI_MIN_KEY_INDEX (0) | ||
231 | #define WMI_MAX_KEY_INDEX (3) | ||
232 | #define WMI_MAX_KEY_LEN (32) | ||
233 | #define WMI_PASSPHRASE_LEN (64) | ||
234 | #define WMI_PMK_LEN (32) | ||
235 | |||
236 | struct wmi_set_pmk_cmd { | ||
237 | u8 pmk[WMI_PMK_LEN]; | ||
238 | } __packed; | ||
239 | |||
240 | |||
241 | /* | ||
242 | * WMI_SET_PASSPHRASE_CMDID | ||
243 | */ | ||
244 | struct wmi_set_passphrase_cmd { | ||
245 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
246 | u8 passphrase[WMI_PASSPHRASE_LEN]; | ||
247 | u8 ssid_len; | ||
248 | u8 passphrase_len; | ||
249 | } __packed; | ||
250 | |||
251 | /* | ||
252 | * WMI_ADD_CIPHER_KEY_CMDID | ||
253 | */ | ||
254 | enum wmi_key_usage { | ||
255 | WMI_KEY_USE_PAIRWISE = 0, | ||
256 | WMI_KEY_USE_GROUP = 1, | ||
257 | WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ | ||
258 | }; | ||
259 | |||
260 | struct wmi_add_cipher_key_cmd { | ||
261 | u8 key_index; | ||
262 | u8 key_type; | ||
263 | u8 key_usage; /* enum wmi_key_usage */ | ||
264 | u8 key_len; | ||
265 | u8 key_rsc[8]; /* key replay sequence counter */ | ||
266 | u8 key[WMI_MAX_KEY_LEN]; | ||
267 | u8 key_op_ctrl; /* Additional Key Control information */ | ||
268 | u8 mac[WMI_MAC_LEN]; | ||
269 | } __packed; | ||
270 | |||
271 | /* | ||
272 | * WMI_DELETE_CIPHER_KEY_CMDID | ||
273 | */ | ||
274 | struct wmi_delete_cipher_key_cmd { | ||
275 | u8 key_index; | ||
276 | u8 mac[WMI_MAC_LEN]; | ||
277 | } __packed; | ||
278 | |||
279 | |||
280 | /* | ||
281 | * WMI_START_SCAN_CMDID | ||
282 | * | ||
283 | * Start L1 scan operation | ||
284 | * | ||
285 | * Returned events: | ||
286 | * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. | ||
287 | * - WMI_SCAN_COMPLETE_EVENTID | ||
288 | */ | ||
289 | enum wmi_scan_type { | ||
290 | WMI_LONG_SCAN = 0, | ||
291 | WMI_SHORT_SCAN = 1, | ||
292 | }; | ||
293 | |||
294 | struct wmi_start_scan_cmd { | ||
295 | u8 reserved[8]; | ||
296 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ | ||
297 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ | ||
298 | u8 scan_type; /* wmi_scan_type */ | ||
299 | u8 num_channels; /* how many channels follow */ | ||
300 | struct { | ||
301 | u8 channel; | ||
302 | u8 reserved; | ||
303 | } channel_list[0]; /* channels ID's */ | ||
304 | /* 0 - 58320 MHz */ | ||
305 | /* 1 - 60480 MHz */ | ||
306 | /* 2 - 62640 MHz */ | ||
307 | } __packed; | ||
308 | |||
309 | /* | ||
310 | * WMI_SET_PROBED_SSID_CMDID | ||
311 | */ | ||
312 | #define MAX_PROBED_SSID_INDEX (15) | ||
313 | |||
314 | enum wmi_ssid_flag { | ||
315 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ | ||
316 | WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ | ||
317 | WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ | ||
318 | }; | ||
319 | |||
320 | struct wmi_probed_ssid_cmd { | ||
321 | u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ | ||
322 | u8 flag; /* enum wmi_ssid_flag */ | ||
323 | u8 ssid_len; | ||
324 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
325 | } __packed; | ||
326 | |||
327 | /* | ||
328 | * WMI_SET_APPIE_CMDID | ||
329 | * Add Application specified IE to a management frame | ||
330 | */ | ||
331 | struct wmi_set_appie_cmd { | ||
332 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | ||
333 | u8 reserved; | ||
334 | __le16 ie_len; /* Length of the IE to be added to MGMT frame */ | ||
335 | u8 ie_info[0]; | ||
336 | } __packed; | ||
337 | |||
338 | #define WMI_MAX_IE_LEN (1024) | ||
339 | |||
340 | struct wmi_pxmt_range_cfg_cmd { | ||
341 | u8 dst_mac[WMI_MAC_LEN]; | ||
342 | __le16 range; | ||
343 | } __packed; | ||
344 | |||
345 | struct wmi_pxmt_snr2_range_cfg_cmd { | ||
346 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; | ||
347 | } __packed; | ||
348 | |||
349 | /* | ||
350 | * WMI_RF_MGMT_CMDID | ||
351 | */ | ||
352 | enum wmi_rf_mgmt_type { | ||
353 | WMI_RF_MGMT_W_DISABLE = 0, | ||
354 | WMI_RF_MGMT_W_ENABLE = 1, | ||
355 | WMI_RF_MGMT_GET_STATUS = 2, | ||
356 | }; | ||
357 | |||
358 | struct wmi_rf_mgmt_cmd { | ||
359 | __le32 rf_mgmt_type; | ||
360 | } __packed; | ||
361 | |||
362 | /* | ||
363 | * WMI_SET_SSID_CMDID | ||
364 | */ | ||
365 | struct wmi_set_ssid_cmd { | ||
366 | __le32 ssid_len; | ||
367 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
368 | } __packed; | ||
369 | |||
370 | /* | ||
371 | * WMI_SET_PCP_CHANNEL_CMDID | ||
372 | */ | ||
373 | struct wmi_set_pcp_channel_cmd { | ||
374 | u8 channel; | ||
375 | u8 reserved[3]; | ||
376 | } __packed; | ||
377 | |||
378 | /* | ||
379 | * WMI_BCON_CTRL_CMDID | ||
380 | */ | ||
381 | struct wmi_bcon_ctrl_cmd { | ||
382 | __le16 bcon_interval; | ||
383 | __le16 frag_num; | ||
384 | __le64 ss_mask; | ||
385 | u8 network_type; | ||
386 | u8 reserved; | ||
387 | u8 disable_sec_offload; | ||
388 | u8 disable_sec; | ||
389 | } __packed; | ||
390 | |||
391 | /* | ||
392 | * WMI_SW_TX_REQ_CMDID | ||
393 | */ | ||
394 | struct wmi_sw_tx_req_cmd { | ||
395 | u8 dst_mac[WMI_MAC_LEN]; | ||
396 | __le16 len; | ||
397 | u8 payload[0]; | ||
398 | } __packed; | ||
399 | |||
400 | /* | ||
401 | * WMI_VRING_CFG_CMDID | ||
402 | */ | ||
403 | |||
404 | struct wmi_sw_ring_cfg { | ||
405 | __le64 ring_mem_base; | ||
406 | __le16 ring_size; | ||
407 | __le16 max_mpdu_size; | ||
408 | } __packed; | ||
409 | |||
410 | struct wmi_vring_cfg_schd { | ||
411 | __le16 priority; | ||
412 | __le16 timeslot_us; | ||
413 | } __packed; | ||
414 | |||
415 | enum wmi_vring_cfg_encap_trans_type { | ||
416 | WMI_VRING_ENC_TYPE_802_3 = 0, | ||
417 | WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, | ||
418 | }; | ||
419 | |||
420 | enum wmi_vring_cfg_ds_cfg { | ||
421 | WMI_VRING_DS_PBSS = 0, | ||
422 | WMI_VRING_DS_STATION = 1, | ||
423 | WMI_VRING_DS_AP = 2, | ||
424 | WMI_VRING_DS_ADDR4 = 3, | ||
425 | }; | ||
426 | |||
427 | enum wmi_vring_cfg_nwifi_ds_trans_type { | ||
428 | WMI_NWIFI_TX_TRANS_MODE_NO = 0, | ||
429 | WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, | ||
430 | WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, | ||
431 | }; | ||
432 | |||
433 | enum wmi_vring_cfg_schd_params_priority { | ||
434 | WMI_SCH_PRIO_REGULAR = 0, | ||
435 | WMI_SCH_PRIO_HIGH = 1, | ||
436 | }; | ||
437 | |||
438 | struct wmi_vring_cfg { | ||
439 | struct wmi_sw_ring_cfg tx_sw_ring; | ||
440 | u8 ringid; /* 0-23 vrings */ | ||
441 | |||
442 | #define CIDXTID_CID_POS (0) | ||
443 | #define CIDXTID_CID_LEN (4) | ||
444 | #define CIDXTID_CID_MSK (0xF) | ||
445 | #define CIDXTID_TID_POS (4) | ||
446 | #define CIDXTID_TID_LEN (4) | ||
447 | #define CIDXTID_TID_MSK (0xF0) | ||
448 | u8 cidxtid; | ||
449 | |||
450 | u8 encap_trans_type; | ||
451 | u8 ds_cfg; /* 802.3 DS cfg */ | ||
452 | u8 nwifi_ds_trans_type; | ||
453 | |||
454 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) | ||
455 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) | ||
456 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) | ||
457 | #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) | ||
458 | #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) | ||
459 | #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) | ||
460 | u8 mac_ctrl; | ||
461 | |||
462 | #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) | ||
463 | #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) | ||
464 | #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) | ||
465 | u8 to_resolution; | ||
466 | u8 agg_max_wsize; | ||
467 | struct wmi_vring_cfg_schd schd_params; | ||
468 | } __packed; | ||
469 | |||
470 | enum wmi_vring_cfg_cmd_action { | ||
471 | WMI_VRING_CMD_ADD = 0, | ||
472 | WMI_VRING_CMD_MODIFY = 1, | ||
473 | WMI_VRING_CMD_DELETE = 2, | ||
474 | }; | ||
475 | |||
476 | struct wmi_vring_cfg_cmd { | ||
477 | __le32 action; | ||
478 | struct wmi_vring_cfg vring_cfg; | ||
479 | } __packed; | ||
480 | |||
481 | /* | ||
482 | * WMI_VRING_BA_EN_CMDID | ||
483 | */ | ||
484 | struct wmi_vring_ba_en_cmd { | ||
485 | u8 ringid; | ||
486 | u8 agg_max_wsize; | ||
487 | __le16 ba_timeout; | ||
488 | } __packed; | ||
489 | |||
490 | /* | ||
491 | * WMI_VRING_BA_DIS_CMDID | ||
492 | */ | ||
493 | struct wmi_vring_ba_dis_cmd { | ||
494 | u8 ringid; | ||
495 | u8 reserved; | ||
496 | __le16 reason; | ||
497 | } __packed; | ||
498 | |||
499 | /* | ||
500 | * WMI_NOTIFY_REQ_CMDID | ||
501 | */ | ||
502 | struct wmi_notify_req_cmd { | ||
503 | u8 cid; | ||
504 | u8 reserved[3]; | ||
505 | __le32 interval_usec; | ||
506 | } __packed; | ||
507 | |||
508 | /* | ||
509 | * WMI_CFG_RX_CHAIN_CMDID | ||
510 | */ | ||
511 | enum wmi_sniffer_cfg_mode { | ||
512 | WMI_SNIFFER_OFF = 0, | ||
513 | WMI_SNIFFER_ON = 1, | ||
514 | }; | ||
515 | |||
516 | enum wmi_sniffer_cfg_phy_info_mode { | ||
517 | WMI_SNIFFER_PHY_INFO_DISABLED = 0, | ||
518 | WMI_SNIFFER_PHY_INFO_ENABLED = 1, | ||
519 | }; | ||
520 | |||
521 | enum wmi_sniffer_cfg_phy_support { | ||
522 | WMI_SNIFFER_CP = 0, | ||
523 | WMI_SNIFFER_DP = 1, | ||
524 | WMI_SNIFFER_BOTH_PHYS = 2, | ||
525 | }; | ||
526 | |||
527 | struct wmi_sniffer_cfg { | ||
528 | __le32 mode; /* enum wmi_sniffer_cfg_mode */ | ||
529 | __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ | ||
530 | __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ | ||
531 | u8 channel; | ||
532 | u8 reserved[3]; | ||
533 | } __packed; | ||
534 | |||
535 | enum wmi_cfg_rx_chain_cmd_action { | ||
536 | WMI_RX_CHAIN_ADD = 0, | ||
537 | WMI_RX_CHAIN_DEL = 1, | ||
538 | }; | ||
539 | |||
540 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { | ||
541 | WMI_DECAP_TYPE_802_3 = 0, | ||
542 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, | ||
543 | }; | ||
544 | |||
545 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | ||
546 | WMI_NWIFI_RX_TRANS_MODE_NO = 0, | ||
547 | WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, | ||
548 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, | ||
549 | }; | ||
550 | |||
551 | struct wmi_cfg_rx_chain_cmd { | ||
552 | __le32 action; | ||
553 | struct wmi_sw_ring_cfg rx_sw_ring; | ||
554 | u8 mid; | ||
555 | u8 decap_trans_type; | ||
556 | |||
557 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) | ||
558 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) | ||
559 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) | ||
560 | u8 l2_802_3_offload_ctrl; | ||
561 | |||
562 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) | ||
563 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) | ||
564 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) | ||
565 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) | ||
566 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) | ||
567 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) | ||
568 | u8 l2_nwifi_offload_ctrl; | ||
569 | |||
570 | u8 vlan_id; | ||
571 | u8 nwifi_ds_trans_type; | ||
572 | |||
573 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) | ||
574 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) | ||
575 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) | ||
576 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) | ||
577 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) | ||
578 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) | ||
579 | u8 l3_l4_ctrl; | ||
580 | |||
581 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) | ||
582 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) | ||
583 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) | ||
584 | #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) | ||
585 | #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) | ||
586 | #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) | ||
587 | #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) | ||
588 | #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) | ||
589 | #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) | ||
590 | #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) | ||
591 | #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) | ||
592 | #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) | ||
593 | u8 ring_ctrl; | ||
594 | |||
595 | __le16 prefetch_thrsh; | ||
596 | __le16 wb_thrsh; | ||
597 | __le32 itr_value; | ||
598 | __le16 host_thrsh; | ||
599 | u8 reserved[2]; | ||
600 | struct wmi_sniffer_cfg sniffer_cfg; | ||
601 | } __packed; | ||
602 | |||
603 | /* | ||
604 | * WMI_RCP_ADDBA_RESP_CMDID | ||
605 | */ | ||
606 | struct wmi_rcp_addba_resp_cmd { | ||
607 | |||
608 | #define CIDXTID_CID_POS (0) | ||
609 | #define CIDXTID_CID_LEN (4) | ||
610 | #define CIDXTID_CID_MSK (0xF) | ||
611 | #define CIDXTID_TID_POS (4) | ||
612 | #define CIDXTID_TID_LEN (4) | ||
613 | #define CIDXTID_TID_MSK (0xF0) | ||
614 | u8 cidxtid; | ||
615 | |||
616 | u8 dialog_token; | ||
617 | __le16 status_code; | ||
618 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ | ||
619 | __le16 ba_timeout; | ||
620 | } __packed; | ||
621 | |||
622 | /* | ||
623 | * WMI_RCP_DELBA_CMDID | ||
624 | */ | ||
625 | struct wmi_rcp_delba_cmd { | ||
626 | |||
627 | #define CIDXTID_CID_POS (0) | ||
628 | #define CIDXTID_CID_LEN (4) | ||
629 | #define CIDXTID_CID_MSK (0xF) | ||
630 | #define CIDXTID_TID_POS (4) | ||
631 | #define CIDXTID_TID_LEN (4) | ||
632 | #define CIDXTID_TID_MSK (0xF0) | ||
633 | u8 cidxtid; | ||
634 | |||
635 | u8 reserved; | ||
636 | __le16 reason; | ||
637 | } __packed; | ||
638 | |||
639 | /* | ||
640 | * WMI_RCP_ADDBA_REQ_CMDID | ||
641 | */ | ||
642 | struct wmi_rcp_addba_req_cmd { | ||
643 | |||
644 | #define CIDXTID_CID_POS (0) | ||
645 | #define CIDXTID_CID_LEN (4) | ||
646 | #define CIDXTID_CID_MSK (0xF) | ||
647 | #define CIDXTID_TID_POS (4) | ||
648 | #define CIDXTID_TID_LEN (4) | ||
649 | #define CIDXTID_TID_MSK (0xF0) | ||
650 | u8 cidxtid; | ||
651 | |||
652 | u8 dialog_token; | ||
653 | /* ieee80211_ba_parameterset field as it received */ | ||
654 | __le16 ba_param_set; | ||
655 | __le16 ba_timeout; | ||
656 | /* ieee80211_ba_seqstrl field as it received */ | ||
657 | __le16 ba_seq_ctrl; | ||
658 | } __packed; | ||
659 | |||
660 | /* | ||
661 | * WMI_SET_MAC_ADDRESS_CMDID | ||
662 | */ | ||
663 | struct wmi_set_mac_address_cmd { | ||
664 | u8 mac[WMI_MAC_LEN]; | ||
665 | u8 reserved[2]; | ||
666 | } __packed; | ||
667 | |||
668 | |||
669 | /* | ||
670 | * WMI_EAPOL_TX_CMDID | ||
671 | */ | ||
672 | struct wmi_eapol_tx_cmd { | ||
673 | u8 dst_mac[WMI_MAC_LEN]; | ||
674 | __le16 eapol_len; | ||
675 | u8 eapol[0]; | ||
676 | } __packed; | ||
677 | |||
678 | /* | ||
679 | * WMI_ECHO_CMDID | ||
680 | * | ||
681 | * Check FW is alive | ||
682 | * | ||
683 | * WMI_DEEP_ECHO_CMDID | ||
684 | * | ||
685 | * Check FW and ucode are alive | ||
686 | * | ||
687 | * Returned event: WMI_ECHO_RSP_EVENTID | ||
688 | * same event for both commands | ||
689 | */ | ||
690 | struct wmi_echo_cmd { | ||
691 | __le32 value; | ||
692 | } __packed; | ||
693 | |||
694 | /* | ||
695 | * WMI Events | ||
696 | */ | ||
697 | |||
698 | /* | ||
699 | * List of Events (target to host) | ||
700 | */ | ||
701 | enum wmi_event_id { | ||
702 | WMI_IMM_RSP_EVENTID = 0x0000, | ||
703 | WMI_READY_EVENTID = 0x1001, | ||
704 | WMI_CONNECT_EVENTID = 0x1002, | ||
705 | WMI_DISCONNECT_EVENTID = 0x1003, | ||
706 | WMI_SCAN_COMPLETE_EVENTID = 0x100a, | ||
707 | WMI_REPORT_STATISTICS_EVENTID = 0x100b, | ||
708 | WMI_RD_MEM_RSP_EVENTID = 0x1800, | ||
709 | WMI_FW_READY_EVENTID = 0x1801, | ||
710 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, | ||
711 | WMI_ECHO_RSP_EVENTID = 0x1803, | ||
712 | WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, | ||
713 | WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, | ||
714 | WMI_ADD_STATION_DONE_EVENTID = 0x1807, | ||
715 | WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, | ||
716 | WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, | ||
717 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, | ||
718 | WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, | ||
719 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, | ||
720 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, | ||
721 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, | ||
722 | WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, | ||
723 | WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, | ||
724 | WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, | ||
725 | WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, | ||
726 | WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, | ||
727 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | ||
728 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | ||
729 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, | ||
730 | |||
731 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, | ||
732 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, | ||
733 | WMI_RX_ON_DONE_EVENTID = 0x1822, | ||
734 | WMI_BA_STATUS_EVENTID = 0x1823, | ||
735 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, | ||
736 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, | ||
737 | WMI_DELBA_EVENTID = 0x1826, | ||
738 | WMI_GET_SSID_EVENTID = 0x1828, | ||
739 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, | ||
740 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, | ||
741 | WMI_RX_OFF_DONE_EVENTID = 0x182c, | ||
742 | |||
743 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, | ||
744 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, | ||
745 | WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, | ||
746 | WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, | ||
747 | WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, | ||
748 | |||
749 | WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, | ||
750 | WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, | ||
751 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, | ||
752 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, | ||
753 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, | ||
754 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, | ||
755 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, | ||
756 | |||
757 | /* Performance monitoring events */ | ||
758 | WMI_DATA_PORT_OPEN_EVENTID = 0x1860, | ||
759 | WMI_WBE_LINKDOWN_EVENTID = 0x1861, | ||
760 | |||
761 | WMI_BF_CTRL_DONE_EVENTID = 0x1862, | ||
762 | WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, | ||
763 | WMI_GET_STATUS_DONE_EVENTID = 0x1864, | ||
764 | |||
765 | WMI_UNIT_TEST_EVENTID = 0x1900, | ||
766 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | ||
767 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | ||
768 | |||
769 | WMI_SET_CHANNEL_EVENTID = 0x9000, | ||
770 | WMI_ASSOC_REQ_EVENTID = 0x9001, | ||
771 | WMI_EAPOL_RX_EVENTID = 0x9002, | ||
772 | WMI_MAC_ADDR_RESP_EVENTID = 0x9003, | ||
773 | WMI_FW_VER_EVENTID = 0x9004, | ||
774 | }; | ||
775 | |||
776 | /* | ||
777 | * Events data structures | ||
778 | */ | ||
779 | |||
780 | /* | ||
781 | * WMI_RF_MGMT_STATUS_EVENTID | ||
782 | */ | ||
783 | enum wmi_rf_status { | ||
784 | WMI_RF_ENABLED = 0, | ||
785 | WMI_RF_DISABLED_HW = 1, | ||
786 | WMI_RF_DISABLED_SW = 2, | ||
787 | WMI_RF_DISABLED_HW_SW = 3, | ||
788 | }; | ||
789 | |||
790 | struct wmi_rf_mgmt_status_event { | ||
791 | __le32 rf_status; | ||
792 | } __packed; | ||
793 | |||
794 | /* | ||
795 | * WMI_GET_STATUS_DONE_EVENTID | ||
796 | */ | ||
797 | struct wmi_get_status_done_event { | ||
798 | __le32 is_associated; | ||
799 | u8 cid; | ||
800 | u8 reserved0[3]; | ||
801 | u8 bssid[WMI_MAC_LEN]; | ||
802 | u8 channel; | ||
803 | u8 reserved1; | ||
804 | u8 network_type; | ||
805 | u8 reserved2[3]; | ||
806 | __le32 ssid_len; | ||
807 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
808 | __le32 rf_status; | ||
809 | __le32 is_secured; | ||
810 | } __packed; | ||
811 | |||
812 | /* | ||
813 | * WMI_FW_VER_EVENTID | ||
814 | */ | ||
815 | struct wmi_fw_ver_event { | ||
816 | u8 major; | ||
817 | u8 minor; | ||
818 | __le16 subminor; | ||
819 | __le16 build; | ||
820 | } __packed; | ||
821 | |||
822 | /* | ||
823 | * WMI_MAC_ADDR_RESP_EVENTID | ||
824 | */ | ||
825 | struct wmi_mac_addr_resp_event { | ||
826 | u8 mac[WMI_MAC_LEN]; | ||
827 | u8 auth_mode; | ||
828 | u8 crypt_mode; | ||
829 | __le32 offload_mode; | ||
830 | } __packed; | ||
831 | |||
832 | /* | ||
833 | * WMI_EAPOL_RX_EVENTID | ||
834 | */ | ||
835 | struct wmi_eapol_rx_event { | ||
836 | u8 src_mac[WMI_MAC_LEN]; | ||
837 | __le16 eapol_len; | ||
838 | u8 eapol[0]; | ||
839 | } __packed; | ||
840 | |||
841 | /* | ||
842 | * WMI_READY_EVENTID | ||
843 | */ | ||
844 | enum wmi_phy_capability { | ||
845 | WMI_11A_CAPABILITY = 1, | ||
846 | WMI_11G_CAPABILITY = 2, | ||
847 | WMI_11AG_CAPABILITY = 3, | ||
848 | WMI_11NA_CAPABILITY = 4, | ||
849 | WMI_11NG_CAPABILITY = 5, | ||
850 | WMI_11NAG_CAPABILITY = 6, | ||
851 | WMI_11AD_CAPABILITY = 7, | ||
852 | WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, | ||
853 | }; | ||
854 | |||
855 | struct wmi_ready_event { | ||
856 | __le32 sw_version; | ||
857 | __le32 abi_version; | ||
858 | u8 mac[WMI_MAC_LEN]; | ||
859 | u8 phy_capability; /* enum wmi_phy_capability */ | ||
860 | u8 reserved; | ||
861 | } __packed; | ||
862 | |||
863 | /* | ||
864 | * WMI_NOTIFY_REQ_DONE_EVENTID | ||
865 | */ | ||
866 | struct wmi_notify_req_done_event { | ||
867 | __le32 status; | ||
868 | __le64 tsf; | ||
869 | __le32 snr_val; | ||
870 | __le32 tx_tpt; | ||
871 | __le32 tx_goodput; | ||
872 | __le32 rx_goodput; | ||
873 | __le16 bf_mcs; | ||
874 | __le16 my_rx_sector; | ||
875 | __le16 my_tx_sector; | ||
876 | __le16 other_rx_sector; | ||
877 | __le16 other_tx_sector; | ||
878 | __le16 range; | ||
879 | } __packed; | ||
880 | |||
881 | /* | ||
882 | * WMI_CONNECT_EVENTID | ||
883 | */ | ||
884 | struct wmi_connect_event { | ||
885 | u8 channel; | ||
886 | u8 reserved0; | ||
887 | u8 bssid[WMI_MAC_LEN]; | ||
888 | __le16 listen_interval; | ||
889 | __le16 beacon_interval; | ||
890 | u8 network_type; | ||
891 | u8 reserved1[3]; | ||
892 | u8 beacon_ie_len; | ||
893 | u8 assoc_req_len; | ||
894 | u8 assoc_resp_len; | ||
895 | u8 cid; | ||
896 | u8 reserved2[3]; | ||
897 | u8 assoc_info[0]; | ||
898 | } __packed; | ||
899 | |||
900 | /* | ||
901 | * WMI_DISCONNECT_EVENTID | ||
902 | */ | ||
903 | enum wmi_disconnect_reason { | ||
904 | WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, | ||
905 | WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ | ||
906 | WMI_DIS_REASON_DISCONNECT_CMD = 3, | ||
907 | WMI_DIS_REASON_BSS_DISCONNECTED = 4, | ||
908 | WMI_DIS_REASON_AUTH_FAILED = 5, | ||
909 | WMI_DIS_REASON_ASSOC_FAILED = 6, | ||
910 | WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, | ||
911 | WMI_DIS_REASON_CSERV_DISCONNECT = 8, | ||
912 | WMI_DIS_REASON_INVALID_PROFILE = 10, | ||
913 | WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, | ||
914 | WMI_DIS_REASON_PROFILE_MISMATCH = 12, | ||
915 | WMI_DIS_REASON_CONNECTION_EVICTED = 13, | ||
916 | WMI_DIS_REASON_IBSS_MERGE = 14, | ||
917 | }; | ||
918 | |||
919 | struct wmi_disconnect_event { | ||
920 | __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ | ||
921 | u8 bssid[WMI_MAC_LEN]; /* set if known */ | ||
922 | u8 disconnect_reason; /* see wmi_disconnect_reason_e */ | ||
923 | u8 assoc_resp_len; | ||
924 | u8 assoc_info[0]; | ||
925 | } __packed; | ||
926 | |||
927 | /* | ||
928 | * WMI_SCAN_COMPLETE_EVENTID | ||
929 | */ | ||
930 | struct wmi_scan_complete_event { | ||
931 | __le32 status; | ||
932 | } __packed; | ||
933 | |||
934 | /* | ||
935 | * WMI_BA_STATUS_EVENTID | ||
936 | */ | ||
937 | enum wmi_vring_ba_status { | ||
938 | WMI_BA_AGREED = 0, | ||
939 | WMI_BA_NON_AGREED = 1, | ||
940 | }; | ||
941 | |||
942 | struct wmi_vring_ba_status_event { | ||
943 | __le16 status; | ||
944 | u8 reserved[2]; | ||
945 | u8 ringid; | ||
946 | u8 agg_wsize; | ||
947 | __le16 ba_timeout; | ||
948 | } __packed; | ||
949 | |||
950 | /* | ||
951 | * WMI_DELBA_EVENTID | ||
952 | */ | ||
953 | struct wmi_delba_event { | ||
954 | |||
955 | #define CIDXTID_CID_POS (0) | ||
956 | #define CIDXTID_CID_LEN (4) | ||
957 | #define CIDXTID_CID_MSK (0xF) | ||
958 | #define CIDXTID_TID_POS (4) | ||
959 | #define CIDXTID_TID_LEN (4) | ||
960 | #define CIDXTID_TID_MSK (0xF0) | ||
961 | u8 cidxtid; | ||
962 | |||
963 | u8 from_initiator; | ||
964 | __le16 reason; | ||
965 | } __packed; | ||
966 | |||
967 | /* | ||
968 | * WMI_VRING_CFG_DONE_EVENTID | ||
969 | */ | ||
970 | enum wmi_vring_cfg_done_event_status { | ||
971 | WMI_VRING_CFG_SUCCESS = 0, | ||
972 | WMI_VRING_CFG_FAILURE = 1, | ||
973 | }; | ||
974 | |||
975 | struct wmi_vring_cfg_done_event { | ||
976 | u8 ringid; | ||
977 | u8 status; | ||
978 | u8 reserved[2]; | ||
979 | __le32 tx_vring_tail_ptr; | ||
980 | } __packed; | ||
981 | |||
982 | /* | ||
983 | * WMI_ADDBA_RESP_SENT_EVENTID | ||
984 | */ | ||
985 | enum wmi_rcp_addba_resp_sent_event_status { | ||
986 | WMI_ADDBA_SUCCESS = 0, | ||
987 | WMI_ADDBA_FAIL = 1, | ||
988 | }; | ||
989 | |||
990 | struct wmi_rcp_addba_resp_sent_event { | ||
991 | |||
992 | #define CIDXTID_CID_POS (0) | ||
993 | #define CIDXTID_CID_LEN (4) | ||
994 | #define CIDXTID_CID_MSK (0xF) | ||
995 | #define CIDXTID_TID_POS (4) | ||
996 | #define CIDXTID_TID_LEN (4) | ||
997 | #define CIDXTID_TID_MSK (0xF0) | ||
998 | u8 cidxtid; | ||
999 | |||
1000 | u8 reserved; | ||
1001 | __le16 status; | ||
1002 | } __packed; | ||
1003 | |||
1004 | /* | ||
1005 | * WMI_RCP_ADDBA_REQ_EVENTID | ||
1006 | */ | ||
1007 | struct wmi_rcp_addba_req_event { | ||
1008 | |||
1009 | #define CIDXTID_CID_POS (0) | ||
1010 | #define CIDXTID_CID_LEN (4) | ||
1011 | #define CIDXTID_CID_MSK (0xF) | ||
1012 | #define CIDXTID_TID_POS (4) | ||
1013 | #define CIDXTID_TID_LEN (4) | ||
1014 | #define CIDXTID_TID_MSK (0xF0) | ||
1015 | u8 cidxtid; | ||
1016 | |||
1017 | u8 dialog_token; | ||
1018 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ | ||
1019 | __le16 ba_timeout; | ||
1020 | __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ | ||
1021 | } __packed; | ||
1022 | |||
1023 | /* | ||
1024 | * WMI_CFG_RX_CHAIN_DONE_EVENTID | ||
1025 | */ | ||
1026 | enum wmi_cfg_rx_chain_done_event_status { | ||
1027 | WMI_CFG_RX_CHAIN_SUCCESS = 1, | ||
1028 | }; | ||
1029 | |||
1030 | struct wmi_cfg_rx_chain_done_event { | ||
1031 | __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ | ||
1032 | __le32 status; | ||
1033 | } __packed; | ||
1034 | |||
1035 | /* | ||
1036 | * WMI_WBE_LINKDOWN_EVENTID | ||
1037 | */ | ||
1038 | enum wmi_wbe_link_down_event_reason { | ||
1039 | WMI_WBE_REASON_USER_REQUEST = 0, | ||
1040 | WMI_WBE_REASON_RX_DISASSOC = 1, | ||
1041 | WMI_WBE_REASON_BAD_PHY_LINK = 2, | ||
1042 | }; | ||
1043 | |||
1044 | struct wmi_wbe_link_down_event { | ||
1045 | u8 cid; | ||
1046 | u8 reserved[3]; | ||
1047 | __le32 reason; | ||
1048 | } __packed; | ||
1049 | |||
1050 | /* | ||
1051 | * WMI_DATA_PORT_OPEN_EVENTID | ||
1052 | */ | ||
1053 | struct wmi_data_port_open_event { | ||
1054 | u8 cid; | ||
1055 | u8 reserved[3]; | ||
1056 | } __packed; | ||
1057 | |||
1058 | /* | ||
1059 | * WMI_GET_PCP_CHANNEL_EVENTID | ||
1060 | */ | ||
1061 | struct wmi_get_pcp_channel_event { | ||
1062 | u8 channel; | ||
1063 | u8 reserved[3]; | ||
1064 | } __packed; | ||
1065 | |||
1066 | /* | ||
1067 | * WMI_SW_TX_COMPLETE_EVENTID | ||
1068 | */ | ||
1069 | enum wmi_sw_tx_status { | ||
1070 | WMI_TX_SW_STATUS_SUCCESS = 0, | ||
1071 | WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, | ||
1072 | WMI_TX_SW_STATUS_FAILED_TX = 2, | ||
1073 | }; | ||
1074 | |||
1075 | struct wmi_sw_tx_complete_event { | ||
1076 | u8 status; /* enum wmi_sw_tx_status */ | ||
1077 | u8 reserved[3]; | ||
1078 | } __packed; | ||
1079 | |||
1080 | /* | ||
1081 | * WMI_GET_SSID_EVENTID | ||
1082 | */ | ||
1083 | struct wmi_get_ssid_event { | ||
1084 | __le32 ssid_len; | ||
1085 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
1086 | } __packed; | ||
1087 | |||
1088 | /* | ||
1089 | * WMI_RX_MGMT_PACKET_EVENTID | ||
1090 | */ | ||
1091 | struct wmi_rx_mgmt_info { | ||
1092 | u8 mcs; | ||
1093 | s8 snr; | ||
1094 | __le16 range; | ||
1095 | __le16 stype; | ||
1096 | __le16 status; | ||
1097 | __le32 len; | ||
1098 | u8 qid; | ||
1099 | u8 mid; | ||
1100 | u8 cid; | ||
1101 | u8 channel; /* From Radio MNGR */ | ||
1102 | } __packed; | ||
1103 | |||
1104 | struct wmi_rx_mgmt_packet_event { | ||
1105 | struct wmi_rx_mgmt_info info; | ||
1106 | u8 payload[0]; | ||
1107 | } __packed; | ||
1108 | |||
1109 | /* | ||
1110 | * WMI_ECHO_RSP_EVENTID | ||
1111 | */ | ||
1112 | struct wmi_echo_event { | ||
1113 | __le32 echoed_value; | ||
1114 | } __packed; | ||
1115 | |||
1116 | #endif /* __WILOCITY_WMI_H__ */ | ||
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b298e5d68be2..10e288d470e7 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/hw_random.h> | 7 | #include <linux/hw_random.h> |
8 | #include <linux/bcma/bcma.h> | 8 | #include <linux/bcma/bcma.h> |
9 | #include <linux/ssb/ssb.h> | 9 | #include <linux/ssb/ssb.h> |
10 | #include <linux/completion.h> | ||
10 | #include <net/mac80211.h> | 11 | #include <net/mac80211.h> |
11 | 12 | ||
12 | #include "debugfs.h" | 13 | #include "debugfs.h" |
@@ -722,6 +723,10 @@ enum b43_firmware_file_type { | |||
722 | struct b43_request_fw_context { | 723 | struct b43_request_fw_context { |
723 | /* The device we are requesting the fw for. */ | 724 | /* The device we are requesting the fw for. */ |
724 | struct b43_wldev *dev; | 725 | struct b43_wldev *dev; |
726 | /* a completion event structure needed if this call is asynchronous */ | ||
727 | struct completion fw_load_complete; | ||
728 | /* a pointer to the firmware object */ | ||
729 | const struct firmware *blob; | ||
725 | /* The type of firmware to request. */ | 730 | /* The type of firmware to request. */ |
726 | enum b43_firmware_file_type req_type; | 731 | enum b43_firmware_file_type req_type; |
727 | /* Error messages for each firmware type. */ | 732 | /* Error messages for each firmware type. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 16ab280359bd..806e34c19281 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
2088 | b43warn(wl, text); | 2088 | b43warn(wl, text); |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | static void b43_fw_cb(const struct firmware *firmware, void *context) | ||
2092 | { | ||
2093 | struct b43_request_fw_context *ctx = context; | ||
2094 | |||
2095 | ctx->blob = firmware; | ||
2096 | complete(&ctx->fw_load_complete); | ||
2097 | } | ||
2098 | |||
2091 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 2099 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
2092 | const char *name, | 2100 | const char *name, |
2093 | struct b43_firmware_file *fw) | 2101 | struct b43_firmware_file *fw, bool async) |
2094 | { | 2102 | { |
2095 | const struct firmware *blob; | ||
2096 | struct b43_fw_header *hdr; | 2103 | struct b43_fw_header *hdr; |
2097 | u32 size; | 2104 | u32 size; |
2098 | int err; | 2105 | int err; |
@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2131 | B43_WARN_ON(1); | 2138 | B43_WARN_ON(1); |
2132 | return -ENOSYS; | 2139 | return -ENOSYS; |
2133 | } | 2140 | } |
2134 | err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); | 2141 | if (async) { |
2142 | /* do this part asynchronously */ | ||
2143 | init_completion(&ctx->fw_load_complete); | ||
2144 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, | ||
2145 | ctx->dev->dev->dev, GFP_KERNEL, | ||
2146 | ctx, b43_fw_cb); | ||
2147 | if (err < 0) { | ||
2148 | pr_err("Unable to load firmware\n"); | ||
2149 | return err; | ||
2150 | } | ||
2151 | /* stall here until fw ready */ | ||
2152 | wait_for_completion(&ctx->fw_load_complete); | ||
2153 | if (ctx->blob) | ||
2154 | goto fw_ready; | ||
2155 | /* On some ARM systems, the async request will fail, but the next sync | ||
2156 | * request works. For this reason, we dall through here | ||
2157 | */ | ||
2158 | } | ||
2159 | err = request_firmware(&ctx->blob, ctx->fwname, | ||
2160 | ctx->dev->dev->dev); | ||
2135 | if (err == -ENOENT) { | 2161 | if (err == -ENOENT) { |
2136 | snprintf(ctx->errors[ctx->req_type], | 2162 | snprintf(ctx->errors[ctx->req_type], |
2137 | sizeof(ctx->errors[ctx->req_type]), | 2163 | sizeof(ctx->errors[ctx->req_type]), |
2138 | "Firmware file \"%s\" not found\n", ctx->fwname); | 2164 | "Firmware file \"%s\" not found\n", |
2165 | ctx->fwname); | ||
2139 | return err; | 2166 | return err; |
2140 | } else if (err) { | 2167 | } else if (err) { |
2141 | snprintf(ctx->errors[ctx->req_type], | 2168 | snprintf(ctx->errors[ctx->req_type], |
@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2144 | ctx->fwname, err); | 2171 | ctx->fwname, err); |
2145 | return err; | 2172 | return err; |
2146 | } | 2173 | } |
2147 | if (blob->size < sizeof(struct b43_fw_header)) | 2174 | fw_ready: |
2175 | if (ctx->blob->size < sizeof(struct b43_fw_header)) | ||
2148 | goto err_format; | 2176 | goto err_format; |
2149 | hdr = (struct b43_fw_header *)(blob->data); | 2177 | hdr = (struct b43_fw_header *)(ctx->blob->data); |
2150 | switch (hdr->type) { | 2178 | switch (hdr->type) { |
2151 | case B43_FW_TYPE_UCODE: | 2179 | case B43_FW_TYPE_UCODE: |
2152 | case B43_FW_TYPE_PCM: | 2180 | case B43_FW_TYPE_PCM: |
2153 | size = be32_to_cpu(hdr->size); | 2181 | size = be32_to_cpu(hdr->size); |
2154 | if (size != blob->size - sizeof(struct b43_fw_header)) | 2182 | if (size != ctx->blob->size - sizeof(struct b43_fw_header)) |
2155 | goto err_format; | 2183 | goto err_format; |
2156 | /* fallthrough */ | 2184 | /* fallthrough */ |
2157 | case B43_FW_TYPE_IV: | 2185 | case B43_FW_TYPE_IV: |
@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2162 | goto err_format; | 2190 | goto err_format; |
2163 | } | 2191 | } |
2164 | 2192 | ||
2165 | fw->data = blob; | 2193 | fw->data = ctx->blob; |
2166 | fw->filename = name; | 2194 | fw->filename = name; |
2167 | fw->type = ctx->req_type; | 2195 | fw->type = ctx->req_type; |
2168 | 2196 | ||
@@ -2172,7 +2200,7 @@ err_format: | |||
2172 | snprintf(ctx->errors[ctx->req_type], | 2200 | snprintf(ctx->errors[ctx->req_type], |
2173 | sizeof(ctx->errors[ctx->req_type]), | 2201 | sizeof(ctx->errors[ctx->req_type]), |
2174 | "Firmware file \"%s\" format error.\n", ctx->fwname); | 2202 | "Firmware file \"%s\" format error.\n", ctx->fwname); |
2175 | release_firmware(blob); | 2203 | release_firmware(ctx->blob); |
2176 | 2204 | ||
2177 | return -EPROTO; | 2205 | return -EPROTO; |
2178 | } | 2206 | } |
@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2223 | goto err_no_ucode; | 2251 | goto err_no_ucode; |
2224 | } | 2252 | } |
2225 | } | 2253 | } |
2226 | err = b43_do_request_fw(ctx, filename, &fw->ucode); | 2254 | err = b43_do_request_fw(ctx, filename, &fw->ucode, true); |
2227 | if (err) | 2255 | if (err) |
2228 | goto err_load; | 2256 | goto err_load; |
2229 | 2257 | ||
@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2235 | else | 2263 | else |
2236 | goto err_no_pcm; | 2264 | goto err_no_pcm; |
2237 | fw->pcm_request_failed = false; | 2265 | fw->pcm_request_failed = false; |
2238 | err = b43_do_request_fw(ctx, filename, &fw->pcm); | 2266 | err = b43_do_request_fw(ctx, filename, &fw->pcm, false); |
2239 | if (err == -ENOENT) { | 2267 | if (err == -ENOENT) { |
2240 | /* We did not find a PCM file? Not fatal, but | 2268 | /* We did not find a PCM file? Not fatal, but |
2241 | * core rev <= 10 must do without hwcrypto then. */ | 2269 | * core rev <= 10 must do without hwcrypto then. */ |
@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2296 | default: | 2324 | default: |
2297 | goto err_no_initvals; | 2325 | goto err_no_initvals; |
2298 | } | 2326 | } |
2299 | err = b43_do_request_fw(ctx, filename, &fw->initvals); | 2327 | err = b43_do_request_fw(ctx, filename, &fw->initvals, false); |
2300 | if (err) | 2328 | if (err) |
2301 | goto err_load; | 2329 | goto err_load; |
2302 | 2330 | ||
@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2355 | default: | 2383 | default: |
2356 | goto err_no_initvals; | 2384 | goto err_no_initvals; |
2357 | } | 2385 | } |
2358 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band); | 2386 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); |
2359 | if (err) | 2387 | if (err) |
2360 | goto err_load; | 2388 | goto err_load; |
2361 | 2389 | ||
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd33529..abac25ee958d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); | |||
137 | 137 | ||
138 | 138 | ||
139 | struct b43_request_fw_context; | 139 | struct b43_request_fw_context; |
140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, |
141 | const char *name, | 141 | struct b43_firmware_file *fw, bool async); |
142 | struct b43_firmware_file *fw); | ||
143 | void b43_do_release_fw(struct b43_firmware_file *fw); | 142 | void b43_do_release_fw(struct b43_firmware_file *fw); |
144 | 143 | ||
145 | #endif /* B43_MAIN_H_ */ | 144 | #endif /* B43_MAIN_H_ */ |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index d604b4036a76..3726cd6fcd75 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, | |||
3273 | 3273 | ||
3274 | if (count) { | 3274 | if (count) { |
3275 | char *p = buffer; | 3275 | char *p = buffer; |
3276 | strncpy(buffer, buf, min(sizeof(buffer), count)); | 3276 | strlcpy(buffer, buf, sizeof(buffer)); |
3277 | channel = simple_strtoul(p, NULL, 0); | 3277 | channel = simple_strtoul(p, NULL, 0); |
3278 | if (channel) | 3278 | if (channel) |
3279 | params.channel = channel; | 3279 | params.channel = channel; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index da21328ca8ed..a790599fe2c2 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -1151,13 +1151,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1151 | next_reclaimed = ssn; | 1151 | next_reclaimed = ssn; |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | if (tid != IWL_TID_NON_QOS) { | ||
1155 | priv->tid_data[sta_id][tid].next_reclaimed = | ||
1156 | next_reclaimed; | ||
1157 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", | ||
1158 | next_reclaimed); | ||
1159 | } | ||
1160 | |||
1161 | iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); | 1154 | iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); |
1162 | 1155 | ||
1163 | iwlagn_check_ratid_empty(priv, sta_id, tid); | 1156 | iwlagn_check_ratid_empty(priv, sta_id, tid); |
@@ -1208,11 +1201,28 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1208 | if (!is_agg) | 1201 | if (!is_agg) |
1209 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); | 1202 | iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); |
1210 | 1203 | ||
1204 | /* | ||
1205 | * W/A for FW bug - the seq_ctl isn't updated when the | ||
1206 | * queues are flushed. Fetch it from the packet itself | ||
1207 | */ | ||
1208 | if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { | ||
1209 | next_reclaimed = le16_to_cpu(hdr->seq_ctrl); | ||
1210 | next_reclaimed = | ||
1211 | SEQ_TO_SN(next_reclaimed + 0x10); | ||
1212 | } | ||
1213 | |||
1211 | is_offchannel_skb = | 1214 | is_offchannel_skb = |
1212 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); | 1215 | (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); |
1213 | freed++; | 1216 | freed++; |
1214 | } | 1217 | } |
1215 | 1218 | ||
1219 | if (tid != IWL_TID_NON_QOS) { | ||
1220 | priv->tid_data[sta_id][tid].next_reclaimed = | ||
1221 | next_reclaimed; | ||
1222 | IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", | ||
1223 | next_reclaimed); | ||
1224 | } | ||
1225 | |||
1216 | WARN_ON(!is_agg && freed != 1); | 1226 | WARN_ON(!is_agg && freed != 1); |
1217 | 1227 | ||
1218 | /* | 1228 | /* |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index dad4c4aad91f..8389cd38338b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -1166,6 +1166,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1166 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1166 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
1167 | !trans_pcie->inta) | 1167 | !trans_pcie->inta) |
1168 | iwl_enable_interrupts(trans); | 1168 | iwl_enable_interrupts(trans); |
1169 | return IRQ_HANDLED; | ||
1169 | 1170 | ||
1170 | none: | 1171 | none: |
1171 | /* re-enable interrupts here since we don't have anything to service. */ | 1172 | /* re-enable interrupts here since we don't have anything to service. */ |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a875499f8945..efe525be27dd 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1709,7 +1709,7 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, | |||
1709 | NL80211_CHAN_NO_HT) | 1709 | NL80211_CHAN_NO_HT) |
1710 | config_bands |= BAND_GN; | 1710 | config_bands |= BAND_GN; |
1711 | } else { | 1711 | } else { |
1712 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1712 | if (cfg80211_get_chandef_type(¶ms->chandef) == |
1713 | NL80211_CHAN_NO_HT) | 1713 | NL80211_CHAN_NO_HT) |
1714 | config_bands = BAND_A; | 1714 | config_bands = BAND_A; |
1715 | else | 1715 | else |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index cb682561c438..60e88b58039d 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | |||
56 | */ | 56 | */ |
57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) |
58 | { | 58 | { |
59 | bool cancel_flag = false; | ||
60 | int status; | 59 | int status; |
61 | struct cmd_ctrl_node *cmd_queued; | 60 | struct cmd_ctrl_node *cmd_queued; |
62 | 61 | ||
@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | |||
70 | atomic_inc(&adapter->cmd_pending); | 69 | atomic_inc(&adapter->cmd_pending); |
71 | 70 | ||
72 | /* Wait for completion */ | 71 | /* Wait for completion */ |
73 | wait_event_interruptible(adapter->cmd_wait_q.wait, | 72 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, |
74 | *(cmd_queued->condition)); | 73 | *(cmd_queued->condition)); |
75 | if (!*(cmd_queued->condition)) | 74 | if (status) { |
76 | cancel_flag = true; | 75 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
77 | 76 | return status; | |
78 | if (cancel_flag) { | ||
79 | mwifiex_cancel_pending_ioctl(adapter); | ||
80 | dev_dbg(adapter->dev, "cmd cancel\n"); | ||
81 | } | 77 | } |
82 | 78 | ||
83 | status = adapter->cmd_wait_q.status; | 79 | status = adapter->cmd_wait_q.status; |
@@ -496,8 +492,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | |||
496 | return false; | 492 | return false; |
497 | } | 493 | } |
498 | 494 | ||
499 | wait_event_interruptible(adapter->hs_activate_wait_q, | 495 | if (wait_event_interruptible(adapter->hs_activate_wait_q, |
500 | adapter->hs_activate_wait_q_woken); | 496 | adapter->hs_activate_wait_q_woken)) { |
497 | dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); | ||
498 | return false; | ||
499 | } | ||
501 | 500 | ||
502 | return true; | 501 | return true; |
503 | } | 502 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f221b95b90b3..83564d36e801 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -4250,9 +4250,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, | |||
4250 | p->amsdu_enabled = 0; | 4250 | p->amsdu_enabled = 0; |
4251 | 4251 | ||
4252 | rc = mwl8k_post_cmd(hw, &cmd->header); | 4252 | rc = mwl8k_post_cmd(hw, &cmd->header); |
4253 | if (!rc) | ||
4254 | rc = p->station_id; | ||
4253 | kfree(cmd); | 4255 | kfree(cmd); |
4254 | 4256 | ||
4255 | return rc ? rc : p->station_id; | 4257 | return rc; |
4256 | } | 4258 | } |
4257 | 4259 | ||
4258 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, | 4260 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 1d5d3604e3e0..246e5352f2e1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | |||
@@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) | |||
692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
693 | rtl92c_phy_sw_chnl_callback(hw); | 693 | rtl92c_phy_sw_chnl_callback(hw); |
694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
695 | "sw_chnl_inprogress false schdule workitem\n"); | 695 | "sw_chnl_inprogress false schedule workitem\n"); |
696 | rtlphy->sw_chnl_inprogress = false; | 696 | rtlphy->sw_chnl_inprogress = false; |
697 | } else { | 697 | } else { |
698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index 39cc7938eedf..3d8536bb0d2b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c | |||
@@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw) | |||
1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
1107 | rtl8723ae_phy_sw_chnl_callback(hw); | 1107 | rtl8723ae_phy_sw_chnl_callback(hw); |
1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
1109 | "sw_chnl_inprogress false schdule workitem\n"); | 1109 | "sw_chnl_inprogress false schedule workitem\n"); |
1110 | rtlphy->sw_chnl_inprogress = false; | 1110 | rtlphy->sw_chnl_inprogress = false; |
1111 | } else { | 1111 | } else { |
1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 26ffd3e3fb74..2c113de94323 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; | |||
44 | extern int pciehp_poll_time; | 44 | extern int pciehp_poll_time; |
45 | extern bool pciehp_debug; | 45 | extern bool pciehp_debug; |
46 | extern bool pciehp_force; | 46 | extern bool pciehp_force; |
47 | extern struct workqueue_struct *pciehp_wq; | ||
48 | 47 | ||
49 | #define dbg(format, arg...) \ | 48 | #define dbg(format, arg...) \ |
50 | do { \ | 49 | do { \ |
@@ -78,6 +77,7 @@ struct slot { | |||
78 | struct hotplug_slot *hotplug_slot; | 77 | struct hotplug_slot *hotplug_slot; |
79 | struct delayed_work work; /* work for button event */ | 78 | struct delayed_work work; /* work for button event */ |
80 | struct mutex lock; | 79 | struct mutex lock; |
80 | struct workqueue_struct *wq; | ||
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct event_info { | 83 | struct event_info { |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 916bf4f53aba..939bd1d4b5b1 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -42,7 +42,6 @@ bool pciehp_debug; | |||
42 | bool pciehp_poll_mode; | 42 | bool pciehp_poll_mode; |
43 | int pciehp_poll_time; | 43 | int pciehp_poll_time; |
44 | bool pciehp_force; | 44 | bool pciehp_force; |
45 | struct workqueue_struct *pciehp_wq; | ||
46 | 45 | ||
47 | #define DRIVER_VERSION "0.4" | 46 | #define DRIVER_VERSION "0.4" |
48 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -340,18 +339,13 @@ static int __init pcied_init(void) | |||
340 | { | 339 | { |
341 | int retval = 0; | 340 | int retval = 0; |
342 | 341 | ||
343 | pciehp_wq = alloc_workqueue("pciehp", 0, 0); | ||
344 | if (!pciehp_wq) | ||
345 | return -ENOMEM; | ||
346 | |||
347 | pciehp_firmware_init(); | 342 | pciehp_firmware_init(); |
348 | retval = pcie_port_service_register(&hpdriver_portdrv); | 343 | retval = pcie_port_service_register(&hpdriver_portdrv); |
349 | dbg("pcie_port_service_register = %d\n", retval); | 344 | dbg("pcie_port_service_register = %d\n", retval); |
350 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 345 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
351 | if (retval) { | 346 | if (retval) |
352 | destroy_workqueue(pciehp_wq); | ||
353 | dbg("Failure to register service\n"); | 347 | dbg("Failure to register service\n"); |
354 | } | 348 | |
355 | return retval; | 349 | return retval; |
356 | } | 350 | } |
357 | 351 | ||
@@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) | |||
359 | { | 353 | { |
360 | dbg("unload_pciehpd()\n"); | 354 | dbg("unload_pciehpd()\n"); |
361 | pcie_port_service_unregister(&hpdriver_portdrv); | 355 | pcie_port_service_unregister(&hpdriver_portdrv); |
362 | destroy_workqueue(pciehp_wq); | ||
363 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 356 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
364 | } | 357 | } |
365 | 358 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a657..38f018679175 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) | |||
49 | info->p_slot = p_slot; | 49 | info->p_slot = p_slot; |
50 | INIT_WORK(&info->work, interrupt_event_handler); | 50 | INIT_WORK(&info->work, interrupt_event_handler); |
51 | 51 | ||
52 | queue_work(pciehp_wq, &info->work); | 52 | queue_work(p_slot->wq, &info->work); |
53 | 53 | ||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
344 | kfree(info); | 344 | kfree(info); |
345 | goto out; | 345 | goto out; |
346 | } | 346 | } |
347 | queue_work(pciehp_wq, &info->work); | 347 | queue_work(p_slot->wq, &info->work); |
348 | out: | 348 | out: |
349 | mutex_unlock(&p_slot->lock); | 349 | mutex_unlock(&p_slot->lock); |
350 | } | 350 | } |
@@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) | |||
377 | if (ATTN_LED(ctrl)) | 377 | if (ATTN_LED(ctrl)) |
378 | pciehp_set_attention_status(p_slot, 0); | 378 | pciehp_set_attention_status(p_slot, 0); |
379 | 379 | ||
380 | queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); | 380 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); |
381 | break; | 381 | break; |
382 | case BLINKINGOFF_STATE: | 382 | case BLINKINGOFF_STATE: |
383 | case BLINKINGON_STATE: | 383 | case BLINKINGON_STATE: |
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) | |||
439 | else | 439 | else |
440 | p_slot->state = POWERON_STATE; | 440 | p_slot->state = POWERON_STATE; |
441 | 441 | ||
442 | queue_work(pciehp_wq, &info->work); | 442 | queue_work(p_slot->wq, &info->work); |
443 | } | 443 | } |
444 | 444 | ||
445 | static void interrupt_event_handler(struct work_struct *work) | 445 | static void interrupt_event_handler(struct work_struct *work) |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 13b2eaf7ba43..5127f3f41821 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) | |||
773 | static int pcie_init_slot(struct controller *ctrl) | 773 | static int pcie_init_slot(struct controller *ctrl) |
774 | { | 774 | { |
775 | struct slot *slot; | 775 | struct slot *slot; |
776 | char name[32]; | ||
776 | 777 | ||
777 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 778 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
778 | if (!slot) | 779 | if (!slot) |
779 | return -ENOMEM; | 780 | return -ENOMEM; |
780 | 781 | ||
782 | snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); | ||
783 | slot->wq = alloc_workqueue(name, 0, 0); | ||
784 | if (!slot->wq) | ||
785 | goto abort; | ||
786 | |||
781 | slot->ctrl = ctrl; | 787 | slot->ctrl = ctrl; |
782 | mutex_init(&slot->lock); | 788 | mutex_init(&slot->lock); |
783 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | 789 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); |
784 | ctrl->slot = slot; | 790 | ctrl->slot = slot; |
785 | return 0; | 791 | return 0; |
792 | abort: | ||
793 | kfree(slot); | ||
794 | return -ENOMEM; | ||
786 | } | 795 | } |
787 | 796 | ||
788 | static void pcie_cleanup_slot(struct controller *ctrl) | 797 | static void pcie_cleanup_slot(struct controller *ctrl) |
789 | { | 798 | { |
790 | struct slot *slot = ctrl->slot; | 799 | struct slot *slot = ctrl->slot; |
791 | cancel_delayed_work(&slot->work); | 800 | cancel_delayed_work(&slot->work); |
792 | flush_workqueue(pciehp_wq); | 801 | destroy_workqueue(slot->wq); |
793 | kfree(slot); | 802 | kfree(slot); |
794 | } | 803 | } |
795 | 804 | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658b..b849f995075a 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -46,8 +46,6 @@ | |||
46 | extern bool shpchp_poll_mode; | 46 | extern bool shpchp_poll_mode; |
47 | extern int shpchp_poll_time; | 47 | extern int shpchp_poll_time; |
48 | extern bool shpchp_debug; | 48 | extern bool shpchp_debug; |
49 | extern struct workqueue_struct *shpchp_wq; | ||
50 | extern struct workqueue_struct *shpchp_ordered_wq; | ||
51 | 49 | ||
52 | #define dbg(format, arg...) \ | 50 | #define dbg(format, arg...) \ |
53 | do { \ | 51 | do { \ |
@@ -91,6 +89,7 @@ struct slot { | |||
91 | struct list_head slot_list; | 89 | struct list_head slot_list; |
92 | struct delayed_work work; /* work for button event */ | 90 | struct delayed_work work; /* work for button event */ |
93 | struct mutex lock; | 91 | struct mutex lock; |
92 | struct workqueue_struct *wq; | ||
94 | u8 hp_slot; | 93 | u8 hp_slot; |
95 | }; | 94 | }; |
96 | 95 | ||
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index b6de307248e4..3100c52c837c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -39,8 +39,6 @@ | |||
39 | bool shpchp_debug; | 39 | bool shpchp_debug; |
40 | bool shpchp_poll_mode; | 40 | bool shpchp_poll_mode; |
41 | int shpchp_poll_time; | 41 | int shpchp_poll_time; |
42 | struct workqueue_struct *shpchp_wq; | ||
43 | struct workqueue_struct *shpchp_ordered_wq; | ||
44 | 42 | ||
45 | #define DRIVER_VERSION "0.4" | 43 | #define DRIVER_VERSION "0.4" |
46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 44 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl) | |||
129 | slot->device = ctrl->slot_device_offset + i; | 127 | slot->device = ctrl->slot_device_offset + i; |
130 | slot->hpc_ops = ctrl->hpc_ops; | 128 | slot->hpc_ops = ctrl->hpc_ops; |
131 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); | 129 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); |
130 | |||
131 | snprintf(name, sizeof(name), "shpchp-%d", slot->number); | ||
132 | slot->wq = alloc_workqueue(name, 0, 0); | ||
133 | if (!slot->wq) { | ||
134 | retval = -ENOMEM; | ||
135 | goto error_info; | ||
136 | } | ||
137 | |||
132 | mutex_init(&slot->lock); | 138 | mutex_init(&slot->lock); |
133 | INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); | 139 | INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); |
134 | 140 | ||
@@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl) | |||
148 | if (retval) { | 154 | if (retval) { |
149 | ctrl_err(ctrl, "pci_hp_register failed with error %d\n", | 155 | ctrl_err(ctrl, "pci_hp_register failed with error %d\n", |
150 | retval); | 156 | retval); |
151 | goto error_info; | 157 | goto error_slotwq; |
152 | } | 158 | } |
153 | 159 | ||
154 | get_power_status(hotplug_slot, &info->power_status); | 160 | get_power_status(hotplug_slot, &info->power_status); |
@@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl) | |||
160 | } | 166 | } |
161 | 167 | ||
162 | return 0; | 168 | return 0; |
169 | error_slotwq: | ||
170 | destroy_workqueue(slot->wq); | ||
163 | error_info: | 171 | error_info: |
164 | kfree(info); | 172 | kfree(info); |
165 | error_hpslot: | 173 | error_hpslot: |
@@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl) | |||
180 | slot = list_entry(tmp, struct slot, slot_list); | 188 | slot = list_entry(tmp, struct slot, slot_list); |
181 | list_del(&slot->slot_list); | 189 | list_del(&slot->slot_list); |
182 | cancel_delayed_work(&slot->work); | 190 | cancel_delayed_work(&slot->work); |
183 | flush_workqueue(shpchp_wq); | 191 | destroy_workqueue(slot->wq); |
184 | flush_workqueue(shpchp_ordered_wq); | ||
185 | pci_hp_deregister(slot->hotplug_slot); | 192 | pci_hp_deregister(slot->hotplug_slot); |
186 | } | 193 | } |
187 | } | 194 | } |
@@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = { | |||
364 | 371 | ||
365 | static int __init shpcd_init(void) | 372 | static int __init shpcd_init(void) |
366 | { | 373 | { |
367 | int retval = 0; | 374 | int retval; |
368 | |||
369 | shpchp_wq = alloc_ordered_workqueue("shpchp", 0); | ||
370 | if (!shpchp_wq) | ||
371 | return -ENOMEM; | ||
372 | |||
373 | shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); | ||
374 | if (!shpchp_ordered_wq) { | ||
375 | destroy_workqueue(shpchp_wq); | ||
376 | return -ENOMEM; | ||
377 | } | ||
378 | 375 | ||
379 | retval = pci_register_driver(&shpc_driver); | 376 | retval = pci_register_driver(&shpc_driver); |
380 | dbg("%s: pci_register_driver = %d\n", __func__, retval); | 377 | dbg("%s: pci_register_driver = %d\n", __func__, retval); |
381 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 378 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
382 | if (retval) { | 379 | |
383 | destroy_workqueue(shpchp_ordered_wq); | ||
384 | destroy_workqueue(shpchp_wq); | ||
385 | } | ||
386 | return retval; | 380 | return retval; |
387 | } | 381 | } |
388 | 382 | ||
@@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void) | |||
390 | { | 384 | { |
391 | dbg("unload_shpchpd()\n"); | 385 | dbg("unload_shpchpd()\n"); |
392 | pci_unregister_driver(&shpc_driver); | 386 | pci_unregister_driver(&shpc_driver); |
393 | destroy_workqueue(shpchp_ordered_wq); | ||
394 | destroy_workqueue(shpchp_wq); | ||
395 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 387 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
396 | } | 388 | } |
397 | 389 | ||
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index f9b5a52e4115..58499277903a 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) | |||
51 | info->p_slot = p_slot; | 51 | info->p_slot = p_slot; |
52 | INIT_WORK(&info->work, interrupt_event_handler); | 52 | INIT_WORK(&info->work, interrupt_event_handler); |
53 | 53 | ||
54 | queue_work(shpchp_wq, &info->work); | 54 | queue_work(p_slot->wq, &info->work); |
55 | 55 | ||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
@@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) | |||
453 | kfree(info); | 453 | kfree(info); |
454 | goto out; | 454 | goto out; |
455 | } | 455 | } |
456 | queue_work(shpchp_ordered_wq, &info->work); | 456 | queue_work(p_slot->wq, &info->work); |
457 | out: | 457 | out: |
458 | mutex_unlock(&p_slot->lock); | 458 | mutex_unlock(&p_slot->lock); |
459 | } | 459 | } |
@@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot) | |||
501 | p_slot->hpc_ops->green_led_blink(p_slot); | 501 | p_slot->hpc_ops->green_led_blink(p_slot); |
502 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 502 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
503 | 503 | ||
504 | queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); | 504 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); |
505 | break; | 505 | break; |
506 | case BLINKINGOFF_STATE: | 506 | case BLINKINGOFF_STATE: |
507 | case BLINKINGON_STATE: | 507 | case BLINKINGON_STATE: |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index bafd2bbcaf65..c18e5bf444fa 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -739,7 +739,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf); | |||
739 | /** | 739 | /** |
740 | * pci_sriov_set_totalvfs -- reduce the TotalVFs available | 740 | * pci_sriov_set_totalvfs -- reduce the TotalVFs available |
741 | * @dev: the PCI PF device | 741 | * @dev: the PCI PF device |
742 | * numvfs: number that should be used for TotalVFs supported | 742 | * @numvfs: number that should be used for TotalVFs supported |
743 | * | 743 | * |
744 | * Should be called from PF driver's probe routine with | 744 | * Should be called from PF driver's probe routine with |
745 | * device's mutex held. | 745 | * device's mutex held. |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 6c8bc5809787..fde4a32a0295 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -82,4 +82,4 @@ endchoice | |||
82 | 82 | ||
83 | config PCIE_PME | 83 | config PCIE_PME |
84 | def_bool y | 84 | def_bool y |
85 | depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI | 85 | depends on PCIEPORTBUS && PM_RUNTIME && ACPI |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 421bbc5fee32..564d97f94b6c 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work) | |||
630 | continue; | 630 | continue; |
631 | } | 631 | } |
632 | do_recovery(pdev, entry.severity); | 632 | do_recovery(pdev, entry.severity); |
633 | pci_dev_put(pdev); | ||
633 | } | 634 | } |
634 | } | 635 | } |
635 | #endif | 636 | #endif |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b52630b8eada..8474b6a4fc9b 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus) | |||
771 | { | 771 | { |
772 | struct pci_dev *child; | 772 | struct pci_dev *child; |
773 | 773 | ||
774 | if (aspm_force) | ||
775 | return; | ||
776 | |||
774 | /* | 777 | /* |
775 | * Clear any ASPM setup that the firmware has carried out on this bus | 778 | * Clear any ASPM setup that the firmware has carried out on this bus |
776 | */ | 779 | */ |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 06f4eb7ab87e..afed7018a2b5 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -125,8 +125,11 @@ static const struct key_entry acer_wmi_keymap[] = { | |||
125 | {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, | 125 | {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, |
126 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ | 126 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ |
127 | {KE_IGNORE, 0x81, {KEY_SLEEP} }, | 127 | {KE_IGNORE, 0x81, {KEY_SLEEP} }, |
128 | {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ | 128 | {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */ |
129 | {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, | ||
130 | {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, | ||
129 | {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, | 131 | {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, |
132 | {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} }, | ||
130 | {KE_END, 0} | 133 | {KE_END, 0} |
131 | }; | 134 | }; |
132 | 135 | ||
@@ -147,6 +150,7 @@ struct event_return_value { | |||
147 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ | 150 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ |
148 | #define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */ | 151 | #define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */ |
149 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ | 152 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ |
153 | #define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */ | ||
150 | 154 | ||
151 | struct lm_input_params { | 155 | struct lm_input_params { |
152 | u8 function_num; /* Function Number */ | 156 | u8 function_num; /* Function Number */ |
@@ -875,7 +879,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) | |||
875 | struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; | 879 | struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; |
876 | struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; | 880 | struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; |
877 | union acpi_object *obj; | 881 | union acpi_object *obj; |
878 | u32 tmp; | 882 | u32 tmp = 0; |
879 | acpi_status status; | 883 | acpi_status status; |
880 | 884 | ||
881 | status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); | 885 | status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); |
@@ -884,14 +888,14 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) | |||
884 | return status; | 888 | return status; |
885 | 889 | ||
886 | obj = (union acpi_object *) result.pointer; | 890 | obj = (union acpi_object *) result.pointer; |
887 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 891 | if (obj) { |
888 | (obj->buffer.length == sizeof(u32) || | 892 | if (obj->type == ACPI_TYPE_BUFFER && |
889 | obj->buffer.length == sizeof(u64))) { | 893 | (obj->buffer.length == sizeof(u32) || |
890 | tmp = *((u32 *) obj->buffer.pointer); | 894 | obj->buffer.length == sizeof(u64))) { |
891 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 895 | tmp = *((u32 *) obj->buffer.pointer); |
892 | tmp = (u32) obj->integer.value; | 896 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
893 | } else { | 897 | tmp = (u32) obj->integer.value; |
894 | tmp = 0; | 898 | } |
895 | } | 899 | } |
896 | 900 | ||
897 | if (out) | 901 | if (out) |
@@ -1193,12 +1197,14 @@ static acpi_status WMID_set_capabilities(void) | |||
1193 | return status; | 1197 | return status; |
1194 | 1198 | ||
1195 | obj = (union acpi_object *) out.pointer; | 1199 | obj = (union acpi_object *) out.pointer; |
1196 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 1200 | if (obj) { |
1197 | (obj->buffer.length == sizeof(u32) || | 1201 | if (obj->type == ACPI_TYPE_BUFFER && |
1198 | obj->buffer.length == sizeof(u64))) { | 1202 | (obj->buffer.length == sizeof(u32) || |
1199 | devices = *((u32 *) obj->buffer.pointer); | 1203 | obj->buffer.length == sizeof(u64))) { |
1200 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 1204 | devices = *((u32 *) obj->buffer.pointer); |
1201 | devices = (u32) obj->integer.value; | 1205 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
1206 | devices = (u32) obj->integer.value; | ||
1207 | } | ||
1202 | } else { | 1208 | } else { |
1203 | kfree(out.pointer); | 1209 | kfree(out.pointer); |
1204 | return AE_ERROR; | 1210 | return AE_ERROR; |
@@ -1676,6 +1682,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1676 | acpi_status status; | 1682 | acpi_status status; |
1677 | u16 device_state; | 1683 | u16 device_state; |
1678 | const struct key_entry *key; | 1684 | const struct key_entry *key; |
1685 | u32 scancode; | ||
1679 | 1686 | ||
1680 | status = wmi_get_event_data(value, &response); | 1687 | status = wmi_get_event_data(value, &response); |
1681 | if (status != AE_OK) { | 1688 | if (status != AE_OK) { |
@@ -1712,6 +1719,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1712 | pr_warn("Unknown key number - 0x%x\n", | 1719 | pr_warn("Unknown key number - 0x%x\n", |
1713 | return_value.key_num); | 1720 | return_value.key_num); |
1714 | } else { | 1721 | } else { |
1722 | scancode = return_value.key_num; | ||
1715 | switch (key->keycode) { | 1723 | switch (key->keycode) { |
1716 | case KEY_WLAN: | 1724 | case KEY_WLAN: |
1717 | case KEY_BLUETOOTH: | 1725 | case KEY_BLUETOOTH: |
@@ -1725,9 +1733,11 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1725 | rfkill_set_sw_state(bluetooth_rfkill, | 1733 | rfkill_set_sw_state(bluetooth_rfkill, |
1726 | !(device_state & ACER_WMID3_GDS_BLUETOOTH)); | 1734 | !(device_state & ACER_WMID3_GDS_BLUETOOTH)); |
1727 | break; | 1735 | break; |
1736 | case KEY_TOUCHPAD_TOGGLE: | ||
1737 | scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ? | ||
1738 | KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF; | ||
1728 | } | 1739 | } |
1729 | sparse_keymap_report_entry(acer_wmi_input_dev, key, | 1740 | sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true); |
1730 | 1, true); | ||
1731 | } | 1741 | } |
1732 | break; | 1742 | break; |
1733 | case WMID_ACCEL_EVENT: | 1743 | case WMID_ACCEL_EVENT: |
@@ -1946,12 +1956,14 @@ static u32 get_wmid_devices(void) | |||
1946 | return 0; | 1956 | return 0; |
1947 | 1957 | ||
1948 | obj = (union acpi_object *) out.pointer; | 1958 | obj = (union acpi_object *) out.pointer; |
1949 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 1959 | if (obj) { |
1950 | (obj->buffer.length == sizeof(u32) || | 1960 | if (obj->type == ACPI_TYPE_BUFFER && |
1951 | obj->buffer.length == sizeof(u64))) { | 1961 | (obj->buffer.length == sizeof(u32) || |
1952 | devices = *((u32 *) obj->buffer.pointer); | 1962 | obj->buffer.length == sizeof(u64))) { |
1953 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 1963 | devices = *((u32 *) obj->buffer.pointer); |
1954 | devices = (u32) obj->integer.value; | 1964 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
1965 | devices = (u32) obj->integer.value; | ||
1966 | } | ||
1955 | } | 1967 | } |
1956 | 1968 | ||
1957 | kfree(out.pointer); | 1969 | kfree(out.pointer); |
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ec1d3bc2dbe2..fcde4e528819 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -860,8 +860,10 @@ static ssize_t show_infos(struct device *dev, | |||
860 | /* | 860 | /* |
861 | * The HWRS method return informations about the hardware. | 861 | * The HWRS method return informations about the hardware. |
862 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 862 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. |
863 | * 0x40 for WWAN, 0x10 for WIMAX. | ||
863 | * The significance of others is yet to be found. | 864 | * The significance of others is yet to be found. |
864 | * If we don't find the method, we assume the device are present. | 865 | * We don't currently use this for device detection, and it |
866 | * takes several seconds to run on some systems. | ||
865 | */ | 867 | */ |
866 | rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); | 868 | rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); |
867 | if (!ACPI_FAILURE(rv)) | 869 | if (!ACPI_FAILURE(rv)) |
@@ -1682,7 +1684,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1682 | { | 1684 | { |
1683 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 1685 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
1684 | union acpi_object *model = NULL; | 1686 | union acpi_object *model = NULL; |
1685 | unsigned long long bsts_result, hwrs_result; | 1687 | unsigned long long bsts_result; |
1686 | char *string = NULL; | 1688 | char *string = NULL; |
1687 | acpi_status status; | 1689 | acpi_status status; |
1688 | 1690 | ||
@@ -1741,20 +1743,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1741 | return -ENOMEM; | 1743 | return -ENOMEM; |
1742 | } | 1744 | } |
1743 | 1745 | ||
1744 | if (*string) | 1746 | if (string) |
1745 | pr_notice(" %s model detected\n", string); | 1747 | pr_notice(" %s model detected\n", string); |
1746 | 1748 | ||
1747 | /* | ||
1748 | * The HWRS method return informations about the hardware. | ||
1749 | * 0x80 bit is for WLAN, 0x100 for Bluetooth, | ||
1750 | * 0x40 for WWAN, 0x10 for WIMAX. | ||
1751 | * The significance of others is yet to be found. | ||
1752 | */ | ||
1753 | status = | ||
1754 | acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); | ||
1755 | if (!ACPI_FAILURE(status)) | ||
1756 | pr_notice(" HWRS returned %x", (int)hwrs_result); | ||
1757 | |||
1758 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) | 1749 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) |
1759 | asus->have_rsts = true; | 1750 | asus->have_rsts = true; |
1760 | 1751 | ||
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index dd90d15f5210..71623a2ff3e8 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c | |||
@@ -1523,6 +1523,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { | |||
1523 | }, | 1523 | }, |
1524 | .driver_data = &samsung_broken_acpi_video, | 1524 | .driver_data = &samsung_broken_acpi_video, |
1525 | }, | 1525 | }, |
1526 | { | ||
1527 | .callback = samsung_dmi_matched, | ||
1528 | .ident = "N250P", | ||
1529 | .matches = { | ||
1530 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
1531 | DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), | ||
1532 | DMI_MATCH(DMI_BOARD_NAME, "N250P"), | ||
1533 | }, | ||
1534 | .driver_data = &samsung_broken_acpi_video, | ||
1535 | }, | ||
1526 | { }, | 1536 | { }, |
1527 | }; | 1537 | }; |
1528 | MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); | 1538 | MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index daaddec68def..b8ad71f7863f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle handle, char *name, int *value, | |||
786 | static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, | 786 | static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, |
787 | void *buffer, size_t buflen) | 787 | void *buffer, size_t buflen) |
788 | { | 788 | { |
789 | int ret = 0; | ||
789 | size_t len = len; | 790 | size_t len = len; |
790 | union acpi_object *object = __call_snc_method(handle, name, value); | 791 | union acpi_object *object = __call_snc_method(handle, name, value); |
791 | 792 | ||
792 | if (!object) | 793 | if (!object) |
793 | return -EINVAL; | 794 | return -EINVAL; |
794 | 795 | ||
795 | if (object->type == ACPI_TYPE_BUFFER) | 796 | if (object->type == ACPI_TYPE_BUFFER) { |
796 | len = MIN(buflen, object->buffer.length); | 797 | len = MIN(buflen, object->buffer.length); |
798 | memcpy(buffer, object->buffer.pointer, len); | ||
797 | 799 | ||
798 | else if (object->type == ACPI_TYPE_INTEGER) | 800 | } else if (object->type == ACPI_TYPE_INTEGER) { |
799 | len = MIN(buflen, sizeof(object->integer.value)); | 801 | len = MIN(buflen, sizeof(object->integer.value)); |
802 | memcpy(buffer, &object->integer.value, len); | ||
800 | 803 | ||
801 | else { | 804 | } else { |
802 | pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", | 805 | pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", |
803 | ACPI_TYPE_BUFFER, object->type); | 806 | ACPI_TYPE_BUFFER, object->type); |
804 | kfree(object); | 807 | ret = -EINVAL; |
805 | return -EINVAL; | ||
806 | } | 808 | } |
807 | 809 | ||
808 | memcpy(buffer, object->buffer.pointer, len); | ||
809 | kfree(object); | 810 | kfree(object); |
810 | return 0; | 811 | return ret; |
811 | } | 812 | } |
812 | 813 | ||
813 | struct sony_nc_handles { | 814 | struct sony_nc_handles { |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 0f65b246cc0c..278584302f2d 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -1885,9 +1885,15 @@ int regulator_can_change_voltage(struct regulator *regulator) | |||
1885 | struct regulator_dev *rdev = regulator->rdev; | 1885 | struct regulator_dev *rdev = regulator->rdev; |
1886 | 1886 | ||
1887 | if (rdev->constraints && | 1887 | if (rdev->constraints && |
1888 | rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && | 1888 | (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { |
1889 | (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1) | 1889 | if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) |
1890 | return 1; | 1890 | return 1; |
1891 | |||
1892 | if (rdev->desc->continuous_voltage_range && | ||
1893 | rdev->constraints->min_uV && rdev->constraints->max_uV && | ||
1894 | rdev->constraints->min_uV != rdev->constraints->max_uV) | ||
1895 | return 1; | ||
1896 | } | ||
1891 | 1897 | ||
1892 | return 0; | 1898 | return 0; |
1893 | } | 1899 | } |
@@ -3315,7 +3321,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) | |||
3315 | * @config: runtime configuration for regulator | 3321 | * @config: runtime configuration for regulator |
3316 | * | 3322 | * |
3317 | * Called by regulator drivers to register a regulator. | 3323 | * Called by regulator drivers to register a regulator. |
3318 | * Returns 0 on success. | 3324 | * Returns a valid pointer to struct regulator_dev on success |
3325 | * or an ERR_PTR() on error. | ||
3319 | */ | 3326 | */ |
3320 | struct regulator_dev * | 3327 | struct regulator_dev * |
3321 | regulator_register(const struct regulator_desc *regulator_desc, | 3328 | regulator_register(const struct regulator_desc *regulator_desc, |
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index df0eafb0dc7e..02be7fcae32f 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c | |||
@@ -71,26 +71,26 @@ struct voltage_map_desc { | |||
71 | int step; | 71 | int step; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | /* Voltage maps in mV */ | 74 | /* Voltage maps in uV */ |
75 | static const struct voltage_map_desc ldo_voltage_map_desc = { | 75 | static const struct voltage_map_desc ldo_voltage_map_desc = { |
76 | .min = 800, .max = 3950, .step = 50, | 76 | .min = 800000, .max = 3950000, .step = 50000, |
77 | }; /* LDO1 ~ 18, 21 all */ | 77 | }; /* LDO1 ~ 18, 21 all */ |
78 | 78 | ||
79 | static const struct voltage_map_desc buck1245_voltage_map_desc = { | 79 | static const struct voltage_map_desc buck1245_voltage_map_desc = { |
80 | .min = 650, .max = 2225, .step = 25, | 80 | .min = 650000, .max = 2225000, .step = 25000, |
81 | }; /* Buck1, 2, 4, 5 */ | 81 | }; /* Buck1, 2, 4, 5 */ |
82 | 82 | ||
83 | static const struct voltage_map_desc buck37_voltage_map_desc = { | 83 | static const struct voltage_map_desc buck37_voltage_map_desc = { |
84 | .min = 750, .max = 3900, .step = 50, | 84 | .min = 750000, .max = 3900000, .step = 50000, |
85 | }; /* Buck3, 7 */ | 85 | }; /* Buck3, 7 */ |
86 | 86 | ||
87 | /* current map in mA */ | 87 | /* current map in uA */ |
88 | static const struct voltage_map_desc charger_current_map_desc = { | 88 | static const struct voltage_map_desc charger_current_map_desc = { |
89 | .min = 200, .max = 950, .step = 50, | 89 | .min = 200000, .max = 950000, .step = 50000, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static const struct voltage_map_desc topoff_current_map_desc = { | 92 | static const struct voltage_map_desc topoff_current_map_desc = { |
93 | .min = 50, .max = 200, .step = 10, | 93 | .min = 50000, .max = 200000, .step = 10000, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | static const struct voltage_map_desc *reg_voltage_map[] = { | 96 | static const struct voltage_map_desc *reg_voltage_map[] = { |
@@ -194,7 +194,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, | |||
194 | if (val > desc->max) | 194 | if (val > desc->max) |
195 | return -EINVAL; | 195 | return -EINVAL; |
196 | 196 | ||
197 | return val * 1000; | 197 | return val; |
198 | } | 198 | } |
199 | 199 | ||
200 | static int max8997_get_enable_register(struct regulator_dev *rdev, | 200 | static int max8997_get_enable_register(struct regulator_dev *rdev, |
@@ -485,7 +485,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | |||
485 | { | 485 | { |
486 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | 486 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); |
487 | struct i2c_client *i2c = max8997->iodev->i2c; | 487 | struct i2c_client *i2c = max8997->iodev->i2c; |
488 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
489 | const struct voltage_map_desc *desc; | 488 | const struct voltage_map_desc *desc; |
490 | int rid = rdev_get_id(rdev); | 489 | int rid = rdev_get_id(rdev); |
491 | int i, reg, shift, mask, ret; | 490 | int i, reg, shift, mask, ret; |
@@ -509,7 +508,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | |||
509 | 508 | ||
510 | desc = reg_voltage_map[rid]; | 509 | desc = reg_voltage_map[rid]; |
511 | 510 | ||
512 | i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | 511 | i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); |
513 | if (i < 0) | 512 | if (i < 0) |
514 | return i; | 513 | return i; |
515 | 514 | ||
@@ -557,7 +556,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, | |||
557 | case MAX8997_BUCK4: | 556 | case MAX8997_BUCK4: |
558 | case MAX8997_BUCK5: | 557 | case MAX8997_BUCK5: |
559 | return DIV_ROUND_UP(desc->step * (new_selector - old_selector), | 558 | return DIV_ROUND_UP(desc->step * (new_selector - old_selector), |
560 | max8997->ramp_delay); | 559 | max8997->ramp_delay * 1000); |
561 | } | 560 | } |
562 | 561 | ||
563 | return 0; | 562 | return 0; |
@@ -656,7 +655,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, | |||
656 | const struct voltage_map_desc *desc; | 655 | const struct voltage_map_desc *desc; |
657 | int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; | 656 | int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; |
658 | bool gpio_dvs_mode = false; | 657 | bool gpio_dvs_mode = false; |
659 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
660 | 658 | ||
661 | if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) | 659 | if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) |
662 | return -EINVAL; | 660 | return -EINVAL; |
@@ -681,7 +679,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, | |||
681 | selector); | 679 | selector); |
682 | 680 | ||
683 | desc = reg_voltage_map[rid]; | 681 | desc = reg_voltage_map[rid]; |
684 | new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | 682 | new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); |
685 | if (new_val < 0) | 683 | if (new_val < 0) |
686 | return new_val; | 684 | return new_val; |
687 | 685 | ||
@@ -1123,8 +1121,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1123 | max8997->buck1_vol[i] = ret = | 1121 | max8997->buck1_vol[i] = ret = |
1124 | max8997_get_voltage_proper_val( | 1122 | max8997_get_voltage_proper_val( |
1125 | &buck1245_voltage_map_desc, | 1123 | &buck1245_voltage_map_desc, |
1126 | pdata->buck1_voltage[i] / 1000, | 1124 | pdata->buck1_voltage[i], |
1127 | pdata->buck1_voltage[i] / 1000 + | 1125 | pdata->buck1_voltage[i] + |
1128 | buck1245_voltage_map_desc.step); | 1126 | buck1245_voltage_map_desc.step); |
1129 | if (ret < 0) | 1127 | if (ret < 0) |
1130 | goto err_out; | 1128 | goto err_out; |
@@ -1132,8 +1130,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1132 | max8997->buck2_vol[i] = ret = | 1130 | max8997->buck2_vol[i] = ret = |
1133 | max8997_get_voltage_proper_val( | 1131 | max8997_get_voltage_proper_val( |
1134 | &buck1245_voltage_map_desc, | 1132 | &buck1245_voltage_map_desc, |
1135 | pdata->buck2_voltage[i] / 1000, | 1133 | pdata->buck2_voltage[i], |
1136 | pdata->buck2_voltage[i] / 1000 + | 1134 | pdata->buck2_voltage[i] + |
1137 | buck1245_voltage_map_desc.step); | 1135 | buck1245_voltage_map_desc.step); |
1138 | if (ret < 0) | 1136 | if (ret < 0) |
1139 | goto err_out; | 1137 | goto err_out; |
@@ -1141,8 +1139,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1141 | max8997->buck5_vol[i] = ret = | 1139 | max8997->buck5_vol[i] = ret = |
1142 | max8997_get_voltage_proper_val( | 1140 | max8997_get_voltage_proper_val( |
1143 | &buck1245_voltage_map_desc, | 1141 | &buck1245_voltage_map_desc, |
1144 | pdata->buck5_voltage[i] / 1000, | 1142 | pdata->buck5_voltage[i], |
1145 | pdata->buck5_voltage[i] / 1000 + | 1143 | pdata->buck5_voltage[i] + |
1146 | buck1245_voltage_map_desc.step); | 1144 | buck1245_voltage_map_desc.step); |
1147 | if (ret < 0) | 1145 | if (ret < 0) |
1148 | goto err_out; | 1146 | goto err_out; |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index b821d08eb64a..1f0df4046b86 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -51,39 +51,39 @@ struct voltage_map_desc { | |||
51 | int step; | 51 | int step; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | /* Voltage maps */ | 54 | /* Voltage maps in uV*/ |
55 | static const struct voltage_map_desc ldo23_voltage_map_desc = { | 55 | static const struct voltage_map_desc ldo23_voltage_map_desc = { |
56 | .min = 800, .step = 50, .max = 1300, | 56 | .min = 800000, .step = 50000, .max = 1300000, |
57 | }; | 57 | }; |
58 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { | 58 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { |
59 | .min = 1600, .step = 100, .max = 3600, | 59 | .min = 1600000, .step = 100000, .max = 3600000, |
60 | }; | 60 | }; |
61 | static const struct voltage_map_desc ldo8_voltage_map_desc = { | 61 | static const struct voltage_map_desc ldo8_voltage_map_desc = { |
62 | .min = 3000, .step = 100, .max = 3600, | 62 | .min = 3000000, .step = 100000, .max = 3600000, |
63 | }; | 63 | }; |
64 | static const struct voltage_map_desc ldo9_voltage_map_desc = { | 64 | static const struct voltage_map_desc ldo9_voltage_map_desc = { |
65 | .min = 2800, .step = 100, .max = 3100, | 65 | .min = 2800000, .step = 100000, .max = 3100000, |
66 | }; | 66 | }; |
67 | static const struct voltage_map_desc ldo10_voltage_map_desc = { | 67 | static const struct voltage_map_desc ldo10_voltage_map_desc = { |
68 | .min = 950, .step = 50, .max = 1300, | 68 | .min = 95000, .step = 50000, .max = 1300000, |
69 | }; | 69 | }; |
70 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { | 70 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { |
71 | .min = 800, .step = 100, .max = 3300, | 71 | .min = 800000, .step = 100000, .max = 3300000, |
72 | }; | 72 | }; |
73 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { | 73 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { |
74 | .min = 1200, .step = 100, .max = 3300, | 74 | .min = 1200000, .step = 100000, .max = 3300000, |
75 | }; | 75 | }; |
76 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { | 76 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { |
77 | .min = 1600, .step = 100, .max = 3600, | 77 | .min = 1600000, .step = 100000, .max = 3600000, |
78 | }; | 78 | }; |
79 | static const struct voltage_map_desc buck12_voltage_map_desc = { | 79 | static const struct voltage_map_desc buck12_voltage_map_desc = { |
80 | .min = 750, .step = 25, .max = 1525, | 80 | .min = 750000, .step = 25000, .max = 1525000, |
81 | }; | 81 | }; |
82 | static const struct voltage_map_desc buck3_voltage_map_desc = { | 82 | static const struct voltage_map_desc buck3_voltage_map_desc = { |
83 | .min = 1600, .step = 100, .max = 3600, | 83 | .min = 1600000, .step = 100000, .max = 3600000, |
84 | }; | 84 | }; |
85 | static const struct voltage_map_desc buck4_voltage_map_desc = { | 85 | static const struct voltage_map_desc buck4_voltage_map_desc = { |
86 | .min = 800, .step = 100, .max = 2300, | 86 | .min = 800000, .step = 100000, .max = 2300000, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static const struct voltage_map_desc *ldo_voltage_map[] = { | 89 | static const struct voltage_map_desc *ldo_voltage_map[] = { |
@@ -445,9 +445,9 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, | |||
445 | if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) | 445 | if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) |
446 | return 0; | 446 | return 0; |
447 | 447 | ||
448 | difference = (new_selector - old_selector) * desc->step; | 448 | difference = (new_selector - old_selector) * desc->step / 1000; |
449 | if (difference > 0) | 449 | if (difference > 0) |
450 | return difference / ((val & 0x0f) + 1); | 450 | return DIV_ROUND_UP(difference, (val & 0x0f) + 1); |
451 | 451 | ||
452 | return 0; | 452 | return 0; |
453 | } | 453 | } |
@@ -702,7 +702,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
702 | i = 0; | 702 | i = 0; |
703 | while (buck12_voltage_map_desc.min + | 703 | while (buck12_voltage_map_desc.min + |
704 | buck12_voltage_map_desc.step*i | 704 | buck12_voltage_map_desc.step*i |
705 | < (pdata->buck1_voltage1 / 1000)) | 705 | < pdata->buck1_voltage1) |
706 | i++; | 706 | i++; |
707 | max8998->buck1_vol[0] = i; | 707 | max8998->buck1_vol[0] = i; |
708 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); | 708 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); |
@@ -713,7 +713,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
713 | i = 0; | 713 | i = 0; |
714 | while (buck12_voltage_map_desc.min + | 714 | while (buck12_voltage_map_desc.min + |
715 | buck12_voltage_map_desc.step*i | 715 | buck12_voltage_map_desc.step*i |
716 | < (pdata->buck1_voltage2 / 1000)) | 716 | < pdata->buck1_voltage2) |
717 | i++; | 717 | i++; |
718 | 718 | ||
719 | max8998->buck1_vol[1] = i; | 719 | max8998->buck1_vol[1] = i; |
@@ -725,7 +725,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
725 | i = 0; | 725 | i = 0; |
726 | while (buck12_voltage_map_desc.min + | 726 | while (buck12_voltage_map_desc.min + |
727 | buck12_voltage_map_desc.step*i | 727 | buck12_voltage_map_desc.step*i |
728 | < (pdata->buck1_voltage3 / 1000)) | 728 | < pdata->buck1_voltage3) |
729 | i++; | 729 | i++; |
730 | 730 | ||
731 | max8998->buck1_vol[2] = i; | 731 | max8998->buck1_vol[2] = i; |
@@ -737,7 +737,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
737 | i = 0; | 737 | i = 0; |
738 | while (buck12_voltage_map_desc.min + | 738 | while (buck12_voltage_map_desc.min + |
739 | buck12_voltage_map_desc.step*i | 739 | buck12_voltage_map_desc.step*i |
740 | < (pdata->buck1_voltage4 / 1000)) | 740 | < pdata->buck1_voltage4) |
741 | i++; | 741 | i++; |
742 | 742 | ||
743 | max8998->buck1_vol[3] = i; | 743 | max8998->buck1_vol[3] = i; |
@@ -763,7 +763,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
763 | i = 0; | 763 | i = 0; |
764 | while (buck12_voltage_map_desc.min + | 764 | while (buck12_voltage_map_desc.min + |
765 | buck12_voltage_map_desc.step*i | 765 | buck12_voltage_map_desc.step*i |
766 | < (pdata->buck2_voltage1 / 1000)) | 766 | < pdata->buck2_voltage1) |
767 | i++; | 767 | i++; |
768 | max8998->buck2_vol[0] = i; | 768 | max8998->buck2_vol[0] = i; |
769 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); | 769 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); |
@@ -774,7 +774,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
774 | i = 0; | 774 | i = 0; |
775 | while (buck12_voltage_map_desc.min + | 775 | while (buck12_voltage_map_desc.min + |
776 | buck12_voltage_map_desc.step*i | 776 | buck12_voltage_map_desc.step*i |
777 | < (pdata->buck2_voltage2 / 1000)) | 777 | < pdata->buck2_voltage2) |
778 | i++; | 778 | i++; |
779 | max8998->buck2_vol[1] = i; | 779 | max8998->buck2_vol[1] = i; |
780 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); | 780 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); |
@@ -792,8 +792,8 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
792 | int count = (desc->max - desc->min) / desc->step + 1; | 792 | int count = (desc->max - desc->min) / desc->step + 1; |
793 | 793 | ||
794 | regulators[index].n_voltages = count; | 794 | regulators[index].n_voltages = count; |
795 | regulators[index].min_uV = desc->min * 1000; | 795 | regulators[index].min_uV = desc->min; |
796 | regulators[index].uV_step = desc->step * 1000; | 796 | regulators[index].uV_step = desc->step; |
797 | } | 797 | } |
798 | 798 | ||
799 | config.dev = max8998->dev; | 799 | config.dev = max8998->dev; |
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 9f991f2c525a..33b65c9ad5d5 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c | |||
@@ -214,7 +214,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) | |||
214 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | 214 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); |
215 | int ret, reg; | 215 | int ret, reg; |
216 | int mask = 0xc0, enable_ctrl; | 216 | int mask = 0xc0, enable_ctrl; |
217 | u8 val; | 217 | unsigned int val; |
218 | 218 | ||
219 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); | 219 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); |
220 | if (ret == -EINVAL) | 220 | if (ret == -EINVAL) |
@@ -306,7 +306,7 @@ static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) | |||
306 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | 306 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); |
307 | int reg, mask, ret; | 307 | int reg, mask, ret; |
308 | int reg_id = rdev_get_id(rdev); | 308 | int reg_id = rdev_get_id(rdev); |
309 | u8 val; | 309 | unsigned int val; |
310 | 310 | ||
311 | ret = s5m8767_get_voltage_register(rdev, ®); | 311 | ret = s5m8767_get_voltage_register(rdev, ®); |
312 | if (ret) | 312 | if (ret) |
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 96bafc5c3bf8..8f0dcfedb83c 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c | |||
@@ -227,7 +227,7 @@ static const struct rtc_class_ops da9055_rtc_ops = { | |||
227 | .alarm_irq_enable = da9055_rtc_alarm_irq_enable, | 227 | .alarm_irq_enable = da9055_rtc_alarm_irq_enable, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static int __init da9055_rtc_device_init(struct da9055 *da9055, | 230 | static int da9055_rtc_device_init(struct da9055 *da9055, |
231 | struct da9055_pdata *pdata) | 231 | struct da9055_pdata *pdata) |
232 | { | 232 | { |
233 | int ret; | 233 | int ret; |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 9bd5da36f99e..704488d0f819 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -248,7 +248,7 @@ static void dasd_ext_handler(struct ext_code ext_code, | |||
248 | default: | 248 | default: |
249 | return; | 249 | return; |
250 | } | 250 | } |
251 | kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++; | 251 | inc_irq_stat(IRQEXT_DSD); |
252 | if (!ip) { /* no intparm: unsolicited interrupt */ | 252 | if (!ip) { /* no intparm: unsolicited interrupt */ |
253 | DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " | 253 | DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " |
254 | "interrupt"); | 254 | "interrupt"); |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 806fe912d6e7..e37bc1620d14 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -4274,7 +4274,7 @@ static struct ccw_driver dasd_eckd_driver = { | |||
4274 | .thaw = dasd_generic_restore_device, | 4274 | .thaw = dasd_generic_restore_device, |
4275 | .restore = dasd_generic_restore_device, | 4275 | .restore = dasd_generic_restore_device, |
4276 | .uc_handler = dasd_generic_uc_handler, | 4276 | .uc_handler = dasd_generic_uc_handler, |
4277 | .int_class = IOINT_DAS, | 4277 | .int_class = IRQIO_DAS, |
4278 | }; | 4278 | }; |
4279 | 4279 | ||
4280 | /* | 4280 | /* |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index eb748507c7fa..414698584344 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -78,7 +78,7 @@ static struct ccw_driver dasd_fba_driver = { | |||
78 | .freeze = dasd_generic_pm_freeze, | 78 | .freeze = dasd_generic_pm_freeze, |
79 | .thaw = dasd_generic_restore_device, | 79 | .thaw = dasd_generic_restore_device, |
80 | .restore = dasd_generic_restore_device, | 80 | .restore = dasd_generic_restore_device, |
81 | .int_class = IOINT_DAS, | 81 | .int_class = IRQIO_DAS, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static void | 84 | static void |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 40084501c31b..33b7141a182f 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define RAW3215_NR_CCWS 3 | 44 | #define RAW3215_NR_CCWS 3 |
45 | #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ | 45 | #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ |
46 | 46 | ||
47 | #define RAW3215_FIXED 1 /* 3215 console device is not be freed */ | ||
47 | #define RAW3215_WORKING 4 /* set if a request is being worked on */ | 48 | #define RAW3215_WORKING 4 /* set if a request is being worked on */ |
48 | #define RAW3215_THROTTLED 8 /* set if reading is disabled */ | 49 | #define RAW3215_THROTTLED 8 /* set if reading is disabled */ |
49 | #define RAW3215_STOPPED 16 /* set if writing is disabled */ | 50 | #define RAW3215_STOPPED 16 /* set if writing is disabled */ |
@@ -630,7 +631,8 @@ static void raw3215_shutdown(struct raw3215_info *raw) | |||
630 | DECLARE_WAITQUEUE(wait, current); | 631 | DECLARE_WAITQUEUE(wait, current); |
631 | unsigned long flags; | 632 | unsigned long flags; |
632 | 633 | ||
633 | if (!(raw->port.flags & ASYNC_INITIALIZED)) | 634 | if (!(raw->port.flags & ASYNC_INITIALIZED) || |
635 | (raw->flags & RAW3215_FIXED)) | ||
634 | return; | 636 | return; |
635 | /* Wait for outstanding requests, then free irq */ | 637 | /* Wait for outstanding requests, then free irq */ |
636 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); | 638 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
@@ -805,7 +807,7 @@ static struct ccw_driver raw3215_ccw_driver = { | |||
805 | .freeze = &raw3215_pm_stop, | 807 | .freeze = &raw3215_pm_stop, |
806 | .thaw = &raw3215_pm_start, | 808 | .thaw = &raw3215_pm_start, |
807 | .restore = &raw3215_pm_start, | 809 | .restore = &raw3215_pm_start, |
808 | .int_class = IOINT_C15, | 810 | .int_class = IRQIO_C15, |
809 | }; | 811 | }; |
810 | 812 | ||
811 | #ifdef CONFIG_TN3215_CONSOLE | 813 | #ifdef CONFIG_TN3215_CONSOLE |
@@ -927,6 +929,8 @@ static int __init con3215_init(void) | |||
927 | dev_set_drvdata(&cdev->dev, raw); | 929 | dev_set_drvdata(&cdev->dev, raw); |
928 | cdev->handler = raw3215_irq; | 930 | cdev->handler = raw3215_irq; |
929 | 931 | ||
932 | raw->flags |= RAW3215_FIXED; | ||
933 | |||
930 | /* Request the console irq */ | 934 | /* Request the console irq */ |
931 | if (raw3215_startup(raw) != 0) { | 935 | if (raw3215_startup(raw) != 0) { |
932 | raw3215_free_info(raw); | 936 | raw3215_free_info(raw); |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f3b8bb84faf2..9a6c140c5f07 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -1396,7 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = { | |||
1396 | .freeze = &raw3270_pm_stop, | 1396 | .freeze = &raw3270_pm_stop, |
1397 | .thaw = &raw3270_pm_start, | 1397 | .thaw = &raw3270_pm_start, |
1398 | .restore = &raw3270_pm_start, | 1398 | .restore = &raw3270_pm_start, |
1399 | .int_class = IOINT_C70, | 1399 | .int_class = IRQIO_C70, |
1400 | }; | 1400 | }; |
1401 | 1401 | ||
1402 | static int | 1402 | static int |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 4fa21f7e2308..12c16a65dd25 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -400,7 +400,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, | |||
400 | u32 finished_sccb; | 400 | u32 finished_sccb; |
401 | u32 evbuf_pending; | 401 | u32 evbuf_pending; |
402 | 402 | ||
403 | kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; | 403 | inc_irq_stat(IRQEXT_SCP); |
404 | spin_lock(&sclp_lock); | 404 | spin_lock(&sclp_lock); |
405 | finished_sccb = param32 & 0xfffffff8; | 405 | finished_sccb = param32 & 0xfffffff8; |
406 | evbuf_pending = param32 & 0x3; | 406 | evbuf_pending = param32 & 0x3; |
@@ -813,7 +813,7 @@ static void sclp_check_handler(struct ext_code ext_code, | |||
813 | { | 813 | { |
814 | u32 finished_sccb; | 814 | u32 finished_sccb; |
815 | 815 | ||
816 | kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; | 816 | inc_irq_stat(IRQEXT_SCP); |
817 | finished_sccb = param32 & 0xfffffff8; | 817 | finished_sccb = param32 & 0xfffffff8; |
818 | /* Is this the interrupt we are waiting for? */ | 818 | /* Is this the interrupt we are waiting for? */ |
819 | if (finished_sccb == 0) | 819 | if (finished_sccb == 0) |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 6ae929c024ae..9aa79702b370 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -1193,7 +1193,7 @@ static struct ccw_driver tape_34xx_driver = { | |||
1193 | .set_online = tape_34xx_online, | 1193 | .set_online = tape_34xx_online, |
1194 | .set_offline = tape_generic_offline, | 1194 | .set_offline = tape_generic_offline, |
1195 | .freeze = tape_generic_pm_suspend, | 1195 | .freeze = tape_generic_pm_suspend, |
1196 | .int_class = IOINT_TAP, | 1196 | .int_class = IRQIO_TAP, |
1197 | }; | 1197 | }; |
1198 | 1198 | ||
1199 | static int | 1199 | static int |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 1b0eb49f739c..327cb19ad0b0 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -1656,7 +1656,7 @@ static struct ccw_driver tape_3590_driver = { | |||
1656 | .set_offline = tape_generic_offline, | 1656 | .set_offline = tape_generic_offline, |
1657 | .set_online = tape_3590_online, | 1657 | .set_online = tape_3590_online, |
1658 | .freeze = tape_generic_pm_suspend, | 1658 | .freeze = tape_generic_pm_suspend, |
1659 | .int_class = IOINT_TAP, | 1659 | .int_class = IRQIO_TAP, |
1660 | }; | 1660 | }; |
1661 | 1661 | ||
1662 | /* | 1662 | /* |
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 73bef0bd394c..483f72ba030d 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c | |||
@@ -74,7 +74,7 @@ static struct ccw_driver ur_driver = { | |||
74 | .set_online = ur_set_online, | 74 | .set_online = ur_set_online, |
75 | .set_offline = ur_set_offline, | 75 | .set_offline = ur_set_offline, |
76 | .freeze = ur_pm_suspend, | 76 | .freeze = ur_pm_suspend, |
77 | .int_class = IOINT_VMR, | 77 | .int_class = IRQIO_VMR, |
78 | }; | 78 | }; |
79 | 79 | ||
80 | static DEFINE_MUTEX(vmur_mutex); | 80 | static DEFINE_MUTEX(vmur_mutex); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 68e80e2734a4..10729bbceced 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -283,7 +283,7 @@ struct chsc_sei_nt2_area { | |||
283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ | 283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ |
284 | } __packed; | 284 | } __packed; |
285 | 285 | ||
286 | #define CHSC_SEI_NT0 0ULL | 286 | #define CHSC_SEI_NT0 (1ULL << 63) |
287 | #define CHSC_SEI_NT2 (1ULL << 61) | 287 | #define CHSC_SEI_NT2 (1ULL << 61) |
288 | 288 | ||
289 | struct chsc_sei { | 289 | struct chsc_sei { |
@@ -291,7 +291,8 @@ struct chsc_sei { | |||
291 | u32 reserved1; | 291 | u32 reserved1; |
292 | u64 ntsm; /* notification type mask */ | 292 | u64 ntsm; /* notification type mask */ |
293 | struct chsc_header response; | 293 | struct chsc_header response; |
294 | u32 reserved2; | 294 | u32 :24; |
295 | u8 nt; | ||
295 | union { | 296 | union { |
296 | struct chsc_sei_nt0_area nt0_area; | 297 | struct chsc_sei_nt0_area nt0_area; |
297 | struct chsc_sei_nt2_area nt2_area; | 298 | struct chsc_sei_nt2_area nt2_area; |
@@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm) | |||
496 | css_schedule_eval_all(); | 497 | css_schedule_eval_all(); |
497 | } | 498 | } |
498 | 499 | ||
499 | switch (sei->ntsm) { | 500 | switch (sei->nt) { |
500 | case CHSC_SEI_NT0: | 501 | case 0: |
501 | chsc_process_sei_nt0(&sei->u.nt0_area); | 502 | chsc_process_sei_nt0(&sei->u.nt0_area); |
502 | return 1; | 503 | break; |
503 | case CHSC_SEI_NT2: | 504 | case 2: |
504 | chsc_process_sei_nt2(&sei->u.nt2_area); | 505 | chsc_process_sei_nt2(&sei->u.nt2_area); |
505 | return 1; | 506 | break; |
506 | default: | 507 | default: |
507 | CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n", | 508 | CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n", |
508 | sei->ntsm); | 509 | sei->nt); |
509 | return 0; | 510 | break; |
510 | } | 511 | } |
511 | } else { | 512 | } else { |
512 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", | 513 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", |
@@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
537 | sei = sei_page; | 538 | sei = sei_page; |
538 | 539 | ||
539 | CIO_TRACE_EVENT(2, "prcss"); | 540 | CIO_TRACE_EVENT(2, "prcss"); |
540 | 541 | __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2); | |
541 | /* | ||
542 | * The ntsm does not allow to select NT0 and NT2 together. We need to | ||
543 | * first check for NT2, than additionally for NT0... | ||
544 | */ | ||
545 | #ifdef CONFIG_PCI | ||
546 | if (!__chsc_process_crw(sei, CHSC_SEI_NT2)) | ||
547 | #endif | ||
548 | __chsc_process_crw(sei, CHSC_SEI_NT0); | ||
549 | } | 542 | } |
550 | 543 | ||
551 | void chsc_chp_online(struct chp_id chpid) | 544 | void chsc_chp_online(struct chp_id chpid) |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 8f9a1a384496..facdf809113f 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -58,7 +58,7 @@ static void chsc_subchannel_irq(struct subchannel *sch) | |||
58 | 58 | ||
59 | CHSC_LOG(4, "irb"); | 59 | CHSC_LOG(4, "irb"); |
60 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); | 60 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); |
61 | kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++; | 61 | inc_irq_stat(IRQIO_CSC); |
62 | 62 | ||
63 | /* Copy irb to provided request and set done. */ | 63 | /* Copy irb to provided request and set done. */ |
64 | if (!request) { | 64 | if (!request) { |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 8e927b9f285f..c8faf6230b0f 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -611,7 +611,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
611 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; | 611 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; |
612 | irb = (struct irb *)&S390_lowcore.irb; | 612 | irb = (struct irb *)&S390_lowcore.irb; |
613 | do { | 613 | do { |
614 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | 614 | kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); |
615 | if (tpi_info->adapter_IO) { | 615 | if (tpi_info->adapter_IO) { |
616 | do_adapter_IO(tpi_info->isc); | 616 | do_adapter_IO(tpi_info->isc); |
617 | continue; | 617 | continue; |
@@ -619,7 +619,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
619 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | 619 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; |
620 | if (!sch) { | 620 | if (!sch) { |
621 | /* Clear pending interrupt condition. */ | 621 | /* Clear pending interrupt condition. */ |
622 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 622 | inc_irq_stat(IRQIO_CIO); |
623 | tsch(tpi_info->schid, irb); | 623 | tsch(tpi_info->schid, irb); |
624 | continue; | 624 | continue; |
625 | } | 625 | } |
@@ -633,9 +633,9 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
633 | if (sch->driver && sch->driver->irq) | 633 | if (sch->driver && sch->driver->irq) |
634 | sch->driver->irq(sch); | 634 | sch->driver->irq(sch); |
635 | else | 635 | else |
636 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 636 | inc_irq_stat(IRQIO_CIO); |
637 | } else | 637 | } else |
638 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 638 | inc_irq_stat(IRQIO_CIO); |
639 | spin_unlock(sch->lock); | 639 | spin_unlock(sch->lock); |
640 | /* | 640 | /* |
641 | * Are more interrupts pending? | 641 | * Are more interrupts pending? |
@@ -678,7 +678,7 @@ static void cio_tsch(struct subchannel *sch) | |||
678 | if (sch->driver && sch->driver->irq) | 678 | if (sch->driver && sch->driver->irq) |
679 | sch->driver->irq(sch); | 679 | sch->driver->irq(sch); |
680 | else | 680 | else |
681 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 681 | inc_irq_stat(IRQIO_CIO); |
682 | if (!irq_context) { | 682 | if (!irq_context) { |
683 | irq_exit(); | 683 | irq_exit(); |
684 | _local_bh_enable(); | 684 | _local_bh_enable(); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6995cff44636..7cd5c6812ac7 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -758,7 +758,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, | |||
758 | struct ccw_device *cdev) | 758 | struct ccw_device *cdev) |
759 | { | 759 | { |
760 | cdev->private->cdev = cdev; | 760 | cdev->private->cdev = cdev; |
761 | cdev->private->int_class = IOINT_CIO; | 761 | cdev->private->int_class = IRQIO_CIO; |
762 | atomic_set(&cdev->private->onoff, 0); | 762 | atomic_set(&cdev->private->onoff, 0); |
763 | cdev->dev.parent = &sch->dev; | 763 | cdev->dev.parent = &sch->dev; |
764 | cdev->dev.release = ccw_device_release; | 764 | cdev->dev.release = ccw_device_release; |
@@ -1023,7 +1023,7 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1023 | if (cdev) | 1023 | if (cdev) |
1024 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1024 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1025 | else | 1025 | else |
1026 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 1026 | inc_irq_stat(IRQIO_CIO); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | void io_subchannel_init_config(struct subchannel *sch) | 1029 | void io_subchannel_init_config(struct subchannel *sch) |
@@ -1634,7 +1634,7 @@ ccw_device_probe_console(void) | |||
1634 | memset(&console_private, 0, sizeof(struct ccw_device_private)); | 1634 | memset(&console_private, 0, sizeof(struct ccw_device_private)); |
1635 | console_cdev.private = &console_private; | 1635 | console_cdev.private = &console_private; |
1636 | console_private.cdev = &console_cdev; | 1636 | console_private.cdev = &console_cdev; |
1637 | console_private.int_class = IOINT_CIO; | 1637 | console_private.int_class = IRQIO_CIO; |
1638 | ret = ccw_device_console_enable(&console_cdev, sch); | 1638 | ret = ccw_device_console_enable(&console_cdev, sch); |
1639 | if (ret) { | 1639 | if (ret) { |
1640 | cio_release_console(); | 1640 | cio_release_console(); |
@@ -1715,13 +1715,13 @@ ccw_device_probe (struct device *dev) | |||
1715 | if (cdrv->int_class != 0) | 1715 | if (cdrv->int_class != 0) |
1716 | cdev->private->int_class = cdrv->int_class; | 1716 | cdev->private->int_class = cdrv->int_class; |
1717 | else | 1717 | else |
1718 | cdev->private->int_class = IOINT_CIO; | 1718 | cdev->private->int_class = IRQIO_CIO; |
1719 | 1719 | ||
1720 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; | 1720 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; |
1721 | 1721 | ||
1722 | if (ret) { | 1722 | if (ret) { |
1723 | cdev->drv = NULL; | 1723 | cdev->drv = NULL; |
1724 | cdev->private->int_class = IOINT_CIO; | 1724 | cdev->private->int_class = IRQIO_CIO; |
1725 | return ret; | 1725 | return ret; |
1726 | } | 1726 | } |
1727 | 1727 | ||
@@ -1755,7 +1755,7 @@ ccw_device_remove (struct device *dev) | |||
1755 | } | 1755 | } |
1756 | ccw_device_set_timeout(cdev, 0); | 1756 | ccw_device_set_timeout(cdev, 0); |
1757 | cdev->drv = NULL; | 1757 | cdev->drv = NULL; |
1758 | cdev->private->int_class = IOINT_CIO; | 1758 | cdev->private->int_class = IRQIO_CIO; |
1759 | return 0; | 1759 | return 0; |
1760 | } | 1760 | } |
1761 | 1761 | ||
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 2e575cff9845..7d4ecb65db00 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -61,11 +61,10 @@ dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event) | |||
61 | 61 | ||
62 | if (dev_event == DEV_EVENT_INTERRUPT) { | 62 | if (dev_event == DEV_EVENT_INTERRUPT) { |
63 | if (state == DEV_STATE_ONLINE) | 63 | if (state == DEV_STATE_ONLINE) |
64 | kstat_cpu(smp_processor_id()). | 64 | inc_irq_stat(cdev->private->int_class); |
65 | irqs[cdev->private->int_class]++; | ||
66 | else if (state != DEV_STATE_CMFCHANGE && | 65 | else if (state != DEV_STATE_CMFCHANGE && |
67 | state != DEV_STATE_CMFUPDATE) | 66 | state != DEV_STATE_CMFUPDATE) |
68 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 67 | inc_irq_stat(IRQIO_CIO); |
69 | } | 68 | } |
70 | dev_jumptable[state][dev_event](cdev, dev_event); | 69 | dev_jumptable[state][dev_event](cdev, dev_event); |
71 | } | 70 | } |
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index 6c9673400464..d9eddcba7e88 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c | |||
@@ -139,7 +139,7 @@ static void eadm_subchannel_irq(struct subchannel *sch) | |||
139 | EADM_LOG(6, "irq"); | 139 | EADM_LOG(6, "irq"); |
140 | EADM_LOG_HEX(6, irb, sizeof(*irb)); | 140 | EADM_LOG_HEX(6, irb, sizeof(*irb)); |
141 | 141 | ||
142 | kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++; | 142 | inc_irq_stat(IRQIO_ADM); |
143 | 143 | ||
144 | if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) | 144 | if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) |
145 | && scsw->eswf == 1 && irb->esw.eadm.erw.r) | 145 | && scsw->eswf == 1 && irb->esw.eadm.erw.r) |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index bdb394b066fc..bde5255200dc 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -182,7 +182,7 @@ static void tiqdio_thinint_handler(void *alsi, void *data) | |||
182 | struct qdio_q *q; | 182 | struct qdio_q *q; |
183 | 183 | ||
184 | last_ai_time = S390_lowcore.int_clock; | 184 | last_ai_time = S390_lowcore.int_clock; |
185 | kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++; | 185 | inc_irq_stat(IRQIO_QAI); |
186 | 186 | ||
187 | /* protect tiq_list entries, only changed in activate or shutdown */ | 187 | /* protect tiq_list entries, only changed in activate or shutdown */ |
188 | rcu_read_lock(); | 188 | rcu_read_lock(); |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 7b865a7300e6..b8b340ac5332 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -1272,7 +1272,7 @@ out: | |||
1272 | 1272 | ||
1273 | static void ap_interrupt_handler(void *unused1, void *unused2) | 1273 | static void ap_interrupt_handler(void *unused1, void *unused2) |
1274 | { | 1274 | { |
1275 | kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++; | 1275 | inc_irq_stat(IRQIO_APB); |
1276 | tasklet_schedule(&ap_tasklet); | 1276 | tasklet_schedule(&ap_tasklet); |
1277 | } | 1277 | } |
1278 | 1278 | ||
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 7dabef624da3..8491111aec12 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -392,7 +392,7 @@ static void kvm_extint_handler(struct ext_code ext_code, | |||
392 | 392 | ||
393 | if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) | 393 | if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) |
394 | return; | 394 | return; |
395 | kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++; | 395 | inc_irq_stat(IRQEXT_VRT); |
396 | 396 | ||
397 | /* The LSB might be overloaded, we have to mask it */ | 397 | /* The LSB might be overloaded, we have to mask it */ |
398 | vq = (struct virtqueue *)(param64 & ~1UL); | 398 | vq = (struct virtqueue *)(param64 & ~1UL); |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 5c70a6599578..83bc9c5fa0c1 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -282,7 +282,7 @@ static struct ccw_driver claw_ccw_driver = { | |||
282 | .ids = claw_ids, | 282 | .ids = claw_ids, |
283 | .probe = ccwgroup_probe_ccwdev, | 283 | .probe = ccwgroup_probe_ccwdev, |
284 | .remove = ccwgroup_remove_ccwdev, | 284 | .remove = ccwgroup_remove_ccwdev, |
285 | .int_class = IOINT_CLW, | 285 | .int_class = IRQIO_CLW, |
286 | }; | 286 | }; |
287 | 287 | ||
288 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, | 288 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 817b68925ddd..676f12049a36 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -1755,7 +1755,7 @@ static struct ccw_driver ctcm_ccw_driver = { | |||
1755 | .ids = ctcm_ids, | 1755 | .ids = ctcm_ids, |
1756 | .probe = ccwgroup_probe_ccwdev, | 1756 | .probe = ccwgroup_probe_ccwdev, |
1757 | .remove = ccwgroup_remove_ccwdev, | 1757 | .remove = ccwgroup_remove_ccwdev, |
1758 | .int_class = IOINT_CTC, | 1758 | .int_class = IRQIO_CTC, |
1759 | }; | 1759 | }; |
1760 | 1760 | ||
1761 | static struct ccwgroup_driver ctcm_group_driver = { | 1761 | static struct ccwgroup_driver ctcm_group_driver = { |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 2ca0f1dd7a00..c645dc9e98af 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -2384,7 +2384,7 @@ static struct ccw_driver lcs_ccw_driver = { | |||
2384 | .ids = lcs_ids, | 2384 | .ids = lcs_ids, |
2385 | .probe = ccwgroup_probe_ccwdev, | 2385 | .probe = ccwgroup_probe_ccwdev, |
2386 | .remove = ccwgroup_remove_ccwdev, | 2386 | .remove = ccwgroup_remove_ccwdev, |
2387 | .int_class = IOINT_LCS, | 2387 | .int_class = IRQIO_LCS, |
2388 | }; | 2388 | }; |
2389 | 2389 | ||
2390 | /** | 2390 | /** |
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 5aedcdf4ac5c..1ebe67cd1833 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
@@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) | |||
126 | 126 | ||
127 | static int sh_clk_div_enable(struct clk *clk) | 127 | static int sh_clk_div_enable(struct clk *clk) |
128 | { | 128 | { |
129 | if (clk->div_mask == SH_CLK_DIV6_MSK) { | ||
130 | int ret = sh_clk_div_set_rate(clk, clk->rate); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | } | ||
134 | |||
129 | sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); | 135 | sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); |
130 | return 0; | 136 | return 0; |
131 | } | 137 | } |
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 7de2a10213bd..36eec320569c 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig | |||
@@ -444,6 +444,7 @@ config COMEDI_ADQ12B | |||
444 | 444 | ||
445 | config COMEDI_NI_AT_A2150 | 445 | config COMEDI_NI_AT_A2150 |
446 | tristate "NI AT-A2150 ISA card support" | 446 | tristate "NI AT-A2150 ISA card support" |
447 | select COMEDI_FC | ||
447 | depends on VIRT_TO_BUS | 448 | depends on VIRT_TO_BUS |
448 | ---help--- | 449 | ---help--- |
449 | Enable support for National Instruments AT-A2150 cards | 450 | Enable support for National Instruments AT-A2150 cards |
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b7bba1790a20..9b038e4a7e71 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c | |||
@@ -1549,6 +1549,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
1549 | if (cmd == COMEDI_DEVCONFIG) { | 1549 | if (cmd == COMEDI_DEVCONFIG) { |
1550 | rc = do_devconfig_ioctl(dev, | 1550 | rc = do_devconfig_ioctl(dev, |
1551 | (struct comedi_devconfig __user *)arg); | 1551 | (struct comedi_devconfig __user *)arg); |
1552 | if (rc == 0) | ||
1553 | /* Evade comedi_auto_unconfig(). */ | ||
1554 | dev_file_info->hardware_device = NULL; | ||
1552 | goto done; | 1555 | goto done; |
1553 | } | 1556 | } |
1554 | 1557 | ||
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index fb3d09323ba1..01de996239f1 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c | |||
@@ -345,7 +345,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, | |||
345 | struct waveform_private *devpriv = dev->private; | 345 | struct waveform_private *devpriv = dev->private; |
346 | 346 | ||
347 | devpriv->timer_running = 0; | 347 | devpriv->timer_running = 0; |
348 | del_timer(&devpriv->timer); | 348 | del_timer_sync(&devpriv->timer); |
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index aaac0b2cc9eb..fd1662b4175d 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c | |||
@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
963 | .ao_range_table = &range_ni_M_625x_ao, | 963 | .ao_range_table = &range_ni_M_625x_ao, |
964 | .reg_type = ni_reg_625x, | 964 | .reg_type = ni_reg_625x, |
965 | .ao_unipolar = 0, | 965 | .ao_unipolar = 0, |
966 | .ao_speed = 357, | 966 | .ao_speed = 350, |
967 | .num_p0_dio_channels = 8, | 967 | .num_p0_dio_channels = 8, |
968 | .caldac = {caldac_none}, | 968 | .caldac = {caldac_none}, |
969 | .has_8255 = 0, | 969 | .has_8255 = 0, |
@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
982 | .ao_range_table = &range_ni_M_625x_ao, | 982 | .ao_range_table = &range_ni_M_625x_ao, |
983 | .reg_type = ni_reg_625x, | 983 | .reg_type = ni_reg_625x, |
984 | .ao_unipolar = 0, | 984 | .ao_unipolar = 0, |
985 | .ao_speed = 357, | 985 | .ao_speed = 350, |
986 | .num_p0_dio_channels = 8, | 986 | .num_p0_dio_channels = 8, |
987 | .caldac = {caldac_none}, | 987 | .caldac = {caldac_none}, |
988 | .has_8255 = 0, | 988 | .has_8255 = 0, |
@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1001 | .ao_range_table = &range_ni_M_625x_ao, | 1001 | .ao_range_table = &range_ni_M_625x_ao, |
1002 | .reg_type = ni_reg_625x, | 1002 | .reg_type = ni_reg_625x, |
1003 | .ao_unipolar = 0, | 1003 | .ao_unipolar = 0, |
1004 | .ao_speed = 357, | 1004 | .ao_speed = 350, |
1005 | .num_p0_dio_channels = 8, | 1005 | .num_p0_dio_channels = 8, |
1006 | .caldac = {caldac_none}, | 1006 | .caldac = {caldac_none}, |
1007 | .has_8255 = 0, | 1007 | .has_8255 = 0, |
@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1037 | .ao_range_table = &range_ni_M_625x_ao, | 1037 | .ao_range_table = &range_ni_M_625x_ao, |
1038 | .reg_type = ni_reg_625x, | 1038 | .reg_type = ni_reg_625x, |
1039 | .ao_unipolar = 0, | 1039 | .ao_unipolar = 0, |
1040 | .ao_speed = 357, | 1040 | .ao_speed = 350, |
1041 | .num_p0_dio_channels = 32, | 1041 | .num_p0_dio_channels = 32, |
1042 | .caldac = {caldac_none}, | 1042 | .caldac = {caldac_none}, |
1043 | .has_8255 = 0, | 1043 | .has_8255 = 0, |
@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1056 | .ao_range_table = &range_ni_M_625x_ao, | 1056 | .ao_range_table = &range_ni_M_625x_ao, |
1057 | .reg_type = ni_reg_625x, | 1057 | .reg_type = ni_reg_625x, |
1058 | .ao_unipolar = 0, | 1058 | .ao_unipolar = 0, |
1059 | .ao_speed = 357, | 1059 | .ao_speed = 350, |
1060 | .num_p0_dio_channels = 32, | 1060 | .num_p0_dio_channels = 32, |
1061 | .caldac = {caldac_none}, | 1061 | .caldac = {caldac_none}, |
1062 | .has_8255 = 0, | 1062 | .has_8255 = 0, |
@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1092 | .ao_range_table = &range_ni_M_628x_ao, | 1092 | .ao_range_table = &range_ni_M_628x_ao, |
1093 | .reg_type = ni_reg_628x, | 1093 | .reg_type = ni_reg_628x, |
1094 | .ao_unipolar = 1, | 1094 | .ao_unipolar = 1, |
1095 | .ao_speed = 357, | 1095 | .ao_speed = 350, |
1096 | .num_p0_dio_channels = 8, | 1096 | .num_p0_dio_channels = 8, |
1097 | .caldac = {caldac_none}, | 1097 | .caldac = {caldac_none}, |
1098 | .has_8255 = 0, | 1098 | .has_8255 = 0, |
@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1111 | .ao_range_table = &range_ni_M_628x_ao, | 1111 | .ao_range_table = &range_ni_M_628x_ao, |
1112 | .reg_type = ni_reg_628x, | 1112 | .reg_type = ni_reg_628x, |
1113 | .ao_unipolar = 1, | 1113 | .ao_unipolar = 1, |
1114 | .ao_speed = 357, | 1114 | .ao_speed = 350, |
1115 | .num_p0_dio_channels = 8, | 1115 | .num_p0_dio_channels = 8, |
1116 | .caldac = {caldac_none}, | 1116 | .caldac = {caldac_none}, |
1117 | .has_8255 = 0, | 1117 | .has_8255 = 0, |
@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1147 | .ao_range_table = &range_ni_M_628x_ao, | 1147 | .ao_range_table = &range_ni_M_628x_ao, |
1148 | .reg_type = ni_reg_628x, | 1148 | .reg_type = ni_reg_628x, |
1149 | .ao_unipolar = 1, | 1149 | .ao_unipolar = 1, |
1150 | .ao_speed = 357, | 1150 | .ao_speed = 350, |
1151 | .num_p0_dio_channels = 32, | 1151 | .num_p0_dio_channels = 32, |
1152 | .caldac = {caldac_none}, | 1152 | .caldac = {caldac_none}, |
1153 | .has_8255 = 0, | 1153 | .has_8255 = 0, |
diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig index 580406cb1808..b2f8331e4acf 100644 --- a/drivers/staging/fwserial/Kconfig +++ b/drivers/staging/fwserial/Kconfig | |||
@@ -3,7 +3,9 @@ config FIREWIRE_SERIAL | |||
3 | depends on FIREWIRE | 3 | depends on FIREWIRE |
4 | help | 4 | help |
5 | This enables TTY over IEEE 1394, providing high-speed serial | 5 | This enables TTY over IEEE 1394, providing high-speed serial |
6 | connectivity to cabled peers. | 6 | connectivity to cabled peers. This driver implements a |
7 | ad-hoc transport protocol and is currently limited to | ||
8 | Linux-to-Linux communication. | ||
7 | 9 | ||
8 | To compile this driver as a module, say M here: the module will | 10 | To compile this driver as a module, say M here: the module will |
9 | be called firewire-serial. | 11 | be called firewire-serial. |
diff --git a/drivers/staging/fwserial/TODO b/drivers/staging/fwserial/TODO index 726900548eae..8dae8fb25223 100644 --- a/drivers/staging/fwserial/TODO +++ b/drivers/staging/fwserial/TODO | |||
@@ -1,5 +1,5 @@ | |||
1 | TODOs | 1 | TODOs prior to this driver moving out of staging |
2 | ----- | 2 | ------------------------------------------------ |
3 | 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR | 3 | 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR |
4 | - I/O is handled asynchronously which presents some issues when error | 4 | - I/O is handled asynchronously which presents some issues when error |
5 | conditions occur. | 5 | conditions occur. |
@@ -11,17 +11,9 @@ TODOs | |||
11 | -- Issues with firewire stack -- | 11 | -- Issues with firewire stack -- |
12 | 1. This driver uses the same unregistered vendor id that the firewire core does | 12 | 1. This driver uses the same unregistered vendor id that the firewire core does |
13 | (0xd00d1e). Perhaps this could be exposed as a define in | 13 | (0xd00d1e). Perhaps this could be exposed as a define in |
14 | firewire-constants.h? | 14 | firewire.h? |
15 | 2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci | ||
16 | - otherwise how will this driver know the max size of address window to | ||
17 | open for one packet write? | ||
18 | 3. Maybe device_max_receive() and link_speed_to_max_payload() should be | 15 | 3. Maybe device_max_receive() and link_speed_to_max_payload() should be |
19 | taken up by the firewire core? | 16 | taken up by the firewire core? |
20 | 4. To avoid dropping rx data while still limiting the maximum buffering, | ||
21 | the size of the AR context must be known. How to expose this to drivers? | ||
22 | 5. Explore if bigger AR context will reduce RCODE_BUSY responses | ||
23 | (or auto-grow to certain max size -- but this would require major surgery | ||
24 | as the current AR is contiguously mapped) | ||
25 | 17 | ||
26 | -- Issues with TTY core -- | 18 | -- Issues with TTY core -- |
27 | 1. Hack for alternate device name scheme | 19 | 1. Hack for alternate device name scheme |
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 61ee29083b26..d03a7f57e8d4 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c | |||
@@ -179,7 +179,7 @@ static void dump_profile(struct seq_file *m, struct stats *stats) | |||
179 | /* Returns the max receive packet size for the given card */ | 179 | /* Returns the max receive packet size for the given card */ |
180 | static inline int device_max_receive(struct fw_device *fw_device) | 180 | static inline int device_max_receive(struct fw_device *fw_device) |
181 | { | 181 | { |
182 | return 1 << (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1); | 182 | return 1 << (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1); |
183 | } | 183 | } |
184 | 184 | ||
185 | static void fwtty_log_tx_error(struct fwtty_port *port, int rcode) | 185 | static void fwtty_log_tx_error(struct fwtty_port *port, int rcode) |
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 8b572edf9563..caa1c1ea82d5 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h | |||
@@ -374,10 +374,10 @@ static inline void fwtty_bind_console(struct fwtty_port *port, | |||
374 | */ | 374 | */ |
375 | static inline int link_speed_to_max_payload(unsigned speed) | 375 | static inline int link_speed_to_max_payload(unsigned speed) |
376 | { | 376 | { |
377 | static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, }; | 377 | static const int max_async[] = { 307, 614, 1229, 2458, }; |
378 | BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200); | 378 | BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800); |
379 | 379 | ||
380 | speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200); | 380 | speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800); |
381 | if (limit_bw) | 381 | if (limit_bw) |
382 | return max_async[speed]; | 382 | return max_async[speed]; |
383 | else | 383 | else |
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index fb31b457a56a..c5ceb9d90ea8 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c | |||
@@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) | |||
239 | struct mxs_lradc *lradc = iio_priv(iio); | 239 | struct mxs_lradc *lradc = iio_priv(iio); |
240 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | | 240 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | |
241 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); | 241 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); |
242 | int i, j = 0; | 242 | unsigned int i, j = 0; |
243 | 243 | ||
244 | for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { | 244 | for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { |
245 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); | 245 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); |
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index ea295b25308c..87979a0d03a9 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig | |||
@@ -27,8 +27,8 @@ config ADIS16130 | |||
27 | config ADIS16260 | 27 | config ADIS16260 |
28 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" | 28 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" |
29 | depends on SPI | 29 | depends on SPI |
30 | select IIO_TRIGGER if IIO_BUFFER | 30 | select IIO_ADIS_LIB |
31 | select IIO_SW_RING if IIO_BUFFER | 31 | select IIO_ADIS_LIB_BUFFER if IIO_BUFFER |
32 | help | 32 | help |
33 | Say yes here to build support for Analog Devices ADIS16260 ADIS16265 | 33 | Say yes here to build support for Analog Devices ADIS16260 ADIS16265 |
34 | ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. | 34 | ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. |
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 3525a68d6a75..41d7350d030f 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c | |||
@@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev, | |||
69 | ret = spi_read(st->us, st->buf, 2); | 69 | ret = spi_read(st->us, st->buf, 2); |
70 | 70 | ||
71 | if (ret == 0) | 71 | if (ret == 0) |
72 | *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; | 72 | *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11); |
73 | mutex_unlock(&st->buf_lock); | 73 | mutex_unlock(&st->buf_lock); |
74 | 74 | ||
75 | return ret; | 75 | return ret; |
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index ecf0f44bc70e..cec19f1cf56c 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c | |||
@@ -584,7 +584,6 @@ int imx_drm_add_encoder(struct drm_encoder *encoder, | |||
584 | 584 | ||
585 | ret = imx_drm_encoder_register(imx_drm_encoder); | 585 | ret = imx_drm_encoder_register(imx_drm_encoder); |
586 | if (ret) { | 586 | if (ret) { |
587 | kfree(imx_drm_encoder); | ||
588 | ret = -ENOMEM; | 587 | ret = -ENOMEM; |
589 | goto err_register; | 588 | goto err_register; |
590 | } | 589 | } |
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index 677e665ca86d..f7059cddd7fd 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c | |||
@@ -1104,7 +1104,9 @@ static int ipu_probe(struct platform_device *pdev) | |||
1104 | if (ret) | 1104 | if (ret) |
1105 | goto out_failed_irq; | 1105 | goto out_failed_irq; |
1106 | 1106 | ||
1107 | ipu_reset(ipu); | 1107 | ret = ipu_reset(ipu); |
1108 | if (ret) | ||
1109 | goto out_failed_reset; | ||
1108 | 1110 | ||
1109 | /* Set MCU_T to divide MCU access window into 2 */ | 1111 | /* Set MCU_T to divide MCU access window into 2 */ |
1110 | ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), | 1112 | ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), |
@@ -1129,6 +1131,7 @@ failed_add_clients: | |||
1129 | ipu_submodules_exit(ipu); | 1131 | ipu_submodules_exit(ipu); |
1130 | failed_submodules_init: | 1132 | failed_submodules_init: |
1131 | ipu_irq_exit(ipu); | 1133 | ipu_irq_exit(ipu); |
1134 | out_failed_reset: | ||
1132 | out_failed_irq: | 1135 | out_failed_irq: |
1133 | clk_disable_unprepare(ipu->clk); | 1136 | clk_disable_unprepare(ipu->clk); |
1134 | failed_clk_get: | 1137 | failed_clk_get: |
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 1892006526b5..4b3a019409b5 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c | |||
@@ -452,7 +452,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, | |||
452 | int ret; | 452 | int ret; |
453 | 453 | ||
454 | ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); | 454 | ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); |
455 | if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) { | 455 | if (IS_ERR(ipu_crtc->ipu_ch)) { |
456 | ret = PTR_ERR(ipu_crtc->ipu_ch); | 456 | ret = PTR_ERR(ipu_crtc->ipu_ch); |
457 | goto err_out; | 457 | goto err_out; |
458 | } | 458 | } |
@@ -472,7 +472,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, | |||
472 | if (pdata->dp >= 0) { | 472 | if (pdata->dp >= 0) { |
473 | ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); | 473 | ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); |
474 | if (IS_ERR(ipu_crtc->dp)) { | 474 | if (IS_ERR(ipu_crtc->dp)) { |
475 | ret = PTR_ERR(ipu_crtc->ipu_ch); | 475 | ret = PTR_ERR(ipu_crtc->dp); |
476 | goto err_out; | 476 | goto err_out; |
477 | } | 477 | } |
478 | } | 478 | } |
@@ -548,6 +548,8 @@ static int ipu_drm_probe(struct platform_device *pdev) | |||
548 | ipu_crtc->dev = &pdev->dev; | 548 | ipu_crtc->dev = &pdev->dev; |
549 | 549 | ||
550 | ret = ipu_crtc_init(ipu_crtc, pdata); | 550 | ret = ipu_crtc_init(ipu_crtc, pdata); |
551 | if (ret) | ||
552 | return ret; | ||
551 | 553 | ||
552 | platform_set_drvdata(pdev, ipu_crtc); | 554 | platform_set_drvdata(pdev, ipu_crtc); |
553 | 555 | ||
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile index 1ca0e0016de4..d85e058f2845 100644 --- a/drivers/staging/omapdrm/Makefile +++ b/drivers/staging/omapdrm/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | ccflags-y := -Iinclude/drm -Werror | 6 | ccflags-y := -Iinclude/drm -Werror |
7 | omapdrm-y := omap_drv.o \ | 7 | omapdrm-y := omap_drv.o \ |
8 | omap_irq.o \ | ||
8 | omap_debugfs.o \ | 9 | omap_debugfs.o \ |
9 | omap_crtc.o \ | 10 | omap_crtc.o \ |
10 | omap_plane.o \ | 11 | omap_plane.o \ |
diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO index 938c7888ca31..abeeb00aaa12 100644 --- a/drivers/staging/omapdrm/TODO +++ b/drivers/staging/omapdrm/TODO | |||
@@ -17,9 +17,6 @@ TODO | |||
17 | . Revisit GEM sync object infrastructure.. TTM has some framework for this | 17 | . Revisit GEM sync object infrastructure.. TTM has some framework for this |
18 | already. Possibly this could be refactored out and made more common? | 18 | already. Possibly this could be refactored out and made more common? |
19 | There should be some way to do this with less wheel-reinvention. | 19 | There should be some way to do this with less wheel-reinvention. |
20 | . Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder, | ||
21 | part connector. Which results in a bit of duct tape to fwd calls from | ||
22 | encoder to connector. Possibly this could be done a bit better. | ||
23 | . Solve PM sequencing on resume. DMM/TILER must be reloaded before any | 20 | . Solve PM sequencing on resume. DMM/TILER must be reloaded before any |
24 | access is made from any component in the system. Which means on suspend | 21 | access is made from any component in the system. Which means on suspend |
25 | CRTC's should be disabled, and on resume the LUT should be reprogrammed | 22 | CRTC's should be disabled, and on resume the LUT should be reprogrammed |
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 91edb3f96972..4cc9ee733c5f 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c | |||
@@ -31,9 +31,10 @@ | |||
31 | struct omap_connector { | 31 | struct omap_connector { |
32 | struct drm_connector base; | 32 | struct drm_connector base; |
33 | struct omap_dss_device *dssdev; | 33 | struct omap_dss_device *dssdev; |
34 | struct drm_encoder *encoder; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, | 37 | void copy_timings_omap_to_drm(struct drm_display_mode *mode, |
37 | struct omap_video_timings *timings) | 38 | struct omap_video_timings *timings) |
38 | { | 39 | { |
39 | mode->clock = timings->pixel_clock; | 40 | mode->clock = timings->pixel_clock; |
@@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, | |||
64 | mode->flags |= DRM_MODE_FLAG_NVSYNC; | 65 | mode->flags |= DRM_MODE_FLAG_NVSYNC; |
65 | } | 66 | } |
66 | 67 | ||
67 | static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, | 68 | void copy_timings_drm_to_omap(struct omap_video_timings *timings, |
68 | struct drm_display_mode *mode) | 69 | struct drm_display_mode *mode) |
69 | { | 70 | { |
70 | timings->pixel_clock = mode->clock; | 71 | timings->pixel_clock = mode->clock; |
@@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, | |||
96 | timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; | 97 | timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; |
97 | } | 98 | } |
98 | 99 | ||
99 | static void omap_connector_dpms(struct drm_connector *connector, int mode) | 100 | static enum drm_connector_status omap_connector_detect( |
100 | { | ||
101 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
102 | struct omap_dss_device *dssdev = omap_connector->dssdev; | ||
103 | int old_dpms; | ||
104 | |||
105 | DBG("%s: %d", dssdev->name, mode); | ||
106 | |||
107 | old_dpms = connector->dpms; | ||
108 | |||
109 | /* from off to on, do from crtc to connector */ | ||
110 | if (mode < old_dpms) | ||
111 | drm_helper_connector_dpms(connector, mode); | ||
112 | |||
113 | if (mode == DRM_MODE_DPMS_ON) { | ||
114 | /* store resume info for suspended displays */ | ||
115 | switch (dssdev->state) { | ||
116 | case OMAP_DSS_DISPLAY_SUSPENDED: | ||
117 | dssdev->activate_after_resume = true; | ||
118 | break; | ||
119 | case OMAP_DSS_DISPLAY_DISABLED: { | ||
120 | int ret = dssdev->driver->enable(dssdev); | ||
121 | if (ret) { | ||
122 | DBG("%s: failed to enable: %d", | ||
123 | dssdev->name, ret); | ||
124 | dssdev->driver->disable(dssdev); | ||
125 | } | ||
126 | break; | ||
127 | } | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | } else { | ||
132 | /* TODO */ | ||
133 | } | ||
134 | |||
135 | /* from on to off, do from connector to crtc */ | ||
136 | if (mode > old_dpms) | ||
137 | drm_helper_connector_dpms(connector, mode); | ||
138 | } | ||
139 | |||
140 | enum drm_connector_status omap_connector_detect( | ||
141 | struct drm_connector *connector, bool force) | 101 | struct drm_connector *connector, bool force) |
142 | { | 102 | { |
143 | struct omap_connector *omap_connector = to_omap_connector(connector); | 103 | struct omap_connector *omap_connector = to_omap_connector(connector); |
@@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector) | |||
164 | struct omap_connector *omap_connector = to_omap_connector(connector); | 124 | struct omap_connector *omap_connector = to_omap_connector(connector); |
165 | struct omap_dss_device *dssdev = omap_connector->dssdev; | 125 | struct omap_dss_device *dssdev = omap_connector->dssdev; |
166 | 126 | ||
167 | dssdev->driver->disable(dssdev); | ||
168 | |||
169 | DBG("%s", omap_connector->dssdev->name); | 127 | DBG("%s", omap_connector->dssdev->name); |
170 | drm_sysfs_connector_remove(connector); | 128 | drm_sysfs_connector_remove(connector); |
171 | drm_connector_cleanup(connector); | 129 | drm_connector_cleanup(connector); |
@@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector, | |||
261 | struct drm_encoder *omap_connector_attached_encoder( | 219 | struct drm_encoder *omap_connector_attached_encoder( |
262 | struct drm_connector *connector) | 220 | struct drm_connector *connector) |
263 | { | 221 | { |
264 | int i; | ||
265 | struct omap_connector *omap_connector = to_omap_connector(connector); | 222 | struct omap_connector *omap_connector = to_omap_connector(connector); |
266 | 223 | return omap_connector->encoder; | |
267 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
268 | struct drm_mode_object *obj; | ||
269 | |||
270 | if (connector->encoder_ids[i] == 0) | ||
271 | break; | ||
272 | |||
273 | obj = drm_mode_object_find(connector->dev, | ||
274 | connector->encoder_ids[i], | ||
275 | DRM_MODE_OBJECT_ENCODER); | ||
276 | |||
277 | if (obj) { | ||
278 | struct drm_encoder *encoder = obj_to_encoder(obj); | ||
279 | struct omap_overlay_manager *mgr = | ||
280 | omap_encoder_get_manager(encoder); | ||
281 | DBG("%s: found %s", omap_connector->dssdev->name, | ||
282 | mgr->name); | ||
283 | return encoder; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | DBG("%s: no encoder", omap_connector->dssdev->name); | ||
288 | |||
289 | return NULL; | ||
290 | } | 224 | } |
291 | 225 | ||
292 | static const struct drm_connector_funcs omap_connector_funcs = { | 226 | static const struct drm_connector_funcs omap_connector_funcs = { |
293 | .dpms = omap_connector_dpms, | 227 | .dpms = drm_helper_connector_dpms, |
294 | .detect = omap_connector_detect, | 228 | .detect = omap_connector_detect, |
295 | .fill_modes = drm_helper_probe_single_connector_modes, | 229 | .fill_modes = drm_helper_probe_single_connector_modes, |
296 | .destroy = omap_connector_destroy, | 230 | .destroy = omap_connector_destroy, |
@@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = { | |||
302 | .best_encoder = omap_connector_attached_encoder, | 236 | .best_encoder = omap_connector_attached_encoder, |
303 | }; | 237 | }; |
304 | 238 | ||
305 | /* called from encoder when mode is set, to propagate settings to the dssdev */ | ||
306 | void omap_connector_mode_set(struct drm_connector *connector, | ||
307 | struct drm_display_mode *mode) | ||
308 | { | ||
309 | struct drm_device *dev = connector->dev; | ||
310 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
311 | struct omap_dss_device *dssdev = omap_connector->dssdev; | ||
312 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
313 | struct omap_video_timings timings = {0}; | ||
314 | |||
315 | copy_timings_drm_to_omap(&timings, mode); | ||
316 | |||
317 | DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", | ||
318 | omap_connector->dssdev->name, | ||
319 | mode->base.id, mode->name, mode->vrefresh, mode->clock, | ||
320 | mode->hdisplay, mode->hsync_start, | ||
321 | mode->hsync_end, mode->htotal, | ||
322 | mode->vdisplay, mode->vsync_start, | ||
323 | mode->vsync_end, mode->vtotal, mode->type, mode->flags); | ||
324 | |||
325 | if (dssdrv->check_timings(dssdev, &timings)) { | ||
326 | dev_err(dev->dev, "could not set timings\n"); | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | dssdrv->set_timings(dssdev, &timings); | ||
331 | } | ||
332 | |||
333 | /* flush an area of the framebuffer (in case of manual update display that | 239 | /* flush an area of the framebuffer (in case of manual update display that |
334 | * is not automatically flushed) | 240 | * is not automatically flushed) |
335 | */ | 241 | */ |
@@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector, | |||
344 | 250 | ||
345 | /* initialize connector */ | 251 | /* initialize connector */ |
346 | struct drm_connector *omap_connector_init(struct drm_device *dev, | 252 | struct drm_connector *omap_connector_init(struct drm_device *dev, |
347 | int connector_type, struct omap_dss_device *dssdev) | 253 | int connector_type, struct omap_dss_device *dssdev, |
254 | struct drm_encoder *encoder) | ||
348 | { | 255 | { |
349 | struct drm_connector *connector = NULL; | 256 | struct drm_connector *connector = NULL; |
350 | struct omap_connector *omap_connector; | 257 | struct omap_connector *omap_connector; |
@@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
360 | } | 267 | } |
361 | 268 | ||
362 | omap_connector->dssdev = dssdev; | 269 | omap_connector->dssdev = dssdev; |
270 | omap_connector->encoder = encoder; | ||
271 | |||
363 | connector = &omap_connector->base; | 272 | connector = &omap_connector->base; |
364 | 273 | ||
365 | drm_connector_init(dev, connector, &omap_connector_funcs, | 274 | drm_connector_init(dev, connector, &omap_connector_funcs, |
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index d87bd84257bd..5c6ed6040eff 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c | |||
@@ -28,19 +28,131 @@ | |||
28 | struct omap_crtc { | 28 | struct omap_crtc { |
29 | struct drm_crtc base; | 29 | struct drm_crtc base; |
30 | struct drm_plane *plane; | 30 | struct drm_plane *plane; |
31 | |||
31 | const char *name; | 32 | const char *name; |
32 | int id; | 33 | int pipe; |
34 | enum omap_channel channel; | ||
35 | struct omap_overlay_manager_info info; | ||
36 | |||
37 | /* | ||
38 | * Temporary: eventually this will go away, but it is needed | ||
39 | * for now to keep the output's happy. (They only need | ||
40 | * mgr->id.) Eventually this will be replaced w/ something | ||
41 | * more common-panel-framework-y | ||
42 | */ | ||
43 | struct omap_overlay_manager mgr; | ||
44 | |||
45 | struct omap_video_timings timings; | ||
46 | bool enabled; | ||
47 | bool full_update; | ||
48 | |||
49 | struct omap_drm_apply apply; | ||
50 | |||
51 | struct omap_drm_irq apply_irq; | ||
52 | struct omap_drm_irq error_irq; | ||
53 | |||
54 | /* list of in-progress apply's: */ | ||
55 | struct list_head pending_applies; | ||
56 | |||
57 | /* list of queued apply's: */ | ||
58 | struct list_head queued_applies; | ||
59 | |||
60 | /* for handling queued and in-progress applies: */ | ||
61 | struct work_struct apply_work; | ||
33 | 62 | ||
34 | /* if there is a pending flip, these will be non-null: */ | 63 | /* if there is a pending flip, these will be non-null: */ |
35 | struct drm_pending_vblank_event *event; | 64 | struct drm_pending_vblank_event *event; |
36 | struct drm_framebuffer *old_fb; | 65 | struct drm_framebuffer *old_fb; |
66 | |||
67 | /* for handling page flips without caring about what | ||
68 | * the callback is called from. Possibly we should just | ||
69 | * make omap_gem always call the cb from the worker so | ||
70 | * we don't have to care about this.. | ||
71 | * | ||
72 | * XXX maybe fold into apply_work?? | ||
73 | */ | ||
74 | struct work_struct page_flip_work; | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * Manager-ops, callbacks from output when they need to configure | ||
79 | * the upstream part of the video pipe. | ||
80 | * | ||
81 | * Most of these we can ignore until we add support for command-mode | ||
82 | * panels.. for video-mode the crtc-helpers already do an adequate | ||
83 | * job of sequencing the setup of the video pipe in the proper order | ||
84 | */ | ||
85 | |||
86 | /* we can probably ignore these until we support command-mode panels: */ | ||
87 | static void omap_crtc_start_update(struct omap_overlay_manager *mgr) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | static int omap_crtc_enable(struct omap_overlay_manager *mgr) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static void omap_crtc_disable(struct omap_overlay_manager *mgr) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, | ||
101 | const struct omap_video_timings *timings) | ||
102 | { | ||
103 | struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); | ||
104 | DBG("%s", omap_crtc->name); | ||
105 | omap_crtc->timings = *timings; | ||
106 | omap_crtc->full_update = true; | ||
107 | } | ||
108 | |||
109 | static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr, | ||
110 | const struct dss_lcd_mgr_config *config) | ||
111 | { | ||
112 | struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); | ||
113 | DBG("%s", omap_crtc->name); | ||
114 | dispc_mgr_set_lcd_config(omap_crtc->channel, config); | ||
115 | } | ||
116 | |||
117 | static int omap_crtc_register_framedone_handler( | ||
118 | struct omap_overlay_manager *mgr, | ||
119 | void (*handler)(void *), void *data) | ||
120 | { | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void omap_crtc_unregister_framedone_handler( | ||
125 | struct omap_overlay_manager *mgr, | ||
126 | void (*handler)(void *), void *data) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | static const struct dss_mgr_ops mgr_ops = { | ||
131 | .start_update = omap_crtc_start_update, | ||
132 | .enable = omap_crtc_enable, | ||
133 | .disable = omap_crtc_disable, | ||
134 | .set_timings = omap_crtc_set_timings, | ||
135 | .set_lcd_config = omap_crtc_set_lcd_config, | ||
136 | .register_framedone_handler = omap_crtc_register_framedone_handler, | ||
137 | .unregister_framedone_handler = omap_crtc_unregister_framedone_handler, | ||
37 | }; | 138 | }; |
38 | 139 | ||
140 | /* | ||
141 | * CRTC funcs: | ||
142 | */ | ||
143 | |||
39 | static void omap_crtc_destroy(struct drm_crtc *crtc) | 144 | static void omap_crtc_destroy(struct drm_crtc *crtc) |
40 | { | 145 | { |
41 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 146 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
147 | |||
148 | DBG("%s", omap_crtc->name); | ||
149 | |||
150 | WARN_ON(omap_crtc->apply_irq.registered); | ||
151 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
152 | |||
42 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); | 153 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); |
43 | drm_crtc_cleanup(crtc); | 154 | drm_crtc_cleanup(crtc); |
155 | |||
44 | kfree(omap_crtc); | 156 | kfree(omap_crtc); |
45 | } | 157 | } |
46 | 158 | ||
@@ -48,14 +160,25 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
48 | { | 160 | { |
49 | struct omap_drm_private *priv = crtc->dev->dev_private; | 161 | struct omap_drm_private *priv = crtc->dev->dev_private; |
50 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 162 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
163 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
51 | int i; | 164 | int i; |
52 | 165 | ||
53 | WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); | 166 | DBG("%s: %d", omap_crtc->name, mode); |
167 | |||
168 | if (enabled != omap_crtc->enabled) { | ||
169 | omap_crtc->enabled = enabled; | ||
170 | omap_crtc->full_update = true; | ||
171 | omap_crtc_apply(crtc, &omap_crtc->apply); | ||
54 | 172 | ||
55 | for (i = 0; i < priv->num_planes; i++) { | 173 | /* also enable our private plane: */ |
56 | struct drm_plane *plane = priv->planes[i]; | 174 | WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); |
57 | if (plane->crtc == crtc) | 175 | |
58 | WARN_ON(omap_plane_dpms(plane, mode)); | 176 | /* and any attached overlay planes: */ |
177 | for (i = 0; i < priv->num_planes; i++) { | ||
178 | struct drm_plane *plane = priv->planes[i]; | ||
179 | if (plane->crtc == crtc) | ||
180 | WARN_ON(omap_plane_dpms(plane, mode)); | ||
181 | } | ||
59 | } | 182 | } |
60 | } | 183 | } |
61 | 184 | ||
@@ -73,12 +196,26 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc, | |||
73 | struct drm_framebuffer *old_fb) | 196 | struct drm_framebuffer *old_fb) |
74 | { | 197 | { |
75 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 198 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
76 | struct drm_plane *plane = omap_crtc->plane; | ||
77 | 199 | ||
78 | return omap_plane_mode_set(plane, crtc, crtc->fb, | 200 | mode = adjusted_mode; |
201 | |||
202 | DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", | ||
203 | omap_crtc->name, mode->base.id, mode->name, | ||
204 | mode->vrefresh, mode->clock, | ||
205 | mode->hdisplay, mode->hsync_start, | ||
206 | mode->hsync_end, mode->htotal, | ||
207 | mode->vdisplay, mode->vsync_start, | ||
208 | mode->vsync_end, mode->vtotal, | ||
209 | mode->type, mode->flags); | ||
210 | |||
211 | copy_timings_drm_to_omap(&omap_crtc->timings, mode); | ||
212 | omap_crtc->full_update = true; | ||
213 | |||
214 | return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, | ||
79 | 0, 0, mode->hdisplay, mode->vdisplay, | 215 | 0, 0, mode->hdisplay, mode->vdisplay, |
80 | x << 16, y << 16, | 216 | x << 16, y << 16, |
81 | mode->hdisplay << 16, mode->vdisplay << 16); | 217 | mode->hdisplay << 16, mode->vdisplay << 16, |
218 | NULL, NULL); | ||
82 | } | 219 | } |
83 | 220 | ||
84 | static void omap_crtc_prepare(struct drm_crtc *crtc) | 221 | static void omap_crtc_prepare(struct drm_crtc *crtc) |
@@ -102,10 +239,11 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
102 | struct drm_plane *plane = omap_crtc->plane; | 239 | struct drm_plane *plane = omap_crtc->plane; |
103 | struct drm_display_mode *mode = &crtc->mode; | 240 | struct drm_display_mode *mode = &crtc->mode; |
104 | 241 | ||
105 | return plane->funcs->update_plane(plane, crtc, crtc->fb, | 242 | return omap_plane_mode_set(plane, crtc, crtc->fb, |
106 | 0, 0, mode->hdisplay, mode->vdisplay, | 243 | 0, 0, mode->hdisplay, mode->vdisplay, |
107 | x << 16, y << 16, | 244 | x << 16, y << 16, |
108 | mode->hdisplay << 16, mode->vdisplay << 16); | 245 | mode->hdisplay << 16, mode->vdisplay << 16, |
246 | NULL, NULL); | ||
109 | } | 247 | } |
110 | 248 | ||
111 | static void omap_crtc_load_lut(struct drm_crtc *crtc) | 249 | static void omap_crtc_load_lut(struct drm_crtc *crtc) |
@@ -114,63 +252,54 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc) | |||
114 | 252 | ||
115 | static void vblank_cb(void *arg) | 253 | static void vblank_cb(void *arg) |
116 | { | 254 | { |
117 | static uint32_t sequence; | ||
118 | struct drm_crtc *crtc = arg; | 255 | struct drm_crtc *crtc = arg; |
119 | struct drm_device *dev = crtc->dev; | 256 | struct drm_device *dev = crtc->dev; |
120 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 257 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
121 | struct drm_pending_vblank_event *event = omap_crtc->event; | ||
122 | unsigned long flags; | 258 | unsigned long flags; |
123 | struct timeval now; | ||
124 | 259 | ||
125 | WARN_ON(!event); | 260 | spin_lock_irqsave(&dev->event_lock, flags); |
261 | |||
262 | /* wakeup userspace */ | ||
263 | if (omap_crtc->event) | ||
264 | drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event); | ||
126 | 265 | ||
127 | omap_crtc->event = NULL; | 266 | omap_crtc->event = NULL; |
267 | omap_crtc->old_fb = NULL; | ||
128 | 268 | ||
129 | /* wakeup userspace */ | 269 | spin_unlock_irqrestore(&dev->event_lock, flags); |
130 | if (event) { | ||
131 | do_gettimeofday(&now); | ||
132 | |||
133 | spin_lock_irqsave(&dev->event_lock, flags); | ||
134 | /* TODO: we can't yet use the vblank time accounting, | ||
135 | * because omapdss lower layer is the one that knows | ||
136 | * the irq # and registers the handler, which more or | ||
137 | * less defeats how drm_irq works.. for now just fake | ||
138 | * the sequence number and use gettimeofday.. | ||
139 | * | ||
140 | event->event.sequence = drm_vblank_count_and_time( | ||
141 | dev, omap_crtc->id, &now); | ||
142 | */ | ||
143 | event->event.sequence = sequence++; | ||
144 | event->event.tv_sec = now.tv_sec; | ||
145 | event->event.tv_usec = now.tv_usec; | ||
146 | list_add_tail(&event->base.link, | ||
147 | &event->base.file_priv->event_list); | ||
148 | wake_up_interruptible(&event->base.file_priv->event_wait); | ||
149 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
150 | } | ||
151 | } | 270 | } |
152 | 271 | ||
153 | static void page_flip_cb(void *arg) | 272 | static void page_flip_worker(struct work_struct *work) |
154 | { | 273 | { |
155 | struct drm_crtc *crtc = arg; | 274 | struct omap_crtc *omap_crtc = |
156 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 275 | container_of(work, struct omap_crtc, page_flip_work); |
157 | struct drm_framebuffer *old_fb = omap_crtc->old_fb; | 276 | struct drm_crtc *crtc = &omap_crtc->base; |
277 | struct drm_device *dev = crtc->dev; | ||
278 | struct drm_display_mode *mode = &crtc->mode; | ||
158 | struct drm_gem_object *bo; | 279 | struct drm_gem_object *bo; |
159 | 280 | ||
160 | omap_crtc->old_fb = NULL; | 281 | mutex_lock(&dev->mode_config.mutex); |
161 | 282 | omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, | |
162 | omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); | 283 | 0, 0, mode->hdisplay, mode->vdisplay, |
163 | 284 | crtc->x << 16, crtc->y << 16, | |
164 | /* really we'd like to setup the callback atomically w/ setting the | 285 | mode->hdisplay << 16, mode->vdisplay << 16, |
165 | * new scanout buffer to avoid getting stuck waiting an extra vblank | 286 | vblank_cb, crtc); |
166 | * cycle.. for now go for correctness and later figure out speed.. | 287 | mutex_unlock(&dev->mode_config.mutex); |
167 | */ | ||
168 | omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc); | ||
169 | 288 | ||
170 | bo = omap_framebuffer_bo(crtc->fb, 0); | 289 | bo = omap_framebuffer_bo(crtc->fb, 0); |
171 | drm_gem_object_unreference_unlocked(bo); | 290 | drm_gem_object_unreference_unlocked(bo); |
172 | } | 291 | } |
173 | 292 | ||
293 | static void page_flip_cb(void *arg) | ||
294 | { | ||
295 | struct drm_crtc *crtc = arg; | ||
296 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
297 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
298 | |||
299 | /* avoid assumptions about what ctxt we are called from: */ | ||
300 | queue_work(priv->wq, &omap_crtc->page_flip_work); | ||
301 | } | ||
302 | |||
174 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | 303 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, |
175 | struct drm_framebuffer *fb, | 304 | struct drm_framebuffer *fb, |
176 | struct drm_pending_vblank_event *event) | 305 | struct drm_pending_vblank_event *event) |
@@ -179,14 +308,14 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | |||
179 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 308 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
180 | struct drm_gem_object *bo; | 309 | struct drm_gem_object *bo; |
181 | 310 | ||
182 | DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id); | 311 | DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1, |
312 | fb->base.id, event); | ||
183 | 313 | ||
184 | if (omap_crtc->event) { | 314 | if (omap_crtc->old_fb) { |
185 | dev_err(dev->dev, "already a pending flip\n"); | 315 | dev_err(dev->dev, "already a pending flip\n"); |
186 | return -EINVAL; | 316 | return -EINVAL; |
187 | } | 317 | } |
188 | 318 | ||
189 | omap_crtc->old_fb = crtc->fb; | ||
190 | omap_crtc->event = event; | 319 | omap_crtc->event = event; |
191 | crtc->fb = fb; | 320 | crtc->fb = fb; |
192 | 321 | ||
@@ -234,14 +363,244 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { | |||
234 | .load_lut = omap_crtc_load_lut, | 363 | .load_lut = omap_crtc_load_lut, |
235 | }; | 364 | }; |
236 | 365 | ||
366 | const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc) | ||
367 | { | ||
368 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
369 | return &omap_crtc->timings; | ||
370 | } | ||
371 | |||
372 | enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) | ||
373 | { | ||
374 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
375 | return omap_crtc->channel; | ||
376 | } | ||
377 | |||
378 | static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
379 | { | ||
380 | struct omap_crtc *omap_crtc = | ||
381 | container_of(irq, struct omap_crtc, error_irq); | ||
382 | struct drm_crtc *crtc = &omap_crtc->base; | ||
383 | DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); | ||
384 | /* avoid getting in a flood, unregister the irq until next vblank */ | ||
385 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
386 | } | ||
387 | |||
388 | static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
389 | { | ||
390 | struct omap_crtc *omap_crtc = | ||
391 | container_of(irq, struct omap_crtc, apply_irq); | ||
392 | struct drm_crtc *crtc = &omap_crtc->base; | ||
393 | |||
394 | if (!omap_crtc->error_irq.registered) | ||
395 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | ||
396 | |||
397 | if (!dispc_mgr_go_busy(omap_crtc->channel)) { | ||
398 | struct omap_drm_private *priv = | ||
399 | crtc->dev->dev_private; | ||
400 | DBG("%s: apply done", omap_crtc->name); | ||
401 | omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); | ||
402 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | static void apply_worker(struct work_struct *work) | ||
407 | { | ||
408 | struct omap_crtc *omap_crtc = | ||
409 | container_of(work, struct omap_crtc, apply_work); | ||
410 | struct drm_crtc *crtc = &omap_crtc->base; | ||
411 | struct drm_device *dev = crtc->dev; | ||
412 | struct omap_drm_apply *apply, *n; | ||
413 | bool need_apply; | ||
414 | |||
415 | /* | ||
416 | * Synchronize everything on mode_config.mutex, to keep | ||
417 | * the callbacks and list modification all serialized | ||
418 | * with respect to modesetting ioctls from userspace. | ||
419 | */ | ||
420 | mutex_lock(&dev->mode_config.mutex); | ||
421 | dispc_runtime_get(); | ||
422 | |||
423 | /* | ||
424 | * If we are still pending a previous update, wait.. when the | ||
425 | * pending update completes, we get kicked again. | ||
426 | */ | ||
427 | if (omap_crtc->apply_irq.registered) | ||
428 | goto out; | ||
429 | |||
430 | /* finish up previous apply's: */ | ||
431 | list_for_each_entry_safe(apply, n, | ||
432 | &omap_crtc->pending_applies, pending_node) { | ||
433 | apply->post_apply(apply); | ||
434 | list_del(&apply->pending_node); | ||
435 | } | ||
436 | |||
437 | need_apply = !list_empty(&omap_crtc->queued_applies); | ||
438 | |||
439 | /* then handle the next round of of queued apply's: */ | ||
440 | list_for_each_entry_safe(apply, n, | ||
441 | &omap_crtc->queued_applies, queued_node) { | ||
442 | apply->pre_apply(apply); | ||
443 | list_del(&apply->queued_node); | ||
444 | apply->queued = false; | ||
445 | list_add_tail(&apply->pending_node, | ||
446 | &omap_crtc->pending_applies); | ||
447 | } | ||
448 | |||
449 | if (need_apply) { | ||
450 | enum omap_channel channel = omap_crtc->channel; | ||
451 | |||
452 | DBG("%s: GO", omap_crtc->name); | ||
453 | |||
454 | if (dispc_mgr_is_enabled(channel)) { | ||
455 | omap_irq_register(dev, &omap_crtc->apply_irq); | ||
456 | dispc_mgr_go(channel); | ||
457 | } else { | ||
458 | struct omap_drm_private *priv = dev->dev_private; | ||
459 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | out: | ||
464 | dispc_runtime_put(); | ||
465 | mutex_unlock(&dev->mode_config.mutex); | ||
466 | } | ||
467 | |||
468 | int omap_crtc_apply(struct drm_crtc *crtc, | ||
469 | struct omap_drm_apply *apply) | ||
470 | { | ||
471 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
472 | struct drm_device *dev = crtc->dev; | ||
473 | |||
474 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
475 | |||
476 | /* no need to queue it again if it is already queued: */ | ||
477 | if (apply->queued) | ||
478 | return 0; | ||
479 | |||
480 | apply->queued = true; | ||
481 | list_add_tail(&apply->queued_node, &omap_crtc->queued_applies); | ||
482 | |||
483 | /* | ||
484 | * If there are no currently pending updates, then go ahead and | ||
485 | * kick the worker immediately, otherwise it will run again when | ||
486 | * the current update finishes. | ||
487 | */ | ||
488 | if (list_empty(&omap_crtc->pending_applies)) { | ||
489 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
490 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | /* called only from apply */ | ||
497 | static void set_enabled(struct drm_crtc *crtc, bool enable) | ||
498 | { | ||
499 | struct drm_device *dev = crtc->dev; | ||
500 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
501 | enum omap_channel channel = omap_crtc->channel; | ||
502 | struct omap_irq_wait *wait = NULL; | ||
503 | |||
504 | if (dispc_mgr_is_enabled(channel) == enable) | ||
505 | return; | ||
506 | |||
507 | /* ignore sync-lost irqs during enable/disable */ | ||
508 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
509 | |||
510 | if (dispc_mgr_get_framedone_irq(channel)) { | ||
511 | if (!enable) { | ||
512 | wait = omap_irq_wait_init(dev, | ||
513 | dispc_mgr_get_framedone_irq(channel), 1); | ||
514 | } | ||
515 | } else { | ||
516 | /* | ||
517 | * When we disable digit output, we need to wait until fields | ||
518 | * are done. Otherwise the DSS is still working, and turning | ||
519 | * off the clocks prevents DSS from going to OFF mode. And when | ||
520 | * enabling, we need to wait for the extra sync losts | ||
521 | */ | ||
522 | wait = omap_irq_wait_init(dev, | ||
523 | dispc_mgr_get_vsync_irq(channel), 2); | ||
524 | } | ||
525 | |||
526 | dispc_mgr_enable(channel, enable); | ||
527 | |||
528 | if (wait) { | ||
529 | int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); | ||
530 | if (ret) { | ||
531 | dev_err(dev->dev, "%s: timeout waiting for %s\n", | ||
532 | omap_crtc->name, enable ? "enable" : "disable"); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | ||
537 | } | ||
538 | |||
539 | static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | ||
540 | { | ||
541 | struct omap_crtc *omap_crtc = | ||
542 | container_of(apply, struct omap_crtc, apply); | ||
543 | struct drm_crtc *crtc = &omap_crtc->base; | ||
544 | struct drm_encoder *encoder = NULL; | ||
545 | |||
546 | DBG("%s: enabled=%d, full=%d", omap_crtc->name, | ||
547 | omap_crtc->enabled, omap_crtc->full_update); | ||
548 | |||
549 | if (omap_crtc->full_update) { | ||
550 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
551 | int i; | ||
552 | for (i = 0; i < priv->num_encoders; i++) { | ||
553 | if (priv->encoders[i]->crtc == crtc) { | ||
554 | encoder = priv->encoders[i]; | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | if (!omap_crtc->enabled) { | ||
561 | set_enabled(&omap_crtc->base, false); | ||
562 | if (encoder) | ||
563 | omap_encoder_set_enabled(encoder, false); | ||
564 | } else { | ||
565 | if (encoder) { | ||
566 | omap_encoder_set_enabled(encoder, false); | ||
567 | omap_encoder_update(encoder, &omap_crtc->mgr, | ||
568 | &omap_crtc->timings); | ||
569 | omap_encoder_set_enabled(encoder, true); | ||
570 | omap_crtc->full_update = false; | ||
571 | } | ||
572 | |||
573 | dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); | ||
574 | dispc_mgr_set_timings(omap_crtc->channel, | ||
575 | &omap_crtc->timings); | ||
576 | set_enabled(&omap_crtc->base, true); | ||
577 | } | ||
578 | |||
579 | omap_crtc->full_update = false; | ||
580 | } | ||
581 | |||
582 | static void omap_crtc_post_apply(struct omap_drm_apply *apply) | ||
583 | { | ||
584 | /* nothing needed for post-apply */ | ||
585 | } | ||
586 | |||
587 | static const char *channel_names[] = { | ||
588 | [OMAP_DSS_CHANNEL_LCD] = "lcd", | ||
589 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", | ||
590 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", | ||
591 | }; | ||
592 | |||
237 | /* initialize crtc */ | 593 | /* initialize crtc */ |
238 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 594 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
239 | struct omap_overlay *ovl, int id) | 595 | struct drm_plane *plane, enum omap_channel channel, int id) |
240 | { | 596 | { |
241 | struct drm_crtc *crtc = NULL; | 597 | struct drm_crtc *crtc = NULL; |
242 | struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); | 598 | struct omap_crtc *omap_crtc; |
599 | struct omap_overlay_manager_info *info; | ||
600 | |||
601 | DBG("%s", channel_names[channel]); | ||
243 | 602 | ||
244 | DBG("%s", ovl->name); | 603 | omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); |
245 | 604 | ||
246 | if (!omap_crtc) { | 605 | if (!omap_crtc) { |
247 | dev_err(dev->dev, "could not allocate CRTC\n"); | 606 | dev_err(dev->dev, "could not allocate CRTC\n"); |
@@ -250,10 +609,40 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, | |||
250 | 609 | ||
251 | crtc = &omap_crtc->base; | 610 | crtc = &omap_crtc->base; |
252 | 611 | ||
253 | omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true); | 612 | INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker); |
613 | INIT_WORK(&omap_crtc->apply_work, apply_worker); | ||
614 | |||
615 | INIT_LIST_HEAD(&omap_crtc->pending_applies); | ||
616 | INIT_LIST_HEAD(&omap_crtc->queued_applies); | ||
617 | |||
618 | omap_crtc->apply.pre_apply = omap_crtc_pre_apply; | ||
619 | omap_crtc->apply.post_apply = omap_crtc_post_apply; | ||
620 | |||
621 | omap_crtc->apply_irq.irqmask = pipe2vbl(id); | ||
622 | omap_crtc->apply_irq.irq = omap_crtc_apply_irq; | ||
623 | |||
624 | omap_crtc->error_irq.irqmask = | ||
625 | dispc_mgr_get_sync_lost_irq(channel); | ||
626 | omap_crtc->error_irq.irq = omap_crtc_error_irq; | ||
627 | omap_irq_register(dev, &omap_crtc->error_irq); | ||
628 | |||
629 | omap_crtc->channel = channel; | ||
630 | omap_crtc->plane = plane; | ||
254 | omap_crtc->plane->crtc = crtc; | 631 | omap_crtc->plane->crtc = crtc; |
255 | omap_crtc->name = ovl->name; | 632 | omap_crtc->name = channel_names[channel]; |
256 | omap_crtc->id = id; | 633 | omap_crtc->pipe = id; |
634 | |||
635 | /* temporary: */ | ||
636 | omap_crtc->mgr.id = channel; | ||
637 | |||
638 | dss_install_mgr_ops(&mgr_ops); | ||
639 | |||
640 | /* TODO: fix hard-coded setup.. add properties! */ | ||
641 | info = &omap_crtc->info; | ||
642 | info->default_color = 0x00000000; | ||
643 | info->trans_key = 0x00000000; | ||
644 | info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
645 | info->trans_enabled = false; | ||
257 | 646 | ||
258 | drm_crtc_init(dev, crtc, &omap_crtc_funcs); | 647 | drm_crtc_init(dev, crtc, &omap_crtc_funcs); |
259 | drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); | 648 | drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); |
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 84943e5ba1d6..ae5ecc2efbc7 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c | |||
@@ -74,320 +74,99 @@ static int get_connector_type(struct omap_dss_device *dssdev) | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | #if 0 /* enable when dss2 supports hotplug */ | 77 | static int omap_modeset_init(struct drm_device *dev) |
78 | static int omap_drm_notifier(struct notifier_block *nb, | ||
79 | unsigned long evt, void *arg) | ||
80 | { | ||
81 | switch (evt) { | ||
82 | case OMAP_DSS_SIZE_CHANGE: | ||
83 | case OMAP_DSS_HOTPLUG_CONNECT: | ||
84 | case OMAP_DSS_HOTPLUG_DISCONNECT: { | ||
85 | struct drm_device *dev = drm_device; | ||
86 | DBG("hotplug event: evt=%d, dev=%p", evt, dev); | ||
87 | if (dev) | ||
88 | drm_sysfs_hotplug_event(dev); | ||
89 | |||
90 | return NOTIFY_OK; | ||
91 | } | ||
92 | default: /* don't care about other events for now */ | ||
93 | return NOTIFY_DONE; | ||
94 | } | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | static void dump_video_chains(void) | ||
99 | { | ||
100 | int i; | ||
101 | |||
102 | DBG("dumping video chains: "); | ||
103 | for (i = 0; i < omap_dss_get_num_overlays(); i++) { | ||
104 | struct omap_overlay *ovl = omap_dss_get_overlay(i); | ||
105 | struct omap_overlay_manager *mgr = ovl->manager; | ||
106 | struct omap_dss_device *dssdev = mgr ? | ||
107 | mgr->get_device(mgr) : NULL; | ||
108 | if (dssdev) { | ||
109 | DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name, | ||
110 | dssdev->name); | ||
111 | } else if (mgr) { | ||
112 | DBG("%d: %s -> %s", i, ovl->name, mgr->name); | ||
113 | } else { | ||
114 | DBG("%d: %s", i, ovl->name); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* create encoders for each manager */ | ||
120 | static int create_encoder(struct drm_device *dev, | ||
121 | struct omap_overlay_manager *mgr) | ||
122 | { | ||
123 | struct omap_drm_private *priv = dev->dev_private; | ||
124 | struct drm_encoder *encoder = omap_encoder_init(dev, mgr); | ||
125 | |||
126 | if (!encoder) { | ||
127 | dev_err(dev->dev, "could not create encoder: %s\n", | ||
128 | mgr->name); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | |||
132 | BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); | ||
133 | |||
134 | priv->encoders[priv->num_encoders++] = encoder; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /* create connectors for each display device */ | ||
140 | static int create_connector(struct drm_device *dev, | ||
141 | struct omap_dss_device *dssdev) | ||
142 | { | 78 | { |
143 | struct omap_drm_private *priv = dev->dev_private; | 79 | struct omap_drm_private *priv = dev->dev_private; |
144 | static struct notifier_block *notifier; | 80 | struct omap_dss_device *dssdev = NULL; |
145 | struct drm_connector *connector; | 81 | int num_ovls = dss_feat_get_num_ovls(); |
146 | int j; | 82 | int id; |
147 | |||
148 | if (!dssdev->driver) { | ||
149 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
150 | dssdev->name); | ||
151 | return 0; | ||
152 | } | ||
153 | 83 | ||
154 | if (!(dssdev->driver->get_timings || | 84 | drm_mode_config_init(dev); |
155 | dssdev->driver->read_edid)) { | ||
156 | dev_warn(dev->dev, "%s driver does not support " | ||
157 | "get_timings or read_edid.. skipping it!\n", | ||
158 | dssdev->name); | ||
159 | return 0; | ||
160 | } | ||
161 | 85 | ||
162 | connector = omap_connector_init(dev, | 86 | omap_drm_irq_install(dev); |
163 | get_connector_type(dssdev), dssdev); | ||
164 | 87 | ||
165 | if (!connector) { | 88 | /* |
166 | dev_err(dev->dev, "could not create connector: %s\n", | 89 | * Create private planes and CRTCs for the last NUM_CRTCs overlay |
167 | dssdev->name); | 90 | * plus manager: |
168 | return -ENOMEM; | 91 | */ |
169 | } | 92 | for (id = 0; id < min(num_crtc, num_ovls); id++) { |
170 | 93 | struct drm_plane *plane; | |
171 | BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); | 94 | struct drm_crtc *crtc; |
172 | 95 | ||
173 | priv->connectors[priv->num_connectors++] = connector; | 96 | plane = omap_plane_init(dev, id, true); |
97 | crtc = omap_crtc_init(dev, plane, pipe2chan(id), id); | ||
174 | 98 | ||
175 | #if 0 /* enable when dss2 supports hotplug */ | 99 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); |
176 | notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); | 100 | priv->crtcs[id] = crtc; |
177 | notifier->notifier_call = omap_drm_notifier; | 101 | priv->num_crtcs++; |
178 | omap_dss_add_notify(dssdev, notifier); | ||
179 | #else | ||
180 | notifier = NULL; | ||
181 | #endif | ||
182 | 102 | ||
183 | for (j = 0; j < priv->num_encoders; j++) { | 103 | priv->planes[id] = plane; |
184 | struct omap_overlay_manager *mgr = | 104 | priv->num_planes++; |
185 | omap_encoder_get_manager(priv->encoders[j]); | ||
186 | if (mgr->get_device(mgr) == dssdev) { | ||
187 | drm_mode_connector_attach_encoder(connector, | ||
188 | priv->encoders[j]); | ||
189 | } | ||
190 | } | 105 | } |
191 | 106 | ||
192 | return 0; | 107 | /* |
193 | } | 108 | * Create normal planes for the remaining overlays: |
194 | |||
195 | /* create up to max_overlays CRTCs mapping to overlays.. by default, | ||
196 | * connect the overlays to different managers/encoders, giving priority | ||
197 | * to encoders connected to connectors with a detected connection | ||
198 | */ | ||
199 | static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl, | ||
200 | int *j, unsigned int connected_connectors) | ||
201 | { | ||
202 | struct omap_drm_private *priv = dev->dev_private; | ||
203 | struct omap_overlay_manager *mgr = NULL; | ||
204 | struct drm_crtc *crtc; | ||
205 | |||
206 | /* find next best connector, ones with detected connection first | ||
207 | */ | 109 | */ |
208 | while (*j < priv->num_connectors && !mgr) { | 110 | for (; id < num_ovls; id++) { |
209 | if (connected_connectors & (1 << *j)) { | 111 | struct drm_plane *plane = omap_plane_init(dev, id, false); |
210 | struct drm_encoder *encoder = | ||
211 | omap_connector_attached_encoder( | ||
212 | priv->connectors[*j]); | ||
213 | if (encoder) | ||
214 | mgr = omap_encoder_get_manager(encoder); | ||
215 | 112 | ||
216 | } | 113 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); |
217 | (*j)++; | 114 | priv->planes[priv->num_planes++] = plane; |
218 | } | 115 | } |
219 | 116 | ||
220 | /* if we couldn't find another connected connector, lets start | 117 | for_each_dss_dev(dssdev) { |
221 | * looking at the unconnected connectors: | 118 | struct drm_connector *connector; |
222 | * | 119 | struct drm_encoder *encoder; |
223 | * note: it might not be immediately apparent, but thanks to | ||
224 | * the !mgr check in both this loop and the one above, the only | ||
225 | * way to enter this loop is with *j == priv->num_connectors, | ||
226 | * so idx can never go negative. | ||
227 | */ | ||
228 | while (*j < 2 * priv->num_connectors && !mgr) { | ||
229 | int idx = *j - priv->num_connectors; | ||
230 | if (!(connected_connectors & (1 << idx))) { | ||
231 | struct drm_encoder *encoder = | ||
232 | omap_connector_attached_encoder( | ||
233 | priv->connectors[idx]); | ||
234 | if (encoder) | ||
235 | mgr = omap_encoder_get_manager(encoder); | ||
236 | 120 | ||
121 | if (!dssdev->driver) { | ||
122 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
123 | dssdev->name); | ||
124 | return 0; | ||
237 | } | 125 | } |
238 | (*j)++; | ||
239 | } | ||
240 | |||
241 | crtc = omap_crtc_init(dev, ovl, priv->num_crtcs); | ||
242 | |||
243 | if (!crtc) { | ||
244 | dev_err(dev->dev, "could not create CRTC: %s\n", | ||
245 | ovl->name); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | 126 | ||
249 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); | 127 | if (!(dssdev->driver->get_timings || |
250 | 128 | dssdev->driver->read_edid)) { | |
251 | priv->crtcs[priv->num_crtcs++] = crtc; | 129 | dev_warn(dev->dev, "%s driver does not support " |
252 | 130 | "get_timings or read_edid.. skipping it!\n", | |
253 | return 0; | 131 | dssdev->name); |
254 | } | 132 | return 0; |
255 | |||
256 | static int create_plane(struct drm_device *dev, struct omap_overlay *ovl, | ||
257 | unsigned int possible_crtcs) | ||
258 | { | ||
259 | struct omap_drm_private *priv = dev->dev_private; | ||
260 | struct drm_plane *plane = | ||
261 | omap_plane_init(dev, ovl, possible_crtcs, false); | ||
262 | |||
263 | if (!plane) { | ||
264 | dev_err(dev->dev, "could not create plane: %s\n", | ||
265 | ovl->name); | ||
266 | return -ENOMEM; | ||
267 | } | ||
268 | |||
269 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); | ||
270 | |||
271 | priv->planes[priv->num_planes++] = plane; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int match_dev_name(struct omap_dss_device *dssdev, void *data) | ||
277 | { | ||
278 | return !strcmp(dssdev->name, data); | ||
279 | } | ||
280 | |||
281 | static unsigned int detect_connectors(struct drm_device *dev) | ||
282 | { | ||
283 | struct omap_drm_private *priv = dev->dev_private; | ||
284 | unsigned int connected_connectors = 0; | ||
285 | int i; | ||
286 | |||
287 | for (i = 0; i < priv->num_connectors; i++) { | ||
288 | struct drm_connector *connector = priv->connectors[i]; | ||
289 | if (omap_connector_detect(connector, true) == | ||
290 | connector_status_connected) { | ||
291 | connected_connectors |= (1 << i); | ||
292 | } | 133 | } |
293 | } | ||
294 | |||
295 | return connected_connectors; | ||
296 | } | ||
297 | 134 | ||
298 | static int omap_modeset_init(struct drm_device *dev) | 135 | encoder = omap_encoder_init(dev, dssdev); |
299 | { | ||
300 | const struct omap_drm_platform_data *pdata = dev->dev->platform_data; | ||
301 | struct omap_kms_platform_data *kms_pdata = NULL; | ||
302 | struct omap_drm_private *priv = dev->dev_private; | ||
303 | struct omap_dss_device *dssdev = NULL; | ||
304 | int i, j; | ||
305 | unsigned int connected_connectors = 0; | ||
306 | 136 | ||
307 | drm_mode_config_init(dev); | 137 | if (!encoder) { |
308 | 138 | dev_err(dev->dev, "could not create encoder: %s\n", | |
309 | if (pdata && pdata->kms_pdata) { | 139 | dssdev->name); |
310 | kms_pdata = pdata->kms_pdata; | 140 | return -ENOMEM; |
311 | |||
312 | /* if platform data is provided by the board file, use it to | ||
313 | * control which overlays, managers, and devices we own. | ||
314 | */ | ||
315 | for (i = 0; i < kms_pdata->mgr_cnt; i++) { | ||
316 | struct omap_overlay_manager *mgr = | ||
317 | omap_dss_get_overlay_manager( | ||
318 | kms_pdata->mgr_ids[i]); | ||
319 | create_encoder(dev, mgr); | ||
320 | } | ||
321 | |||
322 | for (i = 0; i < kms_pdata->dev_cnt; i++) { | ||
323 | struct omap_dss_device *dssdev = | ||
324 | omap_dss_find_device( | ||
325 | (void *)kms_pdata->dev_names[i], | ||
326 | match_dev_name); | ||
327 | if (!dssdev) { | ||
328 | dev_warn(dev->dev, "no such dssdev: %s\n", | ||
329 | kms_pdata->dev_names[i]); | ||
330 | continue; | ||
331 | } | ||
332 | create_connector(dev, dssdev); | ||
333 | } | 141 | } |
334 | 142 | ||
335 | connected_connectors = detect_connectors(dev); | 143 | connector = omap_connector_init(dev, |
144 | get_connector_type(dssdev), dssdev, encoder); | ||
336 | 145 | ||
337 | j = 0; | 146 | if (!connector) { |
338 | for (i = 0; i < kms_pdata->ovl_cnt; i++) { | 147 | dev_err(dev->dev, "could not create connector: %s\n", |
339 | struct omap_overlay *ovl = | 148 | dssdev->name); |
340 | omap_dss_get_overlay(kms_pdata->ovl_ids[i]); | 149 | return -ENOMEM; |
341 | create_crtc(dev, ovl, &j, connected_connectors); | ||
342 | } | 150 | } |
343 | 151 | ||
344 | for (i = 0; i < kms_pdata->pln_cnt; i++) { | 152 | BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); |
345 | struct omap_overlay *ovl = | 153 | BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); |
346 | omap_dss_get_overlay(kms_pdata->pln_ids[i]); | ||
347 | create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); | ||
348 | } | ||
349 | } else { | ||
350 | /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try | ||
351 | * to make educated guesses about everything else | ||
352 | */ | ||
353 | int max_overlays = min(omap_dss_get_num_overlays(), num_crtc); | ||
354 | 154 | ||
355 | for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) | 155 | priv->encoders[priv->num_encoders++] = encoder; |
356 | create_encoder(dev, omap_dss_get_overlay_manager(i)); | 156 | priv->connectors[priv->num_connectors++] = connector; |
357 | |||
358 | for_each_dss_dev(dssdev) { | ||
359 | create_connector(dev, dssdev); | ||
360 | } | ||
361 | 157 | ||
362 | connected_connectors = detect_connectors(dev); | 158 | drm_mode_connector_attach_encoder(connector, encoder); |
363 | 159 | ||
364 | j = 0; | 160 | /* figure out which crtc's we can connect the encoder to: */ |
365 | for (i = 0; i < max_overlays; i++) { | 161 | encoder->possible_crtcs = 0; |
366 | create_crtc(dev, omap_dss_get_overlay(i), | 162 | for (id = 0; id < priv->num_crtcs; id++) { |
367 | &j, connected_connectors); | 163 | enum omap_dss_output_id supported_outputs = |
368 | } | 164 | dss_feat_get_supported_outputs(pipe2chan(id)); |
369 | 165 | if (supported_outputs & dssdev->output->id) | |
370 | /* use any remaining overlays as drm planes */ | 166 | encoder->possible_crtcs |= (1 << id); |
371 | for (; i < omap_dss_get_num_overlays(); i++) { | ||
372 | struct omap_overlay *ovl = omap_dss_get_overlay(i); | ||
373 | create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); | ||
374 | } | 167 | } |
375 | } | 168 | } |
376 | 169 | ||
377 | /* for now keep the mapping of CRTCs and encoders static.. */ | ||
378 | for (i = 0; i < priv->num_encoders; i++) { | ||
379 | struct drm_encoder *encoder = priv->encoders[i]; | ||
380 | struct omap_overlay_manager *mgr = | ||
381 | omap_encoder_get_manager(encoder); | ||
382 | |||
383 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; | ||
384 | |||
385 | DBG("%s: possible_crtcs=%08x", mgr->name, | ||
386 | encoder->possible_crtcs); | ||
387 | } | ||
388 | |||
389 | dump_video_chains(); | ||
390 | |||
391 | dev->mode_config.min_width = 32; | 170 | dev->mode_config.min_width = 32; |
392 | dev->mode_config.min_height = 32; | 171 | dev->mode_config.min_height = 32; |
393 | 172 | ||
@@ -450,7 +229,7 @@ static int ioctl_gem_new(struct drm_device *dev, void *data, | |||
450 | struct drm_file *file_priv) | 229 | struct drm_file *file_priv) |
451 | { | 230 | { |
452 | struct drm_omap_gem_new *args = data; | 231 | struct drm_omap_gem_new *args = data; |
453 | DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, | 232 | VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, |
454 | args->size.bytes, args->flags); | 233 | args->size.bytes, args->flags); |
455 | return omap_gem_new_handle(dev, file_priv, args->size, | 234 | return omap_gem_new_handle(dev, file_priv, args->size, |
456 | args->flags, &args->handle); | 235 | args->flags, &args->handle); |
@@ -510,7 +289,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, | |||
510 | struct drm_gem_object *obj; | 289 | struct drm_gem_object *obj; |
511 | int ret = 0; | 290 | int ret = 0; |
512 | 291 | ||
513 | DBG("%p:%p: handle=%d", dev, file_priv, args->handle); | 292 | VERB("%p:%p: handle=%d", dev, file_priv, args->handle); |
514 | 293 | ||
515 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 294 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
516 | if (!obj) | 295 | if (!obj) |
@@ -565,14 +344,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
565 | 344 | ||
566 | dev->dev_private = priv; | 345 | dev->dev_private = priv; |
567 | 346 | ||
568 | ret = omapdss_compat_init(); | ||
569 | if (ret) { | ||
570 | dev_err(dev->dev, "coult not init omapdss\n"); | ||
571 | dev->dev_private = NULL; | ||
572 | kfree(priv); | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | 347 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
577 | 348 | ||
578 | INIT_LIST_HEAD(&priv->obj_list); | 349 | INIT_LIST_HEAD(&priv->obj_list); |
@@ -584,10 +355,13 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
584 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); | 355 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); |
585 | dev->dev_private = NULL; | 356 | dev->dev_private = NULL; |
586 | kfree(priv); | 357 | kfree(priv); |
587 | omapdss_compat_uninit(); | ||
588 | return ret; | 358 | return ret; |
589 | } | 359 | } |
590 | 360 | ||
361 | ret = drm_vblank_init(dev, priv->num_crtcs); | ||
362 | if (ret) | ||
363 | dev_warn(dev->dev, "could not init vblank\n"); | ||
364 | |||
591 | priv->fbdev = omap_fbdev_init(dev); | 365 | priv->fbdev = omap_fbdev_init(dev); |
592 | if (!priv->fbdev) { | 366 | if (!priv->fbdev) { |
593 | dev_warn(dev->dev, "omap_fbdev_init failed\n"); | 367 | dev_warn(dev->dev, "omap_fbdev_init failed\n"); |
@@ -596,10 +370,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
596 | 370 | ||
597 | drm_kms_helper_poll_init(dev); | 371 | drm_kms_helper_poll_init(dev); |
598 | 372 | ||
599 | ret = drm_vblank_init(dev, priv->num_crtcs); | ||
600 | if (ret) | ||
601 | dev_warn(dev->dev, "could not init vblank\n"); | ||
602 | |||
603 | return 0; | 373 | return 0; |
604 | } | 374 | } |
605 | 375 | ||
@@ -609,8 +379,9 @@ static int dev_unload(struct drm_device *dev) | |||
609 | 379 | ||
610 | DBG("unload: dev=%p", dev); | 380 | DBG("unload: dev=%p", dev); |
611 | 381 | ||
612 | drm_vblank_cleanup(dev); | ||
613 | drm_kms_helper_poll_fini(dev); | 382 | drm_kms_helper_poll_fini(dev); |
383 | drm_vblank_cleanup(dev); | ||
384 | omap_drm_irq_uninstall(dev); | ||
614 | 385 | ||
615 | omap_fbdev_free(dev); | 386 | omap_fbdev_free(dev); |
616 | omap_modeset_free(dev); | 387 | omap_modeset_free(dev); |
@@ -619,8 +390,6 @@ static int dev_unload(struct drm_device *dev) | |||
619 | flush_workqueue(priv->wq); | 390 | flush_workqueue(priv->wq); |
620 | destroy_workqueue(priv->wq); | 391 | destroy_workqueue(priv->wq); |
621 | 392 | ||
622 | omapdss_compat_uninit(); | ||
623 | |||
624 | kfree(dev->dev_private); | 393 | kfree(dev->dev_private); |
625 | dev->dev_private = NULL; | 394 | dev->dev_private = NULL; |
626 | 395 | ||
@@ -680,7 +449,9 @@ static void dev_lastclose(struct drm_device *dev) | |||
680 | } | 449 | } |
681 | } | 450 | } |
682 | 451 | ||
452 | mutex_lock(&dev->mode_config.mutex); | ||
683 | ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); | 453 | ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); |
454 | mutex_unlock(&dev->mode_config.mutex); | ||
684 | if (ret) | 455 | if (ret) |
685 | DBG("failed to restore crtc mode"); | 456 | DBG("failed to restore crtc mode"); |
686 | } | 457 | } |
@@ -695,60 +466,6 @@ static void dev_postclose(struct drm_device *dev, struct drm_file *file) | |||
695 | DBG("postclose: dev=%p, file=%p", dev, file); | 466 | DBG("postclose: dev=%p, file=%p", dev, file); |
696 | } | 467 | } |
697 | 468 | ||
698 | /** | ||
699 | * enable_vblank - enable vblank interrupt events | ||
700 | * @dev: DRM device | ||
701 | * @crtc: which irq to enable | ||
702 | * | ||
703 | * Enable vblank interrupts for @crtc. If the device doesn't have | ||
704 | * a hardware vblank counter, this routine should be a no-op, since | ||
705 | * interrupts will have to stay on to keep the count accurate. | ||
706 | * | ||
707 | * RETURNS | ||
708 | * Zero on success, appropriate errno if the given @crtc's vblank | ||
709 | * interrupt cannot be enabled. | ||
710 | */ | ||
711 | static int dev_enable_vblank(struct drm_device *dev, int crtc) | ||
712 | { | ||
713 | DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * disable_vblank - disable vblank interrupt events | ||
719 | * @dev: DRM device | ||
720 | * @crtc: which irq to enable | ||
721 | * | ||
722 | * Disable vblank interrupts for @crtc. If the device doesn't have | ||
723 | * a hardware vblank counter, this routine should be a no-op, since | ||
724 | * interrupts will have to stay on to keep the count accurate. | ||
725 | */ | ||
726 | static void dev_disable_vblank(struct drm_device *dev, int crtc) | ||
727 | { | ||
728 | DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc); | ||
729 | } | ||
730 | |||
731 | static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS) | ||
732 | { | ||
733 | return IRQ_HANDLED; | ||
734 | } | ||
735 | |||
736 | static void dev_irq_preinstall(struct drm_device *dev) | ||
737 | { | ||
738 | DBG("irq_preinstall: dev=%p", dev); | ||
739 | } | ||
740 | |||
741 | static int dev_irq_postinstall(struct drm_device *dev) | ||
742 | { | ||
743 | DBG("irq_postinstall: dev=%p", dev); | ||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static void dev_irq_uninstall(struct drm_device *dev) | ||
748 | { | ||
749 | DBG("irq_uninstall: dev=%p", dev); | ||
750 | } | ||
751 | |||
752 | static const struct vm_operations_struct omap_gem_vm_ops = { | 469 | static const struct vm_operations_struct omap_gem_vm_ops = { |
753 | .fault = omap_gem_fault, | 470 | .fault = omap_gem_fault, |
754 | .open = drm_gem_vm_open, | 471 | .open = drm_gem_vm_open, |
@@ -778,12 +495,12 @@ static struct drm_driver omap_drm_driver = { | |||
778 | .preclose = dev_preclose, | 495 | .preclose = dev_preclose, |
779 | .postclose = dev_postclose, | 496 | .postclose = dev_postclose, |
780 | .get_vblank_counter = drm_vblank_count, | 497 | .get_vblank_counter = drm_vblank_count, |
781 | .enable_vblank = dev_enable_vblank, | 498 | .enable_vblank = omap_irq_enable_vblank, |
782 | .disable_vblank = dev_disable_vblank, | 499 | .disable_vblank = omap_irq_disable_vblank, |
783 | .irq_preinstall = dev_irq_preinstall, | 500 | .irq_preinstall = omap_irq_preinstall, |
784 | .irq_postinstall = dev_irq_postinstall, | 501 | .irq_postinstall = omap_irq_postinstall, |
785 | .irq_uninstall = dev_irq_uninstall, | 502 | .irq_uninstall = omap_irq_uninstall, |
786 | .irq_handler = dev_irq_handler, | 503 | .irq_handler = omap_irq_handler, |
787 | #ifdef CONFIG_DEBUG_FS | 504 | #ifdef CONFIG_DEBUG_FS |
788 | .debugfs_init = omap_debugfs_init, | 505 | .debugfs_init = omap_debugfs_init, |
789 | .debugfs_cleanup = omap_debugfs_cleanup, | 506 | .debugfs_cleanup = omap_debugfs_cleanup, |
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index 1d4aea53b75d..cd1f22b0b124 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/platform_data/omap_drm.h> | 28 | #include <linux/platform_data/omap_drm.h> |
29 | #include "omap_drm.h" | 29 | #include "omap_drm.h" |
30 | 30 | ||
31 | |||
31 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) | 32 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) |
32 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */ | 33 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */ |
33 | 34 | ||
@@ -39,6 +40,51 @@ | |||
39 | */ | 40 | */ |
40 | #define MAX_MAPPERS 2 | 41 | #define MAX_MAPPERS 2 |
41 | 42 | ||
43 | /* parameters which describe (unrotated) coordinates of scanout within a fb: */ | ||
44 | struct omap_drm_window { | ||
45 | uint32_t rotation; | ||
46 | int32_t crtc_x, crtc_y; /* signed because can be offscreen */ | ||
47 | uint32_t crtc_w, crtc_h; | ||
48 | uint32_t src_x, src_y; | ||
49 | uint32_t src_w, src_h; | ||
50 | }; | ||
51 | |||
52 | /* Once GO bit is set, we can't make further updates to shadowed registers | ||
53 | * until the GO bit is cleared. So various parts in the kms code that need | ||
54 | * to update shadowed registers queue up a pair of callbacks, pre_apply | ||
55 | * which is called before setting GO bit, and post_apply that is called | ||
56 | * after GO bit is cleared. The crtc manages the queuing, and everyone | ||
57 | * else goes thru omap_crtc_apply() using these callbacks so that the | ||
58 | * code which has to deal w/ GO bit state is centralized. | ||
59 | */ | ||
60 | struct omap_drm_apply { | ||
61 | struct list_head pending_node, queued_node; | ||
62 | bool queued; | ||
63 | void (*pre_apply)(struct omap_drm_apply *apply); | ||
64 | void (*post_apply)(struct omap_drm_apply *apply); | ||
65 | }; | ||
66 | |||
67 | /* For transiently registering for different DSS irqs that various parts | ||
68 | * of the KMS code need during setup/configuration. We these are not | ||
69 | * necessarily the same as what drm_vblank_get/put() are requesting, and | ||
70 | * the hysteresis in drm_vblank_put() is not necessarily desirable for | ||
71 | * internal housekeeping related irq usage. | ||
72 | */ | ||
73 | struct omap_drm_irq { | ||
74 | struct list_head node; | ||
75 | uint32_t irqmask; | ||
76 | bool registered; | ||
77 | void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus); | ||
78 | }; | ||
79 | |||
80 | /* For KMS code that needs to wait for a certain # of IRQs: | ||
81 | */ | ||
82 | struct omap_irq_wait; | ||
83 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, | ||
84 | uint32_t irqmask, int count); | ||
85 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | ||
86 | unsigned long timeout); | ||
87 | |||
42 | struct omap_drm_private { | 88 | struct omap_drm_private { |
43 | uint32_t omaprev; | 89 | uint32_t omaprev; |
44 | 90 | ||
@@ -58,6 +104,7 @@ struct omap_drm_private { | |||
58 | 104 | ||
59 | struct workqueue_struct *wq; | 105 | struct workqueue_struct *wq; |
60 | 106 | ||
107 | /* list of GEM objects: */ | ||
61 | struct list_head obj_list; | 108 | struct list_head obj_list; |
62 | 109 | ||
63 | bool has_dmm; | 110 | bool has_dmm; |
@@ -65,6 +112,11 @@ struct omap_drm_private { | |||
65 | /* properties: */ | 112 | /* properties: */ |
66 | struct drm_property *rotation_prop; | 113 | struct drm_property *rotation_prop; |
67 | struct drm_property *zorder_prop; | 114 | struct drm_property *zorder_prop; |
115 | |||
116 | /* irq handling: */ | ||
117 | struct list_head irq_list; /* list of omap_drm_irq */ | ||
118 | uint32_t vblank_mask; /* irq bits set for userspace vblank */ | ||
119 | struct omap_drm_irq error_handler; | ||
68 | }; | 120 | }; |
69 | 121 | ||
70 | /* this should probably be in drm-core to standardize amongst drivers */ | 122 | /* this should probably be in drm-core to standardize amongst drivers */ |
@@ -75,15 +127,6 @@ struct omap_drm_private { | |||
75 | #define DRM_REFLECT_X 4 | 127 | #define DRM_REFLECT_X 4 |
76 | #define DRM_REFLECT_Y 5 | 128 | #define DRM_REFLECT_Y 5 |
77 | 129 | ||
78 | /* parameters which describe (unrotated) coordinates of scanout within a fb: */ | ||
79 | struct omap_drm_window { | ||
80 | uint32_t rotation; | ||
81 | int32_t crtc_x, crtc_y; /* signed because can be offscreen */ | ||
82 | uint32_t crtc_w, crtc_h; | ||
83 | uint32_t src_x, src_y; | ||
84 | uint32_t src_w, src_h; | ||
85 | }; | ||
86 | |||
87 | #ifdef CONFIG_DEBUG_FS | 130 | #ifdef CONFIG_DEBUG_FS |
88 | int omap_debugfs_init(struct drm_minor *minor); | 131 | int omap_debugfs_init(struct drm_minor *minor); |
89 | void omap_debugfs_cleanup(struct drm_minor *minor); | 132 | void omap_debugfs_cleanup(struct drm_minor *minor); |
@@ -92,23 +135,36 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m); | |||
92 | void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); | 135 | void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); |
93 | #endif | 136 | #endif |
94 | 137 | ||
138 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc); | ||
139 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc); | ||
140 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); | ||
141 | void omap_irq_preinstall(struct drm_device *dev); | ||
142 | int omap_irq_postinstall(struct drm_device *dev); | ||
143 | void omap_irq_uninstall(struct drm_device *dev); | ||
144 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | ||
145 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | ||
146 | int omap_drm_irq_uninstall(struct drm_device *dev); | ||
147 | int omap_drm_irq_install(struct drm_device *dev); | ||
148 | |||
95 | struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); | 149 | struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); |
96 | void omap_fbdev_free(struct drm_device *dev); | 150 | void omap_fbdev_free(struct drm_device *dev); |
97 | 151 | ||
152 | const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); | ||
153 | enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); | ||
154 | int omap_crtc_apply(struct drm_crtc *crtc, | ||
155 | struct omap_drm_apply *apply); | ||
98 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 156 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
99 | struct omap_overlay *ovl, int id); | 157 | struct drm_plane *plane, enum omap_channel channel, int id); |
100 | 158 | ||
101 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 159 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
102 | struct omap_overlay *ovl, unsigned int possible_crtcs, | 160 | int plane_id, bool private_plane); |
103 | bool priv); | ||
104 | int omap_plane_dpms(struct drm_plane *plane, int mode); | 161 | int omap_plane_dpms(struct drm_plane *plane, int mode); |
105 | int omap_plane_mode_set(struct drm_plane *plane, | 162 | int omap_plane_mode_set(struct drm_plane *plane, |
106 | struct drm_crtc *crtc, struct drm_framebuffer *fb, | 163 | struct drm_crtc *crtc, struct drm_framebuffer *fb, |
107 | int crtc_x, int crtc_y, | 164 | int crtc_x, int crtc_y, |
108 | unsigned int crtc_w, unsigned int crtc_h, | 165 | unsigned int crtc_w, unsigned int crtc_h, |
109 | uint32_t src_x, uint32_t src_y, | 166 | uint32_t src_x, uint32_t src_y, |
110 | uint32_t src_w, uint32_t src_h); | 167 | uint32_t src_w, uint32_t src_h, |
111 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
112 | void (*fxn)(void *), void *arg); | 168 | void (*fxn)(void *), void *arg); |
113 | void omap_plane_install_properties(struct drm_plane *plane, | 169 | void omap_plane_install_properties(struct drm_plane *plane, |
114 | struct drm_mode_object *obj); | 170 | struct drm_mode_object *obj); |
@@ -116,21 +172,25 @@ int omap_plane_set_property(struct drm_plane *plane, | |||
116 | struct drm_property *property, uint64_t val); | 172 | struct drm_property *property, uint64_t val); |
117 | 173 | ||
118 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, | 174 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, |
119 | struct omap_overlay_manager *mgr); | 175 | struct omap_dss_device *dssdev); |
120 | struct omap_overlay_manager *omap_encoder_get_manager( | 176 | int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled); |
177 | int omap_encoder_update(struct drm_encoder *encoder, | ||
178 | struct omap_overlay_manager *mgr, | ||
179 | struct omap_video_timings *timings); | ||
180 | |||
181 | struct drm_connector *omap_connector_init(struct drm_device *dev, | ||
182 | int connector_type, struct omap_dss_device *dssdev, | ||
121 | struct drm_encoder *encoder); | 183 | struct drm_encoder *encoder); |
122 | struct drm_encoder *omap_connector_attached_encoder( | 184 | struct drm_encoder *omap_connector_attached_encoder( |
123 | struct drm_connector *connector); | 185 | struct drm_connector *connector); |
124 | enum drm_connector_status omap_connector_detect( | ||
125 | struct drm_connector *connector, bool force); | ||
126 | |||
127 | struct drm_connector *omap_connector_init(struct drm_device *dev, | ||
128 | int connector_type, struct omap_dss_device *dssdev); | ||
129 | void omap_connector_mode_set(struct drm_connector *connector, | ||
130 | struct drm_display_mode *mode); | ||
131 | void omap_connector_flush(struct drm_connector *connector, | 186 | void omap_connector_flush(struct drm_connector *connector, |
132 | int x, int y, int w, int h); | 187 | int x, int y, int w, int h); |
133 | 188 | ||
189 | void copy_timings_omap_to_drm(struct drm_display_mode *mode, | ||
190 | struct omap_video_timings *timings); | ||
191 | void copy_timings_drm_to_omap(struct omap_video_timings *timings, | ||
192 | struct drm_display_mode *mode); | ||
193 | |||
134 | uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, | 194 | uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, |
135 | uint32_t max_formats, enum omap_color_mode supported_modes); | 195 | uint32_t max_formats, enum omap_color_mode supported_modes); |
136 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, | 196 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, |
@@ -207,6 +267,40 @@ static inline int align_pitch(int pitch, int width, int bpp) | |||
207 | return ALIGN(pitch, 8 * bytespp); | 267 | return ALIGN(pitch, 8 * bytespp); |
208 | } | 268 | } |
209 | 269 | ||
270 | static inline enum omap_channel pipe2chan(int pipe) | ||
271 | { | ||
272 | int num_mgrs = dss_feat_get_num_mgrs(); | ||
273 | |||
274 | /* | ||
275 | * We usually don't want to create a CRTC for each manager, | ||
276 | * at least not until we have a way to expose private planes | ||
277 | * to userspace. Otherwise there would not be enough video | ||
278 | * pipes left for drm planes. The higher #'d managers tend | ||
279 | * to have more features so start in reverse order. | ||
280 | */ | ||
281 | return num_mgrs - pipe - 1; | ||
282 | } | ||
283 | |||
284 | /* map crtc to vblank mask */ | ||
285 | static inline uint32_t pipe2vbl(int crtc) | ||
286 | { | ||
287 | enum omap_channel channel = pipe2chan(crtc); | ||
288 | return dispc_mgr_get_vsync_irq(channel); | ||
289 | } | ||
290 | |||
291 | static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc) | ||
292 | { | ||
293 | struct omap_drm_private *priv = dev->dev_private; | ||
294 | int i; | ||
295 | |||
296 | for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++) | ||
297 | if (priv->crtcs[i] == crtc) | ||
298 | return i; | ||
299 | |||
300 | BUG(); /* bogus CRTC ptr */ | ||
301 | return -1; | ||
302 | } | ||
303 | |||
210 | /* should these be made into common util helpers? | 304 | /* should these be made into common util helpers? |
211 | */ | 305 | */ |
212 | 306 | ||
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index 5341d5e3e317..e053160d2db3 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c | |||
@@ -22,37 +22,56 @@ | |||
22 | #include "drm_crtc.h" | 22 | #include "drm_crtc.h" |
23 | #include "drm_crtc_helper.h" | 23 | #include "drm_crtc_helper.h" |
24 | 24 | ||
25 | #include <linux/list.h> | ||
26 | |||
27 | |||
25 | /* | 28 | /* |
26 | * encoder funcs | 29 | * encoder funcs |
27 | */ | 30 | */ |
28 | 31 | ||
29 | #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) | 32 | #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) |
30 | 33 | ||
34 | /* The encoder and connector both map to same dssdev.. the encoder | ||
35 | * handles the 'active' parts, ie. anything the modifies the state | ||
36 | * of the hw, and the connector handles the 'read-only' parts, like | ||
37 | * detecting connection and reading edid. | ||
38 | */ | ||
31 | struct omap_encoder { | 39 | struct omap_encoder { |
32 | struct drm_encoder base; | 40 | struct drm_encoder base; |
33 | struct omap_overlay_manager *mgr; | 41 | struct omap_dss_device *dssdev; |
34 | }; | 42 | }; |
35 | 43 | ||
36 | static void omap_encoder_destroy(struct drm_encoder *encoder) | 44 | static void omap_encoder_destroy(struct drm_encoder *encoder) |
37 | { | 45 | { |
38 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
39 | DBG("%s", omap_encoder->mgr->name); | ||
40 | drm_encoder_cleanup(encoder); | 47 | drm_encoder_cleanup(encoder); |
41 | kfree(omap_encoder); | 48 | kfree(omap_encoder); |
42 | } | 49 | } |
43 | 50 | ||
51 | static const struct drm_encoder_funcs omap_encoder_funcs = { | ||
52 | .destroy = omap_encoder_destroy, | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right | ||
57 | * order.. the easiest way to work around this for now is to make all | ||
58 | * the encoder-helper's no-op's and have the omap_crtc code take care | ||
59 | * of the sequencing and call us in the right points. | ||
60 | * | ||
61 | * Eventually to handle connecting CRTCs to different encoders properly, | ||
62 | * either the CRTC helpers need to change or we need to replace | ||
63 | * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for | ||
64 | * that. | ||
65 | */ | ||
66 | |||
44 | static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) | 67 | static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) |
45 | { | 68 | { |
46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
47 | DBG("%s: %d", omap_encoder->mgr->name, mode); | ||
48 | } | 69 | } |
49 | 70 | ||
50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, | 71 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, |
51 | const struct drm_display_mode *mode, | 72 | const struct drm_display_mode *mode, |
52 | struct drm_display_mode *adjusted_mode) | 73 | struct drm_display_mode *adjusted_mode) |
53 | { | 74 | { |
54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
55 | DBG("%s", omap_encoder->mgr->name); | ||
56 | return true; | 75 | return true; |
57 | } | 76 | } |
58 | 77 | ||
@@ -60,47 +79,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, | |||
60 | struct drm_display_mode *mode, | 79 | struct drm_display_mode *mode, |
61 | struct drm_display_mode *adjusted_mode) | 80 | struct drm_display_mode *adjusted_mode) |
62 | { | 81 | { |
63 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
64 | struct drm_device *dev = encoder->dev; | ||
65 | struct omap_drm_private *priv = dev->dev_private; | ||
66 | int i; | ||
67 | |||
68 | mode = adjusted_mode; | ||
69 | |||
70 | DBG("%s: set mode: %dx%d", omap_encoder->mgr->name, | ||
71 | mode->hdisplay, mode->vdisplay); | ||
72 | |||
73 | for (i = 0; i < priv->num_connectors; i++) { | ||
74 | struct drm_connector *connector = priv->connectors[i]; | ||
75 | if (connector->encoder == encoder) | ||
76 | omap_connector_mode_set(connector, mode); | ||
77 | |||
78 | } | ||
79 | } | 82 | } |
80 | 83 | ||
81 | static void omap_encoder_prepare(struct drm_encoder *encoder) | 84 | static void omap_encoder_prepare(struct drm_encoder *encoder) |
82 | { | 85 | { |
83 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
84 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
85 | encoder->helper_private; | ||
86 | DBG("%s", omap_encoder->mgr->name); | ||
87 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); | ||
88 | } | 86 | } |
89 | 87 | ||
90 | static void omap_encoder_commit(struct drm_encoder *encoder) | 88 | static void omap_encoder_commit(struct drm_encoder *encoder) |
91 | { | 89 | { |
92 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
93 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
94 | encoder->helper_private; | ||
95 | DBG("%s", omap_encoder->mgr->name); | ||
96 | omap_encoder->mgr->apply(omap_encoder->mgr); | ||
97 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
98 | } | 90 | } |
99 | 91 | ||
100 | static const struct drm_encoder_funcs omap_encoder_funcs = { | ||
101 | .destroy = omap_encoder_destroy, | ||
102 | }; | ||
103 | |||
104 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { | 92 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { |
105 | .dpms = omap_encoder_dpms, | 93 | .dpms = omap_encoder_dpms, |
106 | .mode_fixup = omap_encoder_mode_fixup, | 94 | .mode_fixup = omap_encoder_mode_fixup, |
@@ -109,23 +97,54 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { | |||
109 | .commit = omap_encoder_commit, | 97 | .commit = omap_encoder_commit, |
110 | }; | 98 | }; |
111 | 99 | ||
112 | struct omap_overlay_manager *omap_encoder_get_manager( | 100 | /* |
113 | struct drm_encoder *encoder) | 101 | * Instead of relying on the helpers for modeset, the omap_crtc code |
102 | * calls these functions in the proper sequence. | ||
103 | */ | ||
104 | |||
105 | int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled) | ||
114 | { | 106 | { |
115 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 107 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
116 | return omap_encoder->mgr; | 108 | struct omap_dss_device *dssdev = omap_encoder->dssdev; |
109 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
110 | |||
111 | if (enabled) { | ||
112 | return dssdrv->enable(dssdev); | ||
113 | } else { | ||
114 | dssdrv->disable(dssdev); | ||
115 | return 0; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | int omap_encoder_update(struct drm_encoder *encoder, | ||
120 | struct omap_overlay_manager *mgr, | ||
121 | struct omap_video_timings *timings) | ||
122 | { | ||
123 | struct drm_device *dev = encoder->dev; | ||
124 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
125 | struct omap_dss_device *dssdev = omap_encoder->dssdev; | ||
126 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
127 | int ret; | ||
128 | |||
129 | dssdev->output->manager = mgr; | ||
130 | |||
131 | ret = dssdrv->check_timings(dssdev, timings); | ||
132 | if (ret) { | ||
133 | dev_err(dev->dev, "could not set timings: %d\n", ret); | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | dssdrv->set_timings(dssdev, timings); | ||
138 | |||
139 | return 0; | ||
117 | } | 140 | } |
118 | 141 | ||
119 | /* initialize encoder */ | 142 | /* initialize encoder */ |
120 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, | 143 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, |
121 | struct omap_overlay_manager *mgr) | 144 | struct omap_dss_device *dssdev) |
122 | { | 145 | { |
123 | struct drm_encoder *encoder = NULL; | 146 | struct drm_encoder *encoder = NULL; |
124 | struct omap_encoder *omap_encoder; | 147 | struct omap_encoder *omap_encoder; |
125 | struct omap_overlay_manager_info info; | ||
126 | int ret; | ||
127 | |||
128 | DBG("%s", mgr->name); | ||
129 | 148 | ||
130 | omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); | 149 | omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); |
131 | if (!omap_encoder) { | 150 | if (!omap_encoder) { |
@@ -133,33 +152,14 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev, | |||
133 | goto fail; | 152 | goto fail; |
134 | } | 153 | } |
135 | 154 | ||
136 | omap_encoder->mgr = mgr; | 155 | omap_encoder->dssdev = dssdev; |
156 | |||
137 | encoder = &omap_encoder->base; | 157 | encoder = &omap_encoder->base; |
138 | 158 | ||
139 | drm_encoder_init(dev, encoder, &omap_encoder_funcs, | 159 | drm_encoder_init(dev, encoder, &omap_encoder_funcs, |
140 | DRM_MODE_ENCODER_TMDS); | 160 | DRM_MODE_ENCODER_TMDS); |
141 | drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); | 161 | drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); |
142 | 162 | ||
143 | mgr->get_manager_info(mgr, &info); | ||
144 | |||
145 | /* TODO: fix hard-coded setup.. */ | ||
146 | info.default_color = 0x00000000; | ||
147 | info.trans_key = 0x00000000; | ||
148 | info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
149 | info.trans_enabled = false; | ||
150 | |||
151 | ret = mgr->set_manager_info(mgr, &info); | ||
152 | if (ret) { | ||
153 | dev_err(dev->dev, "could not set manager info\n"); | ||
154 | goto fail; | ||
155 | } | ||
156 | |||
157 | ret = mgr->apply(mgr); | ||
158 | if (ret) { | ||
159 | dev_err(dev->dev, "could not apply\n"); | ||
160 | goto fail; | ||
161 | } | ||
162 | |||
163 | return encoder; | 163 | return encoder; |
164 | 164 | ||
165 | fail: | 165 | fail: |
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c index ea3840038250..b6c5b5c6c8c5 100644 --- a/drivers/staging/omapdrm/omap_gem_dmabuf.c +++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c | |||
@@ -194,7 +194,7 @@ struct dma_buf_ops omap_dmabuf_ops = { | |||
194 | struct dma_buf *omap_gem_prime_export(struct drm_device *dev, | 194 | struct dma_buf *omap_gem_prime_export(struct drm_device *dev, |
195 | struct drm_gem_object *obj, int flags) | 195 | struct drm_gem_object *obj, int flags) |
196 | { | 196 | { |
197 | return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600); | 197 | return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags); |
198 | } | 198 | } |
199 | 199 | ||
200 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, | 200 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, |
diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c new file mode 100644 index 000000000000..2629ba7be6c8 --- /dev/null +++ b/drivers/staging/omapdrm/omap_irq.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * drivers/staging/omapdrm/omap_irq.c | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments | ||
5 | * Author: Rob Clark <rob.clark@linaro.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "omap_drv.h" | ||
21 | |||
22 | static DEFINE_SPINLOCK(list_lock); | ||
23 | |||
24 | static void omap_irq_error_handler(struct omap_drm_irq *irq, | ||
25 | uint32_t irqstatus) | ||
26 | { | ||
27 | DRM_ERROR("errors: %08x\n", irqstatus); | ||
28 | } | ||
29 | |||
30 | /* call with list_lock and dispc runtime held */ | ||
31 | static void omap_irq_update(struct drm_device *dev) | ||
32 | { | ||
33 | struct omap_drm_private *priv = dev->dev_private; | ||
34 | struct omap_drm_irq *irq; | ||
35 | uint32_t irqmask = priv->vblank_mask; | ||
36 | |||
37 | BUG_ON(!spin_is_locked(&list_lock)); | ||
38 | |||
39 | list_for_each_entry(irq, &priv->irq_list, node) | ||
40 | irqmask |= irq->irqmask; | ||
41 | |||
42 | DBG("irqmask=%08x", irqmask); | ||
43 | |||
44 | dispc_write_irqenable(irqmask); | ||
45 | dispc_read_irqenable(); /* flush posted write */ | ||
46 | } | ||
47 | |||
48 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | ||
49 | { | ||
50 | struct omap_drm_private *priv = dev->dev_private; | ||
51 | unsigned long flags; | ||
52 | |||
53 | dispc_runtime_get(); | ||
54 | spin_lock_irqsave(&list_lock, flags); | ||
55 | |||
56 | if (!WARN_ON(irq->registered)) { | ||
57 | irq->registered = true; | ||
58 | list_add(&irq->node, &priv->irq_list); | ||
59 | omap_irq_update(dev); | ||
60 | } | ||
61 | |||
62 | spin_unlock_irqrestore(&list_lock, flags); | ||
63 | dispc_runtime_put(); | ||
64 | } | ||
65 | |||
66 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | |||
70 | dispc_runtime_get(); | ||
71 | spin_lock_irqsave(&list_lock, flags); | ||
72 | |||
73 | if (!WARN_ON(!irq->registered)) { | ||
74 | irq->registered = false; | ||
75 | list_del(&irq->node); | ||
76 | omap_irq_update(dev); | ||
77 | } | ||
78 | |||
79 | spin_unlock_irqrestore(&list_lock, flags); | ||
80 | dispc_runtime_put(); | ||
81 | } | ||
82 | |||
83 | struct omap_irq_wait { | ||
84 | struct omap_drm_irq irq; | ||
85 | int count; | ||
86 | }; | ||
87 | |||
88 | static DECLARE_WAIT_QUEUE_HEAD(wait_event); | ||
89 | |||
90 | static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
91 | { | ||
92 | struct omap_irq_wait *wait = | ||
93 | container_of(irq, struct omap_irq_wait, irq); | ||
94 | wait->count--; | ||
95 | wake_up_all(&wait_event); | ||
96 | } | ||
97 | |||
98 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, | ||
99 | uint32_t irqmask, int count) | ||
100 | { | ||
101 | struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); | ||
102 | wait->irq.irq = wait_irq; | ||
103 | wait->irq.irqmask = irqmask; | ||
104 | wait->count = count; | ||
105 | omap_irq_register(dev, &wait->irq); | ||
106 | return wait; | ||
107 | } | ||
108 | |||
109 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | ||
110 | unsigned long timeout) | ||
111 | { | ||
112 | int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout); | ||
113 | omap_irq_unregister(dev, &wait->irq); | ||
114 | kfree(wait); | ||
115 | if (ret == 0) | ||
116 | return -1; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * enable_vblank - enable vblank interrupt events | ||
122 | * @dev: DRM device | ||
123 | * @crtc: which irq to enable | ||
124 | * | ||
125 | * Enable vblank interrupts for @crtc. If the device doesn't have | ||
126 | * a hardware vblank counter, this routine should be a no-op, since | ||
127 | * interrupts will have to stay on to keep the count accurate. | ||
128 | * | ||
129 | * RETURNS | ||
130 | * Zero on success, appropriate errno if the given @crtc's vblank | ||
131 | * interrupt cannot be enabled. | ||
132 | */ | ||
133 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc) | ||
134 | { | ||
135 | struct omap_drm_private *priv = dev->dev_private; | ||
136 | unsigned long flags; | ||
137 | |||
138 | DBG("dev=%p, crtc=%d", dev, crtc); | ||
139 | |||
140 | dispc_runtime_get(); | ||
141 | spin_lock_irqsave(&list_lock, flags); | ||
142 | priv->vblank_mask |= pipe2vbl(crtc); | ||
143 | omap_irq_update(dev); | ||
144 | spin_unlock_irqrestore(&list_lock, flags); | ||
145 | dispc_runtime_put(); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * disable_vblank - disable vblank interrupt events | ||
152 | * @dev: DRM device | ||
153 | * @crtc: which irq to enable | ||
154 | * | ||
155 | * Disable vblank interrupts for @crtc. If the device doesn't have | ||
156 | * a hardware vblank counter, this routine should be a no-op, since | ||
157 | * interrupts will have to stay on to keep the count accurate. | ||
158 | */ | ||
159 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc) | ||
160 | { | ||
161 | struct omap_drm_private *priv = dev->dev_private; | ||
162 | unsigned long flags; | ||
163 | |||
164 | DBG("dev=%p, crtc=%d", dev, crtc); | ||
165 | |||
166 | dispc_runtime_get(); | ||
167 | spin_lock_irqsave(&list_lock, flags); | ||
168 | priv->vblank_mask &= ~pipe2vbl(crtc); | ||
169 | omap_irq_update(dev); | ||
170 | spin_unlock_irqrestore(&list_lock, flags); | ||
171 | dispc_runtime_put(); | ||
172 | } | ||
173 | |||
174 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) | ||
175 | { | ||
176 | struct drm_device *dev = (struct drm_device *) arg; | ||
177 | struct omap_drm_private *priv = dev->dev_private; | ||
178 | struct omap_drm_irq *handler, *n; | ||
179 | unsigned long flags; | ||
180 | unsigned int id; | ||
181 | u32 irqstatus; | ||
182 | |||
183 | irqstatus = dispc_read_irqstatus(); | ||
184 | dispc_clear_irqstatus(irqstatus); | ||
185 | dispc_read_irqstatus(); /* flush posted write */ | ||
186 | |||
187 | VERB("irqs: %08x", irqstatus); | ||
188 | |||
189 | for (id = 0; id < priv->num_crtcs; id++) | ||
190 | if (irqstatus & pipe2vbl(id)) | ||
191 | drm_handle_vblank(dev, id); | ||
192 | |||
193 | spin_lock_irqsave(&list_lock, flags); | ||
194 | list_for_each_entry_safe(handler, n, &priv->irq_list, node) { | ||
195 | if (handler->irqmask & irqstatus) { | ||
196 | spin_unlock_irqrestore(&list_lock, flags); | ||
197 | handler->irq(handler, handler->irqmask & irqstatus); | ||
198 | spin_lock_irqsave(&list_lock, flags); | ||
199 | } | ||
200 | } | ||
201 | spin_unlock_irqrestore(&list_lock, flags); | ||
202 | |||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | |||
206 | void omap_irq_preinstall(struct drm_device *dev) | ||
207 | { | ||
208 | DBG("dev=%p", dev); | ||
209 | dispc_runtime_get(); | ||
210 | dispc_clear_irqstatus(0xffffffff); | ||
211 | dispc_runtime_put(); | ||
212 | } | ||
213 | |||
214 | int omap_irq_postinstall(struct drm_device *dev) | ||
215 | { | ||
216 | struct omap_drm_private *priv = dev->dev_private; | ||
217 | struct omap_drm_irq *error_handler = &priv->error_handler; | ||
218 | |||
219 | DBG("dev=%p", dev); | ||
220 | |||
221 | INIT_LIST_HEAD(&priv->irq_list); | ||
222 | |||
223 | error_handler->irq = omap_irq_error_handler; | ||
224 | error_handler->irqmask = DISPC_IRQ_OCP_ERR; | ||
225 | |||
226 | /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think | ||
227 | * we just need to ignore it while enabling tv-out | ||
228 | */ | ||
229 | error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; | ||
230 | |||
231 | omap_irq_register(dev, error_handler); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | void omap_irq_uninstall(struct drm_device *dev) | ||
237 | { | ||
238 | DBG("dev=%p", dev); | ||
239 | // TODO prolly need to call drm_irq_uninstall() somewhere too | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * We need a special version, instead of just using drm_irq_install(), | ||
244 | * because we need to register the irq via omapdss. Once omapdss and | ||
245 | * omapdrm are merged together we can assign the dispc hwmod data to | ||
246 | * ourselves and drop these and just use drm_irq_{install,uninstall}() | ||
247 | */ | ||
248 | |||
249 | int omap_drm_irq_install(struct drm_device *dev) | ||
250 | { | ||
251 | int ret; | ||
252 | |||
253 | mutex_lock(&dev->struct_mutex); | ||
254 | |||
255 | if (dev->irq_enabled) { | ||
256 | mutex_unlock(&dev->struct_mutex); | ||
257 | return -EBUSY; | ||
258 | } | ||
259 | dev->irq_enabled = 1; | ||
260 | mutex_unlock(&dev->struct_mutex); | ||
261 | |||
262 | /* Before installing handler */ | ||
263 | if (dev->driver->irq_preinstall) | ||
264 | dev->driver->irq_preinstall(dev); | ||
265 | |||
266 | ret = dispc_request_irq(dev->driver->irq_handler, dev); | ||
267 | |||
268 | if (ret < 0) { | ||
269 | mutex_lock(&dev->struct_mutex); | ||
270 | dev->irq_enabled = 0; | ||
271 | mutex_unlock(&dev->struct_mutex); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | /* After installing handler */ | ||
276 | if (dev->driver->irq_postinstall) | ||
277 | ret = dev->driver->irq_postinstall(dev); | ||
278 | |||
279 | if (ret < 0) { | ||
280 | mutex_lock(&dev->struct_mutex); | ||
281 | dev->irq_enabled = 0; | ||
282 | mutex_unlock(&dev->struct_mutex); | ||
283 | dispc_free_irq(dev); | ||
284 | } | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | int omap_drm_irq_uninstall(struct drm_device *dev) | ||
290 | { | ||
291 | unsigned long irqflags; | ||
292 | int irq_enabled, i; | ||
293 | |||
294 | mutex_lock(&dev->struct_mutex); | ||
295 | irq_enabled = dev->irq_enabled; | ||
296 | dev->irq_enabled = 0; | ||
297 | mutex_unlock(&dev->struct_mutex); | ||
298 | |||
299 | /* | ||
300 | * Wake up any waiters so they don't hang. | ||
301 | */ | ||
302 | if (dev->num_crtcs) { | ||
303 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | ||
304 | for (i = 0; i < dev->num_crtcs; i++) { | ||
305 | DRM_WAKEUP(&dev->vbl_queue[i]); | ||
306 | dev->vblank_enabled[i] = 0; | ||
307 | dev->last_vblank[i] = | ||
308 | dev->driver->get_vblank_counter(dev, i); | ||
309 | } | ||
310 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
311 | } | ||
312 | |||
313 | if (!irq_enabled) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (dev->driver->irq_uninstall) | ||
317 | dev->driver->irq_uninstall(dev); | ||
318 | |||
319 | dispc_free_irq(dev); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 2a8e5bab49c9..bb989d7f026d 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c | |||
@@ -41,12 +41,14 @@ struct callback { | |||
41 | 41 | ||
42 | struct omap_plane { | 42 | struct omap_plane { |
43 | struct drm_plane base; | 43 | struct drm_plane base; |
44 | struct omap_overlay *ovl; | 44 | int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ |
45 | const char *name; | ||
45 | struct omap_overlay_info info; | 46 | struct omap_overlay_info info; |
47 | struct omap_drm_apply apply; | ||
46 | 48 | ||
47 | /* position/orientation of scanout within the fb: */ | 49 | /* position/orientation of scanout within the fb: */ |
48 | struct omap_drm_window win; | 50 | struct omap_drm_window win; |
49 | 51 | bool enabled; | |
50 | 52 | ||
51 | /* last fb that we pinned: */ | 53 | /* last fb that we pinned: */ |
52 | struct drm_framebuffer *pinned_fb; | 54 | struct drm_framebuffer *pinned_fb; |
@@ -54,189 +56,15 @@ struct omap_plane { | |||
54 | uint32_t nformats; | 56 | uint32_t nformats; |
55 | uint32_t formats[32]; | 57 | uint32_t formats[32]; |
56 | 58 | ||
57 | /* for synchronizing access to unpins fifo */ | 59 | struct omap_drm_irq error_irq; |
58 | struct mutex unpin_mutex; | ||
59 | 60 | ||
60 | /* set of bo's pending unpin until next END_WIN irq */ | 61 | /* set of bo's pending unpin until next post_apply() */ |
61 | DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *); | 62 | DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *); |
62 | int num_unpins, pending_num_unpins; | ||
63 | |||
64 | /* for deferred unpin when we need to wait for scanout complete irq */ | ||
65 | struct work_struct work; | ||
66 | |||
67 | /* callback on next endwin irq */ | ||
68 | struct callback endwin; | ||
69 | }; | ||
70 | 63 | ||
71 | /* map from ovl->id to the irq we are interested in for scanout-done */ | 64 | // XXX maybe get rid of this and handle vblank in crtc too? |
72 | static const uint32_t id2irq[] = { | 65 | struct callback apply_done_cb; |
73 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_END_WIN, | ||
74 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN, | ||
75 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN, | ||
76 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN, | ||
77 | }; | 66 | }; |
78 | 67 | ||
79 | static void dispc_isr(void *arg, uint32_t mask) | ||
80 | { | ||
81 | struct drm_plane *plane = arg; | ||
82 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
83 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
84 | |||
85 | omap_dispc_unregister_isr(dispc_isr, plane, | ||
86 | id2irq[omap_plane->ovl->id]); | ||
87 | |||
88 | queue_work(priv->wq, &omap_plane->work); | ||
89 | } | ||
90 | |||
91 | static void unpin_worker(struct work_struct *work) | ||
92 | { | ||
93 | struct omap_plane *omap_plane = | ||
94 | container_of(work, struct omap_plane, work); | ||
95 | struct callback endwin; | ||
96 | |||
97 | mutex_lock(&omap_plane->unpin_mutex); | ||
98 | DBG("unpinning %d of %d", omap_plane->num_unpins, | ||
99 | omap_plane->num_unpins + omap_plane->pending_num_unpins); | ||
100 | while (omap_plane->num_unpins > 0) { | ||
101 | struct drm_gem_object *bo = NULL; | ||
102 | int ret = kfifo_get(&omap_plane->unpin_fifo, &bo); | ||
103 | WARN_ON(!ret); | ||
104 | omap_gem_put_paddr(bo); | ||
105 | drm_gem_object_unreference_unlocked(bo); | ||
106 | omap_plane->num_unpins--; | ||
107 | } | ||
108 | endwin = omap_plane->endwin; | ||
109 | omap_plane->endwin.fxn = NULL; | ||
110 | mutex_unlock(&omap_plane->unpin_mutex); | ||
111 | |||
112 | if (endwin.fxn) | ||
113 | endwin.fxn(endwin.arg); | ||
114 | } | ||
115 | |||
116 | static void install_irq(struct drm_plane *plane) | ||
117 | { | ||
118 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
119 | struct omap_overlay *ovl = omap_plane->ovl; | ||
120 | int ret; | ||
121 | |||
122 | ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]); | ||
123 | |||
124 | /* | ||
125 | * omapdss has upper limit on # of registered irq handlers, | ||
126 | * which we shouldn't hit.. but if we do the limit should | ||
127 | * be raised or bad things happen: | ||
128 | */ | ||
129 | WARN_ON(ret == -EBUSY); | ||
130 | } | ||
131 | |||
132 | /* push changes down to dss2 */ | ||
133 | static int commit(struct drm_plane *plane) | ||
134 | { | ||
135 | struct drm_device *dev = plane->dev; | ||
136 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
137 | struct omap_overlay *ovl = omap_plane->ovl; | ||
138 | struct omap_overlay_info *info = &omap_plane->info; | ||
139 | int ret; | ||
140 | |||
141 | DBG("%s", ovl->name); | ||
142 | DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, | ||
143 | info->out_height, info->screen_width); | ||
144 | DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, | ||
145 | info->paddr, info->p_uv_addr); | ||
146 | |||
147 | /* NOTE: do we want to do this at all here, or just wait | ||
148 | * for dpms(ON) since other CRTC's may not have their mode | ||
149 | * set yet, so fb dimensions may still change.. | ||
150 | */ | ||
151 | ret = ovl->set_overlay_info(ovl, info); | ||
152 | if (ret) { | ||
153 | dev_err(dev->dev, "could not set overlay info\n"); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | mutex_lock(&omap_plane->unpin_mutex); | ||
158 | omap_plane->num_unpins += omap_plane->pending_num_unpins; | ||
159 | omap_plane->pending_num_unpins = 0; | ||
160 | mutex_unlock(&omap_plane->unpin_mutex); | ||
161 | |||
162 | /* our encoder doesn't necessarily get a commit() after this, in | ||
163 | * particular in the dpms() and mode_set_base() cases, so force the | ||
164 | * manager to update: | ||
165 | * | ||
166 | * could this be in the encoder somehow? | ||
167 | */ | ||
168 | if (ovl->manager) { | ||
169 | ret = ovl->manager->apply(ovl->manager); | ||
170 | if (ret) { | ||
171 | dev_err(dev->dev, "could not apply settings\n"); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * NOTE: really this should be atomic w/ mgr->apply() but | ||
177 | * omapdss does not expose such an API | ||
178 | */ | ||
179 | if (omap_plane->num_unpins > 0) | ||
180 | install_irq(plane); | ||
181 | |||
182 | } else { | ||
183 | struct omap_drm_private *priv = dev->dev_private; | ||
184 | queue_work(priv->wq, &omap_plane->work); | ||
185 | } | ||
186 | |||
187 | |||
188 | if (ovl->is_enabled(ovl)) { | ||
189 | omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, | ||
190 | info->out_width, info->out_height); | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* when CRTC that we are attached to has potentially changed, this checks | ||
197 | * if we are attached to proper manager, and if necessary updates. | ||
198 | */ | ||
199 | static void update_manager(struct drm_plane *plane) | ||
200 | { | ||
201 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
202 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
203 | struct omap_overlay *ovl = omap_plane->ovl; | ||
204 | struct omap_overlay_manager *mgr = NULL; | ||
205 | int i; | ||
206 | |||
207 | if (plane->crtc) { | ||
208 | for (i = 0; i < priv->num_encoders; i++) { | ||
209 | struct drm_encoder *encoder = priv->encoders[i]; | ||
210 | if (encoder->crtc == plane->crtc) { | ||
211 | mgr = omap_encoder_get_manager(encoder); | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | if (ovl->manager != mgr) { | ||
218 | bool enabled = ovl->is_enabled(ovl); | ||
219 | |||
220 | /* don't switch things around with enabled overlays: */ | ||
221 | if (enabled) | ||
222 | omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); | ||
223 | |||
224 | if (ovl->manager) { | ||
225 | DBG("disconnecting %s from %s", ovl->name, | ||
226 | ovl->manager->name); | ||
227 | ovl->unset_manager(ovl); | ||
228 | } | ||
229 | |||
230 | if (mgr) { | ||
231 | DBG("connecting %s to %s", ovl->name, mgr->name); | ||
232 | ovl->set_manager(ovl, mgr); | ||
233 | } | ||
234 | |||
235 | if (enabled && mgr) | ||
236 | omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | static void unpin(void *arg, struct drm_gem_object *bo) | 68 | static void unpin(void *arg, struct drm_gem_object *bo) |
241 | { | 69 | { |
242 | struct drm_plane *plane = arg; | 70 | struct drm_plane *plane = arg; |
@@ -244,7 +72,6 @@ static void unpin(void *arg, struct drm_gem_object *bo) | |||
244 | 72 | ||
245 | if (kfifo_put(&omap_plane->unpin_fifo, | 73 | if (kfifo_put(&omap_plane->unpin_fifo, |
246 | (const struct drm_gem_object **)&bo)) { | 74 | (const struct drm_gem_object **)&bo)) { |
247 | omap_plane->pending_num_unpins++; | ||
248 | /* also hold a ref so it isn't free'd while pinned */ | 75 | /* also hold a ref so it isn't free'd while pinned */ |
249 | drm_gem_object_reference(bo); | 76 | drm_gem_object_reference(bo); |
250 | } else { | 77 | } else { |
@@ -264,13 +91,19 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) | |||
264 | 91 | ||
265 | DBG("%p -> %p", pinned_fb, fb); | 92 | DBG("%p -> %p", pinned_fb, fb); |
266 | 93 | ||
267 | mutex_lock(&omap_plane->unpin_mutex); | 94 | if (fb) |
95 | drm_framebuffer_reference(fb); | ||
96 | |||
268 | ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin); | 97 | ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin); |
269 | mutex_unlock(&omap_plane->unpin_mutex); | 98 | |
99 | if (pinned_fb) | ||
100 | drm_framebuffer_unreference(pinned_fb); | ||
270 | 101 | ||
271 | if (ret) { | 102 | if (ret) { |
272 | dev_err(plane->dev->dev, "could not swap %p -> %p\n", | 103 | dev_err(plane->dev->dev, "could not swap %p -> %p\n", |
273 | omap_plane->pinned_fb, fb); | 104 | omap_plane->pinned_fb, fb); |
105 | if (fb) | ||
106 | drm_framebuffer_unreference(fb); | ||
274 | omap_plane->pinned_fb = NULL; | 107 | omap_plane->pinned_fb = NULL; |
275 | return ret; | 108 | return ret; |
276 | } | 109 | } |
@@ -281,31 +114,90 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) | |||
281 | return 0; | 114 | return 0; |
282 | } | 115 | } |
283 | 116 | ||
284 | /* update parameters that are dependent on the framebuffer dimensions and | 117 | static void omap_plane_pre_apply(struct omap_drm_apply *apply) |
285 | * position within the fb that this plane scans out from. This is called | ||
286 | * when framebuffer or x,y base may have changed. | ||
287 | */ | ||
288 | static void update_scanout(struct drm_plane *plane) | ||
289 | { | 118 | { |
290 | struct omap_plane *omap_plane = to_omap_plane(plane); | 119 | struct omap_plane *omap_plane = |
291 | struct omap_overlay_info *info = &omap_plane->info; | 120 | container_of(apply, struct omap_plane, apply); |
292 | struct omap_drm_window *win = &omap_plane->win; | 121 | struct omap_drm_window *win = &omap_plane->win; |
122 | struct drm_plane *plane = &omap_plane->base; | ||
123 | struct drm_device *dev = plane->dev; | ||
124 | struct omap_overlay_info *info = &omap_plane->info; | ||
125 | struct drm_crtc *crtc = plane->crtc; | ||
126 | enum omap_channel channel; | ||
127 | bool enabled = omap_plane->enabled && crtc; | ||
128 | bool ilace, replication; | ||
293 | int ret; | 129 | int ret; |
294 | 130 | ||
295 | ret = update_pin(plane, plane->fb); | 131 | DBG("%s, enabled=%d", omap_plane->name, enabled); |
296 | if (ret) { | 132 | |
297 | dev_err(plane->dev->dev, | 133 | /* if fb has changed, pin new fb: */ |
298 | "could not pin fb: %d\n", ret); | 134 | update_pin(plane, enabled ? plane->fb : NULL); |
299 | omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); | 135 | |
136 | if (!enabled) { | ||
137 | dispc_ovl_enable(omap_plane->id, false); | ||
300 | return; | 138 | return; |
301 | } | 139 | } |
302 | 140 | ||
141 | channel = omap_crtc_channel(crtc); | ||
142 | |||
143 | /* update scanout: */ | ||
303 | omap_framebuffer_update_scanout(plane->fb, win, info); | 144 | omap_framebuffer_update_scanout(plane->fb, win, info); |
304 | 145 | ||
305 | DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name, | 146 | DBG("%dx%d -> %dx%d (%d)", info->width, info->height, |
306 | win->src_x, win->src_y, | 147 | info->out_width, info->out_height, |
307 | (u32)info->paddr, (u32)info->p_uv_addr, | ||
308 | info->screen_width); | 148 | info->screen_width); |
149 | DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, | ||
150 | info->paddr, info->p_uv_addr); | ||
151 | |||
152 | /* TODO: */ | ||
153 | ilace = false; | ||
154 | replication = false; | ||
155 | |||
156 | /* and finally, update omapdss: */ | ||
157 | ret = dispc_ovl_setup(omap_plane->id, info, | ||
158 | replication, omap_crtc_timings(crtc), false); | ||
159 | if (ret) { | ||
160 | dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | dispc_ovl_enable(omap_plane->id, true); | ||
165 | dispc_ovl_set_channel_out(omap_plane->id, channel); | ||
166 | } | ||
167 | |||
168 | static void omap_plane_post_apply(struct omap_drm_apply *apply) | ||
169 | { | ||
170 | struct omap_plane *omap_plane = | ||
171 | container_of(apply, struct omap_plane, apply); | ||
172 | struct drm_plane *plane = &omap_plane->base; | ||
173 | struct omap_overlay_info *info = &omap_plane->info; | ||
174 | struct drm_gem_object *bo = NULL; | ||
175 | struct callback cb; | ||
176 | |||
177 | cb = omap_plane->apply_done_cb; | ||
178 | omap_plane->apply_done_cb.fxn = NULL; | ||
179 | |||
180 | while (kfifo_get(&omap_plane->unpin_fifo, &bo)) { | ||
181 | omap_gem_put_paddr(bo); | ||
182 | drm_gem_object_unreference_unlocked(bo); | ||
183 | } | ||
184 | |||
185 | if (cb.fxn) | ||
186 | cb.fxn(cb.arg); | ||
187 | |||
188 | if (omap_plane->enabled) { | ||
189 | omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, | ||
190 | info->out_width, info->out_height); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int apply(struct drm_plane *plane) | ||
195 | { | ||
196 | if (plane->crtc) { | ||
197 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
198 | return omap_crtc_apply(plane->crtc, &omap_plane->apply); | ||
199 | } | ||
200 | return 0; | ||
309 | } | 201 | } |
310 | 202 | ||
311 | int omap_plane_mode_set(struct drm_plane *plane, | 203 | int omap_plane_mode_set(struct drm_plane *plane, |
@@ -313,7 +205,8 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
313 | int crtc_x, int crtc_y, | 205 | int crtc_x, int crtc_y, |
314 | unsigned int crtc_w, unsigned int crtc_h, | 206 | unsigned int crtc_w, unsigned int crtc_h, |
315 | uint32_t src_x, uint32_t src_y, | 207 | uint32_t src_x, uint32_t src_y, |
316 | uint32_t src_w, uint32_t src_h) | 208 | uint32_t src_w, uint32_t src_h, |
209 | void (*fxn)(void *), void *arg) | ||
317 | { | 210 | { |
318 | struct omap_plane *omap_plane = to_omap_plane(plane); | 211 | struct omap_plane *omap_plane = to_omap_plane(plane); |
319 | struct omap_drm_window *win = &omap_plane->win; | 212 | struct omap_drm_window *win = &omap_plane->win; |
@@ -329,17 +222,20 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
329 | win->src_w = src_w >> 16; | 222 | win->src_w = src_w >> 16; |
330 | win->src_h = src_h >> 16; | 223 | win->src_h = src_h >> 16; |
331 | 224 | ||
332 | /* note: this is done after this fxn returns.. but if we need | 225 | if (fxn) { |
333 | * to do a commit/update_scanout, etc before this returns we | 226 | /* omap_crtc should ensure that a new page flip |
334 | * need the current value. | 227 | * isn't permitted while there is one pending: |
335 | */ | 228 | */ |
229 | BUG_ON(omap_plane->apply_done_cb.fxn); | ||
230 | |||
231 | omap_plane->apply_done_cb.fxn = fxn; | ||
232 | omap_plane->apply_done_cb.arg = arg; | ||
233 | } | ||
234 | |||
336 | plane->fb = fb; | 235 | plane->fb = fb; |
337 | plane->crtc = crtc; | 236 | plane->crtc = crtc; |
338 | 237 | ||
339 | update_scanout(plane); | 238 | return apply(plane); |
340 | update_manager(plane); | ||
341 | |||
342 | return 0; | ||
343 | } | 239 | } |
344 | 240 | ||
345 | static int omap_plane_update(struct drm_plane *plane, | 241 | static int omap_plane_update(struct drm_plane *plane, |
@@ -349,9 +245,12 @@ static int omap_plane_update(struct drm_plane *plane, | |||
349 | uint32_t src_x, uint32_t src_y, | 245 | uint32_t src_x, uint32_t src_y, |
350 | uint32_t src_w, uint32_t src_h) | 246 | uint32_t src_w, uint32_t src_h) |
351 | { | 247 | { |
352 | omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, | 248 | struct omap_plane *omap_plane = to_omap_plane(plane); |
353 | src_x, src_y, src_w, src_h); | 249 | omap_plane->enabled = true; |
354 | return omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | 250 | return omap_plane_mode_set(plane, crtc, fb, |
251 | crtc_x, crtc_y, crtc_w, crtc_h, | ||
252 | src_x, src_y, src_w, src_h, | ||
253 | NULL, NULL); | ||
355 | } | 254 | } |
356 | 255 | ||
357 | static int omap_plane_disable(struct drm_plane *plane) | 256 | static int omap_plane_disable(struct drm_plane *plane) |
@@ -364,48 +263,32 @@ static int omap_plane_disable(struct drm_plane *plane) | |||
364 | static void omap_plane_destroy(struct drm_plane *plane) | 263 | static void omap_plane_destroy(struct drm_plane *plane) |
365 | { | 264 | { |
366 | struct omap_plane *omap_plane = to_omap_plane(plane); | 265 | struct omap_plane *omap_plane = to_omap_plane(plane); |
367 | DBG("%s", omap_plane->ovl->name); | 266 | |
267 | DBG("%s", omap_plane->name); | ||
268 | |||
269 | omap_irq_unregister(plane->dev, &omap_plane->error_irq); | ||
270 | |||
368 | omap_plane_disable(plane); | 271 | omap_plane_disable(plane); |
369 | drm_plane_cleanup(plane); | 272 | drm_plane_cleanup(plane); |
370 | WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0); | 273 | |
274 | WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo)); | ||
371 | kfifo_free(&omap_plane->unpin_fifo); | 275 | kfifo_free(&omap_plane->unpin_fifo); |
276 | |||
372 | kfree(omap_plane); | 277 | kfree(omap_plane); |
373 | } | 278 | } |
374 | 279 | ||
375 | int omap_plane_dpms(struct drm_plane *plane, int mode) | 280 | int omap_plane_dpms(struct drm_plane *plane, int mode) |
376 | { | 281 | { |
377 | struct omap_plane *omap_plane = to_omap_plane(plane); | 282 | struct omap_plane *omap_plane = to_omap_plane(plane); |
378 | struct omap_overlay *ovl = omap_plane->ovl; | 283 | bool enabled = (mode == DRM_MODE_DPMS_ON); |
379 | int r; | 284 | int ret = 0; |
380 | 285 | ||
381 | DBG("%s: %d", omap_plane->ovl->name, mode); | 286 | if (enabled != omap_plane->enabled) { |
382 | 287 | omap_plane->enabled = enabled; | |
383 | if (mode == DRM_MODE_DPMS_ON) { | 288 | ret = apply(plane); |
384 | update_scanout(plane); | ||
385 | r = commit(plane); | ||
386 | if (!r) | ||
387 | r = ovl->enable(ovl); | ||
388 | } else { | ||
389 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
390 | r = ovl->disable(ovl); | ||
391 | update_pin(plane, NULL); | ||
392 | queue_work(priv->wq, &omap_plane->work); | ||
393 | } | 289 | } |
394 | 290 | ||
395 | return r; | 291 | return ret; |
396 | } | ||
397 | |||
398 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
399 | void (*fxn)(void *), void *arg) | ||
400 | { | ||
401 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
402 | |||
403 | mutex_lock(&omap_plane->unpin_mutex); | ||
404 | omap_plane->endwin.fxn = fxn; | ||
405 | omap_plane->endwin.arg = arg; | ||
406 | mutex_unlock(&omap_plane->unpin_mutex); | ||
407 | |||
408 | install_irq(plane); | ||
409 | } | 292 | } |
410 | 293 | ||
411 | /* helper to install properties which are common to planes and crtcs */ | 294 | /* helper to install properties which are common to planes and crtcs */ |
@@ -454,25 +337,13 @@ int omap_plane_set_property(struct drm_plane *plane, | |||
454 | int ret = -EINVAL; | 337 | int ret = -EINVAL; |
455 | 338 | ||
456 | if (property == priv->rotation_prop) { | 339 | if (property == priv->rotation_prop) { |
457 | struct omap_overlay *ovl = omap_plane->ovl; | 340 | DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val); |
458 | |||
459 | DBG("%s: rotation: %02x", ovl->name, (uint32_t)val); | ||
460 | omap_plane->win.rotation = val; | 341 | omap_plane->win.rotation = val; |
461 | 342 | ret = apply(plane); | |
462 | if (ovl->is_enabled(ovl)) | ||
463 | ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
464 | else | ||
465 | ret = 0; | ||
466 | } else if (property == priv->zorder_prop) { | 343 | } else if (property == priv->zorder_prop) { |
467 | struct omap_overlay *ovl = omap_plane->ovl; | 344 | DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val); |
468 | |||
469 | DBG("%s: zorder: %d", ovl->name, (uint32_t)val); | ||
470 | omap_plane->info.zorder = val; | 345 | omap_plane->info.zorder = val; |
471 | 346 | ret = apply(plane); | |
472 | if (ovl->is_enabled(ovl)) | ||
473 | ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
474 | else | ||
475 | ret = 0; | ||
476 | } | 347 | } |
477 | 348 | ||
478 | return ret; | 349 | return ret; |
@@ -485,20 +356,38 @@ static const struct drm_plane_funcs omap_plane_funcs = { | |||
485 | .set_property = omap_plane_set_property, | 356 | .set_property = omap_plane_set_property, |
486 | }; | 357 | }; |
487 | 358 | ||
359 | static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
360 | { | ||
361 | struct omap_plane *omap_plane = | ||
362 | container_of(irq, struct omap_plane, error_irq); | ||
363 | DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus); | ||
364 | } | ||
365 | |||
366 | static const char *plane_names[] = { | ||
367 | [OMAP_DSS_GFX] = "gfx", | ||
368 | [OMAP_DSS_VIDEO1] = "vid1", | ||
369 | [OMAP_DSS_VIDEO2] = "vid2", | ||
370 | [OMAP_DSS_VIDEO3] = "vid3", | ||
371 | }; | ||
372 | |||
373 | static const uint32_t error_irqs[] = { | ||
374 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
375 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
376 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
377 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
378 | }; | ||
379 | |||
488 | /* initialize plane */ | 380 | /* initialize plane */ |
489 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 381 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
490 | struct omap_overlay *ovl, unsigned int possible_crtcs, | 382 | int id, bool private_plane) |
491 | bool priv) | ||
492 | { | 383 | { |
384 | struct omap_drm_private *priv = dev->dev_private; | ||
493 | struct drm_plane *plane = NULL; | 385 | struct drm_plane *plane = NULL; |
494 | struct omap_plane *omap_plane; | 386 | struct omap_plane *omap_plane; |
387 | struct omap_overlay_info *info; | ||
495 | int ret; | 388 | int ret; |
496 | 389 | ||
497 | DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name, | 390 | DBG("%s: priv=%d", plane_names[id], private_plane); |
498 | possible_crtcs, priv); | ||
499 | |||
500 | /* friendly reminder to update table for future hw: */ | ||
501 | WARN_ON(ovl->id >= ARRAY_SIZE(id2irq)); | ||
502 | 391 | ||
503 | omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); | 392 | omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); |
504 | if (!omap_plane) { | 393 | if (!omap_plane) { |
@@ -506,47 +395,50 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, | |||
506 | goto fail; | 395 | goto fail; |
507 | } | 396 | } |
508 | 397 | ||
509 | mutex_init(&omap_plane->unpin_mutex); | ||
510 | |||
511 | ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL); | 398 | ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL); |
512 | if (ret) { | 399 | if (ret) { |
513 | dev_err(dev->dev, "could not allocate unpin FIFO\n"); | 400 | dev_err(dev->dev, "could not allocate unpin FIFO\n"); |
514 | goto fail; | 401 | goto fail; |
515 | } | 402 | } |
516 | 403 | ||
517 | INIT_WORK(&omap_plane->work, unpin_worker); | ||
518 | |||
519 | omap_plane->nformats = omap_framebuffer_get_formats( | 404 | omap_plane->nformats = omap_framebuffer_get_formats( |
520 | omap_plane->formats, ARRAY_SIZE(omap_plane->formats), | 405 | omap_plane->formats, ARRAY_SIZE(omap_plane->formats), |
521 | ovl->supported_modes); | 406 | dss_feat_get_supported_color_modes(id)); |
522 | omap_plane->ovl = ovl; | 407 | omap_plane->id = id; |
408 | omap_plane->name = plane_names[id]; | ||
409 | |||
523 | plane = &omap_plane->base; | 410 | plane = &omap_plane->base; |
524 | 411 | ||
525 | drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs, | 412 | omap_plane->apply.pre_apply = omap_plane_pre_apply; |
526 | omap_plane->formats, omap_plane->nformats, priv); | 413 | omap_plane->apply.post_apply = omap_plane_post_apply; |
414 | |||
415 | omap_plane->error_irq.irqmask = error_irqs[id]; | ||
416 | omap_plane->error_irq.irq = omap_plane_error_irq; | ||
417 | omap_irq_register(dev, &omap_plane->error_irq); | ||
418 | |||
419 | drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, | ||
420 | omap_plane->formats, omap_plane->nformats, private_plane); | ||
527 | 421 | ||
528 | omap_plane_install_properties(plane, &plane->base); | 422 | omap_plane_install_properties(plane, &plane->base); |
529 | 423 | ||
530 | /* get our starting configuration, set defaults for parameters | 424 | /* get our starting configuration, set defaults for parameters |
531 | * we don't currently use, etc: | 425 | * we don't currently use, etc: |
532 | */ | 426 | */ |
533 | ovl->get_overlay_info(ovl, &omap_plane->info); | 427 | info = &omap_plane->info; |
534 | omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA; | 428 | info->rotation_type = OMAP_DSS_ROT_DMA; |
535 | omap_plane->info.rotation = OMAP_DSS_ROT_0; | 429 | info->rotation = OMAP_DSS_ROT_0; |
536 | omap_plane->info.global_alpha = 0xff; | 430 | info->global_alpha = 0xff; |
537 | omap_plane->info.mirror = 0; | 431 | info->mirror = 0; |
538 | 432 | ||
539 | /* Set defaults depending on whether we are a CRTC or overlay | 433 | /* Set defaults depending on whether we are a CRTC or overlay |
540 | * layer. | 434 | * layer. |
541 | * TODO add ioctl to give userspace an API to change this.. this | 435 | * TODO add ioctl to give userspace an API to change this.. this |
542 | * will come in a subsequent patch. | 436 | * will come in a subsequent patch. |
543 | */ | 437 | */ |
544 | if (priv) | 438 | if (private_plane) |
545 | omap_plane->info.zorder = 0; | 439 | omap_plane->info.zorder = 0; |
546 | else | 440 | else |
547 | omap_plane->info.zorder = ovl->id; | 441 | omap_plane->info.zorder = id; |
548 | |||
549 | update_manager(plane); | ||
550 | 442 | ||
551 | return plane; | 443 | return plane; |
552 | 444 | ||
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index ae38475854b5..d10d75e8a33f 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
@@ -937,7 +937,8 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) | |||
937 | 937 | ||
938 | dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), | 938 | dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), |
939 | PCI_DMA_FROMDEVICE); | 939 | PCI_DMA_FROMDEVICE); |
940 | 940 | if (pci_dma_mapping_error(pdev, dma_tmp)) | |
941 | return -1; | ||
941 | if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, | 942 | if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, |
942 | &(priv->rxbufferhead))) { | 943 | &(priv->rxbufferhead))) { |
943 | DMESGE("Unable to allocate mem RX buf"); | 944 | DMESGE("Unable to allocate mem RX buf"); |
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 808aab6fa5ef..a9d78e9651c6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | |||
@@ -1183,6 +1183,8 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, | |||
1183 | pTxFwInfo->TxRate, | 1183 | pTxFwInfo->TxRate, |
1184 | cb_desc); | 1184 | cb_desc); |
1185 | 1185 | ||
1186 | if (pci_dma_mapping_error(priv->pdev, mapping)) | ||
1187 | RT_TRACE(COMP_ERR, "DMA Mapping error\n");; | ||
1186 | if (cb_desc->bAMPDUEnable) { | 1188 | if (cb_desc->bAMPDUEnable) { |
1187 | pTxFwInfo->AllowAggregation = 1; | 1189 | pTxFwInfo->AllowAggregation = 1; |
1188 | pTxFwInfo->RxMF = cb_desc->ampdu_factor; | 1190 | pTxFwInfo->RxMF = cb_desc->ampdu_factor; |
@@ -1280,6 +1282,8 @@ void rtl8192_tx_fill_cmd_desc(struct net_device *dev, | |||
1280 | dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, | 1282 | dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, |
1281 | PCI_DMA_TODEVICE); | 1283 | PCI_DMA_TODEVICE); |
1282 | 1284 | ||
1285 | if (pci_dma_mapping_error(priv->pdev, mapping)) | ||
1286 | RT_TRACE(COMP_ERR, "DMA Mapping error\n");; | ||
1283 | memset(entry, 0, 12); | 1287 | memset(entry, 0, 12); |
1284 | entry->LINIP = cb_desc->bLastIniPkt; | 1288 | entry->LINIP = cb_desc->bLastIniPkt; |
1285 | entry->FirstSeg = 1; | 1289 | entry->FirstSeg = 1; |
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 1a70f324552f..4ebf99b30975 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c | |||
@@ -2104,7 +2104,10 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev) | |||
2104 | skb_tail_pointer_rsl(skb), | 2104 | skb_tail_pointer_rsl(skb), |
2105 | priv->rxbuffersize, | 2105 | priv->rxbuffersize, |
2106 | PCI_DMA_FROMDEVICE); | 2106 | PCI_DMA_FROMDEVICE); |
2107 | 2107 | if (pci_dma_mapping_error(priv->pdev, *mapping)) { | |
2108 | dev_kfree_skb_any(skb); | ||
2109 | return -1; | ||
2110 | } | ||
2108 | entry->BufferAddress = cpu_to_le32(*mapping); | 2111 | entry->BufferAddress = cpu_to_le32(*mapping); |
2109 | 2112 | ||
2110 | entry->Length = priv->rxbuffersize; | 2113 | entry->Length = priv->rxbuffersize; |
@@ -2397,7 +2400,11 @@ static void rtl8192_rx_normal(struct net_device *dev) | |||
2397 | skb_tail_pointer_rsl(skb), | 2400 | skb_tail_pointer_rsl(skb), |
2398 | priv->rxbuffersize, | 2401 | priv->rxbuffersize, |
2399 | PCI_DMA_FROMDEVICE); | 2402 | PCI_DMA_FROMDEVICE); |
2400 | 2403 | if (pci_dma_mapping_error(priv->pdev, | |
2404 | *((dma_addr_t *)skb->cb))) { | ||
2405 | dev_kfree_skb_any(skb); | ||
2406 | return; | ||
2407 | } | ||
2401 | } | 2408 | } |
2402 | done: | 2409 | done: |
2403 | pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); | 2410 | pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); |
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 6b73843e580a..a96cd06d69dd 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c | |||
@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { | |||
63 | {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ | 63 | {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ |
64 | /* Belkin */ | 64 | /* Belkin */ |
65 | {USB_DEVICE(0x050D, 0x945A)}, | 65 | {USB_DEVICE(0x050D, 0x945A)}, |
66 | /* ISY IWL - Belkin clone */ | ||
67 | {USB_DEVICE(0x050D, 0x11F1)}, | ||
66 | /* Corega */ | 68 | /* Corega */ |
67 | {USB_DEVICE(0x07AA, 0x0047)}, | 69 | {USB_DEVICE(0x07AA, 0x0047)}, |
68 | /* D-Link */ | 70 | /* D-Link */ |
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig index ac87c5e38dee..1facad625554 100644 --- a/drivers/staging/sb105x/Kconfig +++ b/drivers/staging/sb105x/Kconfig | |||
@@ -2,6 +2,7 @@ config SB105X | |||
2 | tristate "SystemBase PCI Multiport UART" | 2 | tristate "SystemBase PCI Multiport UART" |
3 | select SERIAL_CORE | 3 | select SERIAL_CORE |
4 | depends on PCI | 4 | depends on PCI |
5 | depends on X86 | ||
5 | help | 6 | help |
6 | A driver for the SystemBase Multi-2/PCI serial card | 7 | A driver for the SystemBase Multi-2/PCI serial card |
7 | 8 | ||
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index edb2a85b9d52..9464f3874346 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c | |||
@@ -3054,6 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) | |||
3054 | sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); | 3054 | sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); |
3055 | } | 3055 | } |
3056 | break; | 3056 | break; |
3057 | #ifdef CONFIG_PARPORT_PC | ||
3057 | case PCI_DEVICE_ID_MP2S1P : | 3058 | case PCI_DEVICE_ID_MP2S1P : |
3058 | sbdev->nr_ports = 2; | 3059 | sbdev->nr_ports = 2; |
3059 | 3060 | ||
@@ -3073,6 +3074,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) | |||
3073 | /* add PC compatible parallel port */ | 3074 | /* add PC compatible parallel port */ |
3074 | parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0); | 3075 | parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0); |
3075 | break; | 3076 | break; |
3077 | #endif | ||
3076 | } | 3078 | } |
3077 | 3079 | ||
3078 | ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name); | 3080 | ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name); |
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index df9533798095..7616f058a00b 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c | |||
@@ -342,7 +342,7 @@ int synth_init(char *synth_name) | |||
342 | 342 | ||
343 | mutex_lock(&spk_mutex); | 343 | mutex_lock(&spk_mutex); |
344 | /* First, check if we already have it loaded. */ | 344 | /* First, check if we already have it loaded. */ |
345 | for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) | 345 | for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) |
346 | if (strcmp(synths[i]->name, synth_name) == 0) | 346 | if (strcmp(synths[i]->name, synth_name) == 0) |
347 | synth = synths[i]; | 347 | synth = synths[i]; |
348 | 348 | ||
@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth) | |||
423 | int i; | 423 | int i; |
424 | int status = 0; | 424 | int status = 0; |
425 | mutex_lock(&spk_mutex); | 425 | mutex_lock(&spk_mutex); |
426 | for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) | 426 | for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) |
427 | /* synth_remove() is responsible for rotating the array down */ | 427 | /* synth_remove() is responsible for rotating the array down */ |
428 | if (in_synth == synths[i]) { | 428 | if (in_synth == synths[i]) { |
429 | mutex_unlock(&spk_mutex); | 429 | mutex_unlock(&spk_mutex); |
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h index 543a127c7d4d..b783bfa59b1c 100644 --- a/drivers/staging/tidspbridge/core/_tiomap.h +++ b/drivers/staging/tidspbridge/core/_tiomap.h | |||
@@ -31,7 +31,7 @@ | |||
31 | * driver should read or write to PRM/CM registers directly; they | 31 | * driver should read or write to PRM/CM registers directly; they |
32 | * should rely on OMAP core code to do this. | 32 | * should rely on OMAP core code to do this. |
33 | */ | 33 | */ |
34 | #include <mach-omap2/cm2xxx_3xxx.h> | 34 | #include <mach-omap2/cm3xxx.h> |
35 | #include <mach-omap2/prm-regbits-34xx.h> | 35 | #include <mach-omap2/prm-regbits-34xx.h> |
36 | #include <mach-omap2/cm-regbits-34xx.h> | 36 | #include <mach-omap2/cm-regbits-34xx.h> |
37 | #include <dspbridge/devdefs.h> | 37 | #include <dspbridge/devdefs.h> |
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index b647207928b1..2f084e181d39 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c | |||
@@ -121,9 +121,13 @@ void dsp_clk_exit(void) | |||
121 | for (i = 0; i < DM_TIMER_CLOCKS; i++) | 121 | for (i = 0; i < DM_TIMER_CLOCKS; i++) |
122 | omap_dm_timer_free(timer[i]); | 122 | omap_dm_timer_free(timer[i]); |
123 | 123 | ||
124 | clk_unprepare(iva2_clk); | ||
124 | clk_put(iva2_clk); | 125 | clk_put(iva2_clk); |
126 | clk_unprepare(ssi.sst_fck); | ||
125 | clk_put(ssi.sst_fck); | 127 | clk_put(ssi.sst_fck); |
128 | clk_unprepare(ssi.ssr_fck); | ||
126 | clk_put(ssi.ssr_fck); | 129 | clk_put(ssi.ssr_fck); |
130 | clk_unprepare(ssi.ick); | ||
127 | clk_put(ssi.ick); | 131 | clk_put(ssi.ick); |
128 | } | 132 | } |
129 | 133 | ||
@@ -145,14 +149,21 @@ void dsp_clk_init(void) | |||
145 | iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); | 149 | iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); |
146 | if (IS_ERR(iva2_clk)) | 150 | if (IS_ERR(iva2_clk)) |
147 | dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); | 151 | dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); |
152 | else | ||
153 | clk_prepare(iva2_clk); | ||
148 | 154 | ||
149 | ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck"); | 155 | ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck"); |
150 | ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck"); | 156 | ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck"); |
151 | ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick"); | 157 | ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick"); |
152 | 158 | ||
153 | if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) | 159 | if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) { |
154 | dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n", | 160 | dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n", |
155 | ssi.sst_fck, ssi.ssr_fck, ssi.ick); | 161 | ssi.sst_fck, ssi.ssr_fck, ssi.ick); |
162 | } else { | ||
163 | clk_prepare(ssi.sst_fck); | ||
164 | clk_prepare(ssi.ssr_fck); | ||
165 | clk_prepare(ssi.ick); | ||
166 | } | ||
156 | } | 167 | } |
157 | 168 | ||
158 | /** | 169 | /** |
diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c index 1dce36fb828f..7ff0e6c98039 100644 --- a/drivers/staging/tidspbridge/core/wdt.c +++ b/drivers/staging/tidspbridge/core/wdt.c | |||
@@ -63,11 +63,15 @@ int dsp_wdt_init(void) | |||
63 | dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); | 63 | dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); |
64 | 64 | ||
65 | if (!IS_ERR(dsp_wdt.fclk)) { | 65 | if (!IS_ERR(dsp_wdt.fclk)) { |
66 | clk_prepare(dsp_wdt.fclk); | ||
67 | |||
66 | dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); | 68 | dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); |
67 | if (IS_ERR(dsp_wdt.iclk)) { | 69 | if (IS_ERR(dsp_wdt.iclk)) { |
68 | clk_put(dsp_wdt.fclk); | 70 | clk_put(dsp_wdt.fclk); |
69 | dsp_wdt.fclk = NULL; | 71 | dsp_wdt.fclk = NULL; |
70 | ret = -EFAULT; | 72 | ret = -EFAULT; |
73 | } else { | ||
74 | clk_prepare(dsp_wdt.iclk); | ||
71 | } | 75 | } |
72 | } else | 76 | } else |
73 | ret = -EFAULT; | 77 | ret = -EFAULT; |
@@ -95,10 +99,14 @@ void dsp_wdt_exit(void) | |||
95 | free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); | 99 | free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); |
96 | tasklet_kill(&dsp_wdt.wdt3_tasklet); | 100 | tasklet_kill(&dsp_wdt.wdt3_tasklet); |
97 | 101 | ||
98 | if (dsp_wdt.fclk) | 102 | if (dsp_wdt.fclk) { |
103 | clk_unprepare(dsp_wdt.fclk); | ||
99 | clk_put(dsp_wdt.fclk); | 104 | clk_put(dsp_wdt.fclk); |
100 | if (dsp_wdt.iclk) | 105 | } |
106 | if (dsp_wdt.iclk) { | ||
107 | clk_unprepare(dsp_wdt.iclk); | ||
101 | clk_put(dsp_wdt.iclk); | 108 | clk_put(dsp_wdt.iclk); |
109 | } | ||
102 | 110 | ||
103 | dsp_wdt.fclk = NULL; | 111 | dsp_wdt.fclk = NULL; |
104 | dsp_wdt.iclk = NULL; | 112 | dsp_wdt.iclk = NULL; |
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 0331178ca3b3..bf73ba26e88a 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c | |||
@@ -162,11 +162,9 @@ static struct vme_driver pio2_driver = { | |||
162 | 162 | ||
163 | static int __init pio2_init(void) | 163 | static int __init pio2_init(void) |
164 | { | 164 | { |
165 | int retval = 0; | ||
166 | |||
167 | if (bus_num == 0) { | 165 | if (bus_num == 0) { |
168 | pr_err("No cards, skipping registration\n"); | 166 | pr_err("No cards, skipping registration\n"); |
169 | goto err_nocard; | 167 | return -ENODEV; |
170 | } | 168 | } |
171 | 169 | ||
172 | if (bus_num > PIO2_CARDS_MAX) { | 170 | if (bus_num > PIO2_CARDS_MAX) { |
@@ -176,15 +174,7 @@ static int __init pio2_init(void) | |||
176 | } | 174 | } |
177 | 175 | ||
178 | /* Register the PIO2 driver */ | 176 | /* Register the PIO2 driver */ |
179 | retval = vme_register_driver(&pio2_driver, bus_num); | 177 | return vme_register_driver(&pio2_driver, bus_num); |
180 | if (retval != 0) | ||
181 | goto err_reg; | ||
182 | |||
183 | return retval; | ||
184 | |||
185 | err_reg: | ||
186 | err_nocard: | ||
187 | return retval; | ||
188 | } | 178 | } |
189 | 179 | ||
190 | static int pio2_match(struct vme_dev *vdev) | 180 | static int pio2_match(struct vme_dev *vdev) |
diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index 6b2ec390e775..806cbf72fb59 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h | |||
@@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject { | |||
90 | } SRSNCapObject, *PSRSNCapObject; | 90 | } SRSNCapObject, *PSRSNCapObject; |
91 | 91 | ||
92 | // BSS info(AP) | 92 | // BSS info(AP) |
93 | #pragma pack(1) | ||
94 | typedef struct tagKnownBSS { | 93 | typedef struct tagKnownBSS { |
95 | // BSS info | 94 | // BSS info |
96 | BOOL bActive; | 95 | BOOL bActive; |
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index 5d8faf9f96ec..e0d2b07ba608 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "device.h" | 34 | #include "device.h" |
35 | 35 | ||
36 | /*--------------------- Export Definitions -------------------------*/ | 36 | /*--------------------- Export Definitions -------------------------*/ |
37 | #pragma pack(1) | ||
38 | typedef struct tagSINTData { | 37 | typedef struct tagSINTData { |
39 | BYTE byTSR0; | 38 | BYTE byTSR0; |
40 | BYTE byPkt0; | 39 | BYTE byPkt0; |
diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751d..ae6e2d237b20 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h | |||
@@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { | |||
95 | // Ioctl interface structure | 95 | // Ioctl interface structure |
96 | // Command structure | 96 | // Command structure |
97 | // | 97 | // |
98 | #pragma pack(1) | ||
99 | typedef struct tagSCmdRequest { | 98 | typedef struct tagSCmdRequest { |
100 | u8 name[16]; | 99 | u8 name[16]; |
101 | void *data; | 100 | void *data; |
102 | u16 wResult; | 101 | u16 wResult; |
103 | u16 wCmdCode; | 102 | u16 wCmdCode; |
104 | } SCmdRequest, *PSCmdRequest; | 103 | } __packed SCmdRequest, *PSCmdRequest; |
105 | 104 | ||
106 | // | 105 | // |
107 | // Scan | 106 | // Scan |
@@ -111,7 +110,7 @@ typedef struct tagSCmdScan { | |||
111 | 110 | ||
112 | u8 ssid[SSID_MAXLEN + 2]; | 111 | u8 ssid[SSID_MAXLEN + 2]; |
113 | 112 | ||
114 | } SCmdScan, *PSCmdScan; | 113 | } __packed SCmdScan, *PSCmdScan; |
115 | 114 | ||
116 | // | 115 | // |
117 | // BSS Join | 116 | // BSS Join |
@@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { | |||
126 | BOOL bPSEnable; | 125 | BOOL bPSEnable; |
127 | BOOL bShareKeyAuth; | 126 | BOOL bShareKeyAuth; |
128 | 127 | ||
129 | } SCmdBSSJoin, *PSCmdBSSJoin; | 128 | } __packed SCmdBSSJoin, *PSCmdBSSJoin; |
130 | 129 | ||
131 | // | 130 | // |
132 | // Zonetype Setting | 131 | // Zonetype Setting |
@@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { | |||
137 | BOOL bWrite; | 136 | BOOL bWrite; |
138 | WZONETYPE ZoneType; | 137 | WZONETYPE ZoneType; |
139 | 138 | ||
140 | } SCmdZoneTypeSet, *PSCmdZoneTypeSet; | 139 | } __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; |
141 | 140 | ||
142 | typedef struct tagSWPAResult { | 141 | typedef struct tagSWPAResult { |
143 | char ifname[100]; | 142 | char ifname[100]; |
@@ -145,7 +144,7 @@ typedef struct tagSWPAResult { | |||
145 | u8 key_mgmt; | 144 | u8 key_mgmt; |
146 | u8 eap_type; | 145 | u8 eap_type; |
147 | BOOL authenticated; | 146 | BOOL authenticated; |
148 | } SWPAResult, *PSWPAResult; | 147 | } __packed SWPAResult, *PSWPAResult; |
149 | 148 | ||
150 | typedef struct tagSCmdStartAP { | 149 | typedef struct tagSCmdStartAP { |
151 | 150 | ||
@@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { | |||
157 | BOOL bShareKeyAuth; | 156 | BOOL bShareKeyAuth; |
158 | u8 byBasicRate; | 157 | u8 byBasicRate; |
159 | 158 | ||
160 | } SCmdStartAP, *PSCmdStartAP; | 159 | } __packed SCmdStartAP, *PSCmdStartAP; |
161 | 160 | ||
162 | typedef struct tagSCmdSetWEP { | 161 | typedef struct tagSCmdSetWEP { |
163 | 162 | ||
@@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { | |||
167 | BOOL bWepKeyAvailable[WEP_NKEYS]; | 166 | BOOL bWepKeyAvailable[WEP_NKEYS]; |
168 | u32 auWepKeyLength[WEP_NKEYS]; | 167 | u32 auWepKeyLength[WEP_NKEYS]; |
169 | 168 | ||
170 | } SCmdSetWEP, *PSCmdSetWEP; | 169 | } __packed SCmdSetWEP, *PSCmdSetWEP; |
171 | 170 | ||
172 | typedef struct tagSBSSIDItem { | 171 | typedef struct tagSBSSIDItem { |
173 | 172 | ||
@@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { | |||
180 | BOOL bWEPOn; | 179 | BOOL bWEPOn; |
181 | u32 uRSSI; | 180 | u32 uRSSI; |
182 | 181 | ||
183 | } SBSSIDItem; | 182 | } __packed SBSSIDItem; |
184 | 183 | ||
185 | 184 | ||
186 | typedef struct tagSBSSIDList { | 185 | typedef struct tagSBSSIDList { |
187 | 186 | ||
188 | u32 uItem; | 187 | u32 uItem; |
189 | SBSSIDItem sBSSIDList[0]; | 188 | SBSSIDItem sBSSIDList[0]; |
190 | } SBSSIDList, *PSBSSIDList; | 189 | } __packed SBSSIDList, *PSBSSIDList; |
191 | 190 | ||
192 | 191 | ||
193 | typedef struct tagSNodeItem { | 192 | typedef struct tagSNodeItem { |
@@ -208,7 +207,7 @@ typedef struct tagSNodeItem { | |||
208 | u32 uTxAttempts; | 207 | u32 uTxAttempts; |
209 | u16 wFailureRatio; | 208 | u16 wFailureRatio; |
210 | 209 | ||
211 | } SNodeItem; | 210 | } __packed SNodeItem; |
212 | 211 | ||
213 | 212 | ||
214 | typedef struct tagSNodeList { | 213 | typedef struct tagSNodeList { |
@@ -216,7 +215,7 @@ typedef struct tagSNodeList { | |||
216 | u32 uItem; | 215 | u32 uItem; |
217 | SNodeItem sNodeList[0]; | 216 | SNodeItem sNodeList[0]; |
218 | 217 | ||
219 | } SNodeList, *PSNodeList; | 218 | } __packed SNodeList, *PSNodeList; |
220 | 219 | ||
221 | 220 | ||
222 | typedef struct tagSCmdLinkStatus { | 221 | typedef struct tagSCmdLinkStatus { |
@@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { | |||
229 | u32 uChannel; | 228 | u32 uChannel; |
230 | u32 uLinkRate; | 229 | u32 uLinkRate; |
231 | 230 | ||
232 | } SCmdLinkStatus, *PSCmdLinkStatus; | 231 | } __packed SCmdLinkStatus, *PSCmdLinkStatus; |
233 | 232 | ||
234 | // | 233 | // |
235 | // 802.11 counter | 234 | // 802.11 counter |
@@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { | |||
247 | u32 ReceivedFragmentCount; | 246 | u32 ReceivedFragmentCount; |
248 | u32 MulticastReceivedFrameCount; | 247 | u32 MulticastReceivedFrameCount; |
249 | u32 FCSErrorCount; | 248 | u32 FCSErrorCount; |
250 | } SDot11MIBCount, *PSDot11MIBCount; | 249 | } __packed SDot11MIBCount, *PSDot11MIBCount; |
251 | 250 | ||
252 | 251 | ||
253 | 252 | ||
@@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { | |||
355 | u32 ullTxBroadcastBytes[2]; | 354 | u32 ullTxBroadcastBytes[2]; |
356 | u32 ullTxMulticastBytes[2]; | 355 | u32 ullTxMulticastBytes[2]; |
357 | u32 ullTxDirectedBytes[2]; | 356 | u32 ullTxDirectedBytes[2]; |
358 | } SStatMIBCount, *PSStatMIBCount; | 357 | } __packed SStatMIBCount, *PSStatMIBCount; |
359 | 358 | ||
360 | typedef struct tagSCmdValue { | 359 | typedef struct tagSCmdValue { |
361 | 360 | ||
362 | u32 dwValue; | 361 | u32 dwValue; |
363 | 362 | ||
364 | } SCmdValue, *PSCmdValue; | 363 | } __packed SCmdValue, *PSCmdValue; |
365 | 364 | ||
366 | // | 365 | // |
367 | // hostapd & viawget ioctl related | 366 | // hostapd & viawget ioctl related |
@@ -431,7 +430,7 @@ struct viawget_hostapd_param { | |||
431 | u8 ssid[32]; | 430 | u8 ssid[32]; |
432 | } scan_req; | 431 | } scan_req; |
433 | } u; | 432 | } u; |
434 | }; | 433 | } __packed; |
435 | 434 | ||
436 | /*--------------------- Export Classes ----------------------------*/ | 435 | /*--------------------- Export Classes ----------------------------*/ |
437 | 436 | ||
diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e2..2522ddec718d 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h | |||
@@ -67,12 +67,11 @@ enum { | |||
67 | 67 | ||
68 | 68 | ||
69 | 69 | ||
70 | #pragma pack(1) | ||
71 | typedef struct viawget_wpa_header { | 70 | typedef struct viawget_wpa_header { |
72 | u8 type; | 71 | u8 type; |
73 | u16 req_ie_len; | 72 | u16 req_ie_len; |
74 | u16 resp_ie_len; | 73 | u16 resp_ie_len; |
75 | } viawget_wpa_header; | 74 | } __packed viawget_wpa_header; |
76 | 75 | ||
77 | struct viawget_wpa_param { | 76 | struct viawget_wpa_param { |
78 | u32 cmd; | 77 | u32 cmd; |
@@ -113,9 +112,8 @@ struct viawget_wpa_param { | |||
113 | u8 *buf; | 112 | u8 *buf; |
114 | } scan_results; | 113 | } scan_results; |
115 | } u; | 114 | } u; |
116 | }; | 115 | } __packed; |
117 | 116 | ||
118 | #pragma pack(1) | ||
119 | struct viawget_scan_result { | 117 | struct viawget_scan_result { |
120 | u8 bssid[6]; | 118 | u8 bssid[6]; |
121 | u8 ssid[32]; | 119 | u8 ssid[32]; |
@@ -130,7 +128,7 @@ struct viawget_scan_result { | |||
130 | int noise; | 128 | int noise; |
131 | int level; | 129 | int level; |
132 | int maxrate; | 130 | int maxrate; |
133 | }; | 131 | } __packed; |
134 | 132 | ||
135 | /*--------------------- Export Classes ----------------------------*/ | 133 | /*--------------------- Export Classes ----------------------------*/ |
136 | 134 | ||
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 18c06a59c091..1d31eab19d16 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c | |||
@@ -638,8 +638,8 @@ int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
638 | } | 638 | } |
639 | 639 | ||
640 | 640 | ||
641 | int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, | 641 | int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, |
642 | int mbm) | 642 | enum nl80211_tx_power_setting type, int mbm) |
643 | { | 643 | { |
644 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); | 644 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); |
645 | wlandevice_t *wlandev = priv->wlandev; | 645 | wlandevice_t *wlandev = priv->wlandev; |
@@ -665,7 +665,8 @@ exit: | |||
665 | return err; | 665 | return err; |
666 | } | 666 | } |
667 | 667 | ||
668 | int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) | 668 | int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, |
669 | int *dbm) | ||
669 | { | 670 | { |
670 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); | 671 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); |
671 | wlandevice_t *wlandev = priv->wlandev; | 672 | wlandevice_t *wlandev = priv->wlandev; |
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 4efa9bc0fcf0..89bfd858bb28 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c | |||
@@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) | |||
406 | /* SSID */ | 406 | /* SSID */ |
407 | req->ssid.status = P80211ENUM_msgitem_status_data_ok; | 407 | req->ssid.status = P80211ENUM_msgitem_status_data_ok; |
408 | req->ssid.data.len = le16_to_cpu(item->ssid.len); | 408 | req->ssid.data.len = le16_to_cpu(item->ssid.len); |
409 | req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); | 409 | req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); |
410 | memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); | 410 | memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); |
411 | 411 | ||
412 | /* supported rates */ | 412 | /* supported rates */ |
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index fb4a7c94aed3..f2a73bd739fb 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c | |||
@@ -265,7 +265,7 @@ out_cleanup: | |||
265 | static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | 265 | static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, |
266 | int offset) | 266 | int offset) |
267 | { | 267 | { |
268 | int ret; | 268 | int ret = 0; |
269 | size_t clen; | 269 | size_t clen; |
270 | unsigned long handle; | 270 | unsigned long handle; |
271 | struct page *page; | 271 | struct page *page; |
@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
286 | goto out; | 286 | goto out; |
287 | } | 287 | } |
288 | ret = zram_decompress_page(zram, uncmem, index); | 288 | ret = zram_decompress_page(zram, uncmem, index); |
289 | if (ret) { | 289 | if (ret) |
290 | kfree(uncmem); | ||
291 | goto out; | 290 | goto out; |
292 | } | ||
293 | } | 291 | } |
294 | 292 | ||
295 | /* | 293 | /* |
@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
302 | 300 | ||
303 | user_mem = kmap_atomic(page); | 301 | user_mem = kmap_atomic(page); |
304 | 302 | ||
305 | if (is_partial_io(bvec)) | 303 | if (is_partial_io(bvec)) { |
306 | memcpy(uncmem + offset, user_mem + bvec->bv_offset, | 304 | memcpy(uncmem + offset, user_mem + bvec->bv_offset, |
307 | bvec->bv_len); | 305 | bvec->bv_len); |
308 | else | 306 | kunmap_atomic(user_mem); |
307 | user_mem = NULL; | ||
308 | } else { | ||
309 | uncmem = user_mem; | 309 | uncmem = user_mem; |
310 | } | ||
310 | 311 | ||
311 | if (page_zero_filled(uncmem)) { | 312 | if (page_zero_filled(uncmem)) { |
312 | kunmap_atomic(user_mem); | 313 | if (!is_partial_io(bvec)) |
313 | if (is_partial_io(bvec)) | 314 | kunmap_atomic(user_mem); |
314 | kfree(uncmem); | ||
315 | zram_stat_inc(&zram->stats.pages_zero); | 315 | zram_stat_inc(&zram->stats.pages_zero); |
316 | zram_set_flag(zram, index, ZRAM_ZERO); | 316 | zram_set_flag(zram, index, ZRAM_ZERO); |
317 | ret = 0; | 317 | ret = 0; |
@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
321 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, | 321 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, |
322 | zram->compress_workmem); | 322 | zram->compress_workmem); |
323 | 323 | ||
324 | kunmap_atomic(user_mem); | 324 | if (!is_partial_io(bvec)) { |
325 | if (is_partial_io(bvec)) | 325 | kunmap_atomic(user_mem); |
326 | kfree(uncmem); | 326 | user_mem = NULL; |
327 | uncmem = NULL; | ||
328 | } | ||
327 | 329 | ||
328 | if (unlikely(ret != LZO_E_OK)) { | 330 | if (unlikely(ret != LZO_E_OK)) { |
329 | pr_err("Compression failed! err=%d\n", ret); | 331 | pr_err("Compression failed! err=%d\n", ret); |
@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
332 | 334 | ||
333 | if (unlikely(clen > max_zpage_size)) { | 335 | if (unlikely(clen > max_zpage_size)) { |
334 | zram_stat_inc(&zram->stats.bad_compress); | 336 | zram_stat_inc(&zram->stats.bad_compress); |
335 | src = uncmem; | ||
336 | clen = PAGE_SIZE; | 337 | clen = PAGE_SIZE; |
338 | src = NULL; | ||
339 | if (is_partial_io(bvec)) | ||
340 | src = uncmem; | ||
337 | } | 341 | } |
338 | 342 | ||
339 | handle = zs_malloc(zram->mem_pool, clen); | 343 | handle = zs_malloc(zram->mem_pool, clen); |
@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
345 | } | 349 | } |
346 | cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); | 350 | cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); |
347 | 351 | ||
352 | if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) | ||
353 | src = kmap_atomic(page); | ||
348 | memcpy(cmem, src, clen); | 354 | memcpy(cmem, src, clen); |
355 | if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) | ||
356 | kunmap_atomic(src); | ||
349 | 357 | ||
350 | zs_unmap_object(zram->mem_pool, handle); | 358 | zs_unmap_object(zram->mem_pool, handle); |
351 | 359 | ||
@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
358 | if (clen <= PAGE_SIZE / 2) | 366 | if (clen <= PAGE_SIZE / 2) |
359 | zram_stat_inc(&zram->stats.good_compress); | 367 | zram_stat_inc(&zram->stats.good_compress); |
360 | 368 | ||
361 | return 0; | ||
362 | |||
363 | out: | 369 | out: |
370 | if (is_partial_io(bvec)) | ||
371 | kfree(uncmem); | ||
372 | |||
364 | if (ret) | 373 | if (ret) |
365 | zram_stat64_inc(zram, &zram->stats.failed_writes); | 374 | zram_stat64_inc(zram, &zram->stats.failed_writes); |
366 | return ret; | 375 | return ret; |
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 9ac4c151eae4..ba6091bf93fc 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c | |||
@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) | |||
372 | * made generic here. | 372 | * made generic here. |
373 | */ | 373 | */ |
374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && | 374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && |
375 | iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { | 375 | iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { |
376 | list_del(&cmd->i_conn_node); | 376 | list_del(&cmd->i_conn_node); |
377 | spin_unlock_bh(&conn->cmd_lock); | 377 | spin_unlock_bh(&conn->cmd_lock); |
378 | iscsit_free_cmd(cmd); | 378 | iscsit_free_cmd(cmd); |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 85140f7dde1e..7d4ec02e29a9 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
@@ -212,7 +212,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
212 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; | 212 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; |
213 | unsigned char *buf; | 213 | unsigned char *buf; |
214 | unsigned char *ptr; | 214 | unsigned char *ptr; |
215 | sense_reason_t rc; | 215 | sense_reason_t rc = TCM_NO_SENSE; |
216 | u32 len = 4; /* Skip over RESERVED area in header */ | 216 | u32 len = 4; /* Skip over RESERVED area in header */ |
217 | int alua_access_state, primary = 0; | 217 | int alua_access_state, primary = 0; |
218 | u16 tg_pt_id, rtpi; | 218 | u16 tg_pt_id, rtpi; |
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index e35dbf85841f..8e0290b38e43 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
@@ -2053,7 +2053,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, | |||
2053 | /* Used for APTPL metadata w/ UNREGISTER */ | 2053 | /* Used for APTPL metadata w/ UNREGISTER */ |
2054 | unsigned char *pr_aptpl_buf = NULL; | 2054 | unsigned char *pr_aptpl_buf = NULL; |
2055 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; | 2055 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; |
2056 | sense_reason_t ret; | 2056 | sense_reason_t ret = TCM_NO_SENSE; |
2057 | int pr_holder = 0, type; | 2057 | int pr_holder = 0, type; |
2058 | 2058 | ||
2059 | if (!se_sess || !se_lun) { | 2059 | if (!se_sess || !se_lun) { |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c23c76ccef65..bd587b70661a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -541,9 +541,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) | |||
541 | 541 | ||
542 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) | 542 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) |
543 | { | 543 | { |
544 | if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) | ||
545 | transport_lun_remove_cmd(cmd); | ||
546 | |||
547 | if (transport_cmd_check_stop_to_fabric(cmd)) | 544 | if (transport_cmd_check_stop_to_fabric(cmd)) |
548 | return; | 545 | return; |
549 | if (remove) | 546 | if (remove) |
@@ -1396,6 +1393,8 @@ static void target_complete_tmr_failure(struct work_struct *work) | |||
1396 | 1393 | ||
1397 | se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; | 1394 | se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; |
1398 | se_cmd->se_tfo->queue_tm_rsp(se_cmd); | 1395 | se_cmd->se_tfo->queue_tm_rsp(se_cmd); |
1396 | |||
1397 | transport_cmd_check_stop_to_fabric(se_cmd); | ||
1399 | } | 1398 | } |
1400 | 1399 | ||
1401 | /** | 1400 | /** |
@@ -1688,6 +1687,7 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
1688 | } | 1687 | } |
1689 | 1688 | ||
1690 | cmd->t_state = TRANSPORT_PROCESSING; | 1689 | cmd->t_state = TRANSPORT_PROCESSING; |
1690 | cmd->transport_state |= CMD_T_ACTIVE; | ||
1691 | spin_unlock_irq(&cmd->t_state_lock); | 1691 | spin_unlock_irq(&cmd->t_state_lock); |
1692 | 1692 | ||
1693 | if (!target_handle_task_attr(cmd)) | 1693 | if (!target_handle_task_attr(cmd)) |
@@ -2597,6 +2597,16 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, | |||
2597 | * SENSE KEY values from include/scsi/scsi.h | 2597 | * SENSE KEY values from include/scsi/scsi.h |
2598 | */ | 2598 | */ |
2599 | switch (reason) { | 2599 | switch (reason) { |
2600 | case TCM_NO_SENSE: | ||
2601 | /* CURRENT ERROR */ | ||
2602 | buffer[0] = 0x70; | ||
2603 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; | ||
2604 | /* Not Ready */ | ||
2605 | buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; | ||
2606 | /* NO ADDITIONAL SENSE INFORMATION */ | ||
2607 | buffer[SPC_ASC_KEY_OFFSET] = 0; | ||
2608 | buffer[SPC_ASCQ_KEY_OFFSET] = 0; | ||
2609 | break; | ||
2600 | case TCM_NON_EXISTENT_LUN: | 2610 | case TCM_NON_EXISTENT_LUN: |
2601 | /* CURRENT ERROR */ | 2611 | /* CURRENT ERROR */ |
2602 | buffer[0] = 0x70; | 2612 | buffer[0] = 0x70; |
@@ -2743,7 +2753,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, | |||
2743 | /* ILLEGAL REQUEST */ | 2753 | /* ILLEGAL REQUEST */ |
2744 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | 2754 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; |
2745 | /* LOGICAL UNIT COMMUNICATION FAILURE */ | 2755 | /* LOGICAL UNIT COMMUNICATION FAILURE */ |
2746 | buffer[SPC_ASC_KEY_OFFSET] = 0x80; | 2756 | buffer[SPC_ASC_KEY_OFFSET] = 0x08; |
2747 | break; | 2757 | break; |
2748 | } | 2758 | } |
2749 | /* | 2759 | /* |
@@ -2804,6 +2814,8 @@ void transport_send_task_abort(struct se_cmd *cmd) | |||
2804 | } | 2814 | } |
2805 | cmd->scsi_status = SAM_STAT_TASK_ABORTED; | 2815 | cmd->scsi_status = SAM_STAT_TASK_ABORTED; |
2806 | 2816 | ||
2817 | transport_lun_remove_cmd(cmd); | ||
2818 | |||
2807 | pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," | 2819 | pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," |
2808 | " ITT: 0x%08x\n", cmd->t_task_cdb[0], | 2820 | " ITT: 0x%08x\n", cmd->t_task_cdb[0], |
2809 | cmd->se_tfo->get_task_tag(cmd)); | 2821 | cmd->se_tfo->get_task_tag(cmd)); |
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 12d6fa21e5e1..6659dd36e806 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c | |||
@@ -355,11 +355,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, | |||
355 | 355 | ||
356 | tport = ft_tport_create(rdata->local_port); | 356 | tport = ft_tport_create(rdata->local_port); |
357 | if (!tport) | 357 | if (!tport) |
358 | return 0; /* not a target for this local port */ | 358 | goto not_target; /* not a target for this local port */ |
359 | 359 | ||
360 | acl = ft_acl_get(tport->tpg, rdata); | 360 | acl = ft_acl_get(tport->tpg, rdata); |
361 | if (!acl) | 361 | if (!acl) |
362 | return 0; | 362 | goto not_target; /* no target for this remote */ |
363 | 363 | ||
364 | if (!rspp) | 364 | if (!rspp) |
365 | goto fill; | 365 | goto fill; |
@@ -396,12 +396,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, | |||
396 | 396 | ||
397 | /* | 397 | /* |
398 | * OR in our service parameters with other provider (initiator), if any. | 398 | * OR in our service parameters with other provider (initiator), if any. |
399 | * TBD XXX - indicate RETRY capability? | ||
400 | */ | 399 | */ |
401 | fill: | 400 | fill: |
402 | fcp_parm = ntohl(spp->spp_params); | 401 | fcp_parm = ntohl(spp->spp_params); |
402 | fcp_parm &= ~FCP_SPPF_RETRY; | ||
403 | spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); | 403 | spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); |
404 | return FC_SPP_RESP_ACK; | 404 | return FC_SPP_RESP_ACK; |
405 | |||
406 | not_target: | ||
407 | fcp_parm = ntohl(spp->spp_params); | ||
408 | fcp_parm &= ~FCP_SPPF_TARG_FCN; | ||
409 | spp->spp_params = htonl(fcp_parm); | ||
410 | return 0; | ||
405 | } | 411 | } |
406 | 412 | ||
407 | /** | 413 | /** |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be6a373601b7..79ff3a5e925d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, | |||
441 | return pty_get_pktmode(tty, (int __user *)arg); | 441 | return pty_get_pktmode(tty, (int __user *)arg); |
442 | case TIOCSIG: /* Send signal to other side of pty */ | 442 | case TIOCSIG: /* Send signal to other side of pty */ |
443 | return pty_signal(tty, (int) arg); | 443 | return pty_signal(tty, (int) arg); |
444 | case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */ | ||
445 | return -EINVAL; | ||
444 | } | 446 | } |
445 | return -ENOIOCTLCMD; | 447 | return -ENOIOCTLCMD; |
446 | } | 448 | } |
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d085e3a8ec06..f9320437a649 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = { | |||
300 | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, | 300 | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, |
301 | .flags = UART_CAP_FIFO, | 301 | .flags = UART_CAP_FIFO, |
302 | }, | 302 | }, |
303 | [PORT_BRCM_TRUMANAGE] = { | ||
304 | .name = "TruManage", | ||
305 | .fifo_size = 1, | ||
306 | .tx_loadsz = 1024, | ||
307 | .flags = UART_CAP_HFIFO, | ||
308 | }, | ||
303 | [PORT_8250_CIR] = { | 309 | [PORT_8250_CIR] = { |
304 | .name = "CIR port" | 310 | .name = "CIR port" |
305 | } | 311 | } |
@@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up) | |||
1490 | port->icount.tx++; | 1496 | port->icount.tx++; |
1491 | if (uart_circ_empty(xmit)) | 1497 | if (uart_circ_empty(xmit)) |
1492 | break; | 1498 | break; |
1499 | if (up->capabilities & UART_CAP_HFIFO) { | ||
1500 | if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != | ||
1501 | BOTH_EMPTY) | ||
1502 | break; | ||
1503 | } | ||
1493 | } while (--count > 0); | 1504 | } while (--count > 0); |
1494 | 1505 | ||
1495 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 1506 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 3b4ea84898c2..12caa1292b75 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h | |||
@@ -40,6 +40,7 @@ struct serial8250_config { | |||
40 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ | 40 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ |
41 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ | 41 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ |
42 | #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ | 42 | #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ |
43 | #define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ | ||
43 | 44 | ||
44 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ | 45 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ |
45 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ | 46 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ |
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1d0dba2d562d..096d2ef48b32 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c | |||
@@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) | |||
79 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | 79 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { |
80 | /* Clear the USR and write the LCR again. */ | 80 | /* Clear the USR and write the LCR again. */ |
81 | (void)p->serial_in(p, UART_USR); | 81 | (void)p->serial_in(p, UART_USR); |
82 | p->serial_out(p, d->last_lcr, UART_LCR); | 82 | p->serial_out(p, UART_LCR, d->last_lcr); |
83 | 83 | ||
84 | return 1; | 84 | return 1; |
85 | } | 85 | } |
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 26b9dc012ed0..a27a98e1b066 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv, | |||
1085 | return setup_port(priv, port, 2, idx * 8, 0); | 1085 | return setup_port(priv, port, 2, idx * 8, 0); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static int | ||
1089 | pci_brcm_trumanage_setup(struct serial_private *priv, | ||
1090 | const struct pciserial_board *board, | ||
1091 | struct uart_8250_port *port, int idx) | ||
1092 | { | ||
1093 | int ret = pci_default_setup(priv, board, port, idx); | ||
1094 | |||
1095 | port->port.type = PORT_BRCM_TRUMANAGE; | ||
1096 | port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); | ||
1097 | return ret; | ||
1098 | } | ||
1099 | |||
1088 | static int skip_tx_en_setup(struct serial_private *priv, | 1100 | static int skip_tx_en_setup(struct serial_private *priv, |
1089 | const struct pciserial_board *board, | 1101 | const struct pciserial_board *board, |
1090 | struct uart_8250_port *port, int idx) | 1102 | struct uart_8250_port *port, int idx) |
@@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv, | |||
1301 | #define PCI_VENDOR_ID_AGESTAR 0x5372 | 1313 | #define PCI_VENDOR_ID_AGESTAR 0x5372 |
1302 | #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 | 1314 | #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 |
1303 | #define PCI_VENDOR_ID_ASIX 0x9710 | 1315 | #define PCI_VENDOR_ID_ASIX 0x9710 |
1304 | #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019 | ||
1305 | #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 | 1316 | #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 |
1306 | #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 | 1317 | #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 |
1318 | #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 | ||
1319 | #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a | ||
1307 | 1320 | ||
1308 | 1321 | ||
1309 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 1322 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
@@ -1954,6 +1967,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1954 | .setup = pci_xr17v35x_setup, | 1967 | .setup = pci_xr17v35x_setup, |
1955 | }, | 1968 | }, |
1956 | /* | 1969 | /* |
1970 | * Broadcom TruManage (NetXtreme) | ||
1971 | */ | ||
1972 | { | ||
1973 | .vendor = PCI_VENDOR_ID_BROADCOM, | ||
1974 | .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, | ||
1975 | .subvendor = PCI_ANY_ID, | ||
1976 | .subdevice = PCI_ANY_ID, | ||
1977 | .setup = pci_brcm_trumanage_setup, | ||
1978 | }, | ||
1979 | |||
1980 | /* | ||
1957 | * Default "match everything" terminator entry | 1981 | * Default "match everything" terminator entry |
1958 | */ | 1982 | */ |
1959 | { | 1983 | { |
@@ -2148,6 +2172,7 @@ enum pci_board_num_t { | |||
2148 | pbn_ce4100_1_115200, | 2172 | pbn_ce4100_1_115200, |
2149 | pbn_omegapci, | 2173 | pbn_omegapci, |
2150 | pbn_NETMOS9900_2s_115200, | 2174 | pbn_NETMOS9900_2s_115200, |
2175 | pbn_brcm_trumanage, | ||
2151 | }; | 2176 | }; |
2152 | 2177 | ||
2153 | /* | 2178 | /* |
@@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = { | |||
2246 | 2271 | ||
2247 | [pbn_b0_8_1152000_200] = { | 2272 | [pbn_b0_8_1152000_200] = { |
2248 | .flags = FL_BASE0, | 2273 | .flags = FL_BASE0, |
2249 | .num_ports = 2, | 2274 | .num_ports = 8, |
2250 | .base_baud = 1152000, | 2275 | .base_baud = 1152000, |
2251 | .uart_offset = 0x200, | 2276 | .uart_offset = 0x200, |
2252 | }, | 2277 | }, |
@@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = { | |||
2892 | .num_ports = 2, | 2917 | .num_ports = 2, |
2893 | .base_baud = 115200, | 2918 | .base_baud = 115200, |
2894 | }, | 2919 | }, |
2920 | [pbn_brcm_trumanage] = { | ||
2921 | .flags = FL_BASE0, | ||
2922 | .num_ports = 1, | ||
2923 | .reg_shift = 2, | ||
2924 | .base_baud = 115200, | ||
2925 | }, | ||
2895 | }; | 2926 | }; |
2896 | 2927 | ||
2897 | static const struct pci_device_id blacklist[] = { | 2928 | static const struct pci_device_id blacklist[] = { |
@@ -4471,6 +4502,13 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4471 | pbn_omegapci }, | 4502 | pbn_omegapci }, |
4472 | 4503 | ||
4473 | /* | 4504 | /* |
4505 | * Broadcom TruManage | ||
4506 | */ | ||
4507 | { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, | ||
4508 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
4509 | pbn_brcm_trumanage }, | ||
4510 | |||
4511 | /* | ||
4474 | * AgeStar as-prs2-009 | 4512 | * AgeStar as-prs2-009 |
4475 | */ | 4513 | */ |
4476 | { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, | 4514 | { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94ab0aff..8cb6d8d66a13 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
@@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) | |||
637 | 637 | ||
638 | clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); | 638 | clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); |
639 | mrdy_set_low(ifx_dev); | 639 | mrdy_set_low(ifx_dev); |
640 | del_timer(&ifx_dev->spi_timer); | ||
640 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); | 641 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); |
641 | tasklet_kill(&ifx_dev->io_work_tasklet); | 642 | tasklet_kill(&ifx_dev->io_work_tasklet); |
642 | } | 643 | } |
@@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data) | |||
810 | ifx_dev->spi_xfer.cs_change = 0; | 811 | ifx_dev->spi_xfer.cs_change = 0; |
811 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; | 812 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; |
812 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ | 813 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ |
813 | ifx_dev->spi_xfer.bits_per_word = spi_bpw; | 814 | ifx_dev->spi_xfer.bits_per_word = |
815 | ifx_dev->spi_dev->bits_per_word; | ||
814 | 816 | ||
815 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; | 817 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; |
816 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; | 818 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; |
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 6db23b035efe..e55615eb34ad 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c | |||
@@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s) | |||
253 | struct circ_buf *xmit = &s->port.state->xmit; | 253 | struct circ_buf *xmit = &s->port.state->xmit; |
254 | 254 | ||
255 | if (auart_dma_enabled(s)) { | 255 | if (auart_dma_enabled(s)) { |
256 | int i = 0; | 256 | u32 i = 0; |
257 | int size; | 257 | int size; |
258 | void *buffer = s->tx_dma_buf; | 258 | void *buffer = s->tx_dma_buf; |
259 | 259 | ||
@@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) | |||
412 | 412 | ||
413 | u32 ctrl = readl(u->membase + AUART_CTRL2); | 413 | u32 ctrl = readl(u->membase + AUART_CTRL2); |
414 | 414 | ||
415 | ctrl &= ~AUART_CTRL2_RTSEN; | 415 | ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); |
416 | if (mctrl & TIOCM_RTS) { | 416 | if (mctrl & TIOCM_RTS) { |
417 | if (tty_port_cts_enabled(&u->state->port)) | 417 | if (tty_port_cts_enabled(&u->state->port)) |
418 | ctrl |= AUART_CTRL2_RTSEN; | 418 | ctrl |= AUART_CTRL2_RTSEN; |
419 | else | ||
420 | ctrl |= AUART_CTRL2_RTS; | ||
419 | } | 421 | } |
420 | 422 | ||
421 | s->ctrl = mctrl; | 423 | s->ctrl = mctrl; |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 12e5249d053e..e514b3a4dc57 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, | |||
1006 | 1006 | ||
1007 | ucon &= ucon_mask; | 1007 | ucon &= ucon_mask; |
1008 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | 1008 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); |
1009 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
1010 | 1009 | ||
1011 | /* reset both fifos */ | 1010 | /* reset both fifos */ |
1012 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | 1011 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); |
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 8fd181436a6b..d5ed9f613005 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) | |||
604 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; | 604 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; |
605 | 605 | ||
606 | vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); | 606 | vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); |
607 | if (vt8500_port->clk) { | 607 | if (!IS_ERR(vt8500_port->clk)) { |
608 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); | 608 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); |
609 | } else { | 609 | } else { |
610 | /* use the default of 24Mhz if not specified and warn */ | 610 | /* use the default of 24Mhz if not specified and warn */ |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 4c90b510d016..640ae6c6d2d2 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -37,6 +37,7 @@ config USB_ARCH_HAS_EHCI | |||
37 | default y if ARCH_W90X900 | 37 | default y if ARCH_W90X900 |
38 | default y if ARCH_AT91 | 38 | default y if ARCH_AT91 |
39 | default y if ARCH_MXC | 39 | default y if ARCH_MXC |
40 | default y if ARCH_MXS | ||
40 | default y if ARCH_OMAP3 | 41 | default y if ARCH_OMAP3 |
41 | default y if ARCH_CNS3XXX | 42 | default y if ARCH_CNS3XXX |
42 | default y if ARCH_VT8500 | 43 | default y if ARCH_VT8500 |
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index caecad9213f5..8e9d31277c43 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c | |||
@@ -70,6 +70,9 @@ static int host_start(struct ci13xxx *ci) | |||
70 | else | 70 | else |
71 | ci->hcd = hcd; | 71 | ci->hcd = hcd; |
72 | 72 | ||
73 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | ||
74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | ||
75 | |||
73 | return ret; | 76 | return ret; |
74 | } | 77 | } |
75 | 78 | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8d809a811e16..2d92cce260d7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_ids[] = { | |||
1602 | { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ | 1602 | { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ |
1603 | .driver_info = NO_UNION_NORMAL, | 1603 | .driver_info = NO_UNION_NORMAL, |
1604 | }, | 1604 | }, |
1605 | { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ | ||
1606 | .driver_info = NO_UNION_NORMAL, | ||
1607 | }, | ||
1605 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1608 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1606 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1609 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1607 | }, | 1610 | }, |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a815fd2cc5e7..957ed2c41482 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -877,6 +877,60 @@ static int hub_hub_status(struct usb_hub *hub, | |||
877 | return ret; | 877 | return ret; |
878 | } | 878 | } |
879 | 879 | ||
880 | static int hub_set_port_link_state(struct usb_hub *hub, int port1, | ||
881 | unsigned int link_status) | ||
882 | { | ||
883 | return set_port_feature(hub->hdev, | ||
884 | port1 | (link_status << 3), | ||
885 | USB_PORT_FEAT_LINK_STATE); | ||
886 | } | ||
887 | |||
888 | /* | ||
889 | * If USB 3.0 ports are placed into the Disabled state, they will no longer | ||
890 | * detect any device connects or disconnects. This is generally not what the | ||
891 | * USB core wants, since it expects a disabled port to produce a port status | ||
892 | * change event when a new device connects. | ||
893 | * | ||
894 | * Instead, set the link state to Disabled, wait for the link to settle into | ||
895 | * that state, clear any change bits, and then put the port into the RxDetect | ||
896 | * state. | ||
897 | */ | ||
898 | static int hub_usb3_port_disable(struct usb_hub *hub, int port1) | ||
899 | { | ||
900 | int ret; | ||
901 | int total_time; | ||
902 | u16 portchange, portstatus; | ||
903 | |||
904 | if (!hub_is_superspeed(hub->hdev)) | ||
905 | return -EINVAL; | ||
906 | |||
907 | ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); | ||
908 | if (ret) { | ||
909 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | ||
910 | port1, ret); | ||
911 | return ret; | ||
912 | } | ||
913 | |||
914 | /* Wait for the link to enter the disabled state. */ | ||
915 | for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { | ||
916 | ret = hub_port_status(hub, port1, &portstatus, &portchange); | ||
917 | if (ret < 0) | ||
918 | return ret; | ||
919 | |||
920 | if ((portstatus & USB_PORT_STAT_LINK_STATE) == | ||
921 | USB_SS_PORT_LS_SS_DISABLED) | ||
922 | break; | ||
923 | if (total_time >= HUB_DEBOUNCE_TIMEOUT) | ||
924 | break; | ||
925 | msleep(HUB_DEBOUNCE_STEP); | ||
926 | } | ||
927 | if (total_time >= HUB_DEBOUNCE_TIMEOUT) | ||
928 | dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", | ||
929 | port1, total_time); | ||
930 | |||
931 | return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); | ||
932 | } | ||
933 | |||
880 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | 934 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) |
881 | { | 935 | { |
882 | struct usb_device *hdev = hub->hdev; | 936 | struct usb_device *hdev = hub->hdev; |
@@ -885,8 +939,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | |||
885 | if (hub->ports[port1 - 1]->child && set_state) | 939 | if (hub->ports[port1 - 1]->child && set_state) |
886 | usb_set_device_state(hub->ports[port1 - 1]->child, | 940 | usb_set_device_state(hub->ports[port1 - 1]->child, |
887 | USB_STATE_NOTATTACHED); | 941 | USB_STATE_NOTATTACHED); |
888 | if (!hub->error && !hub_is_superspeed(hub->hdev)) | 942 | if (!hub->error) { |
889 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); | 943 | if (hub_is_superspeed(hub->hdev)) |
944 | ret = hub_usb3_port_disable(hub, port1); | ||
945 | else | ||
946 | ret = clear_port_feature(hdev, port1, | ||
947 | USB_PORT_FEAT_ENABLE); | ||
948 | } | ||
890 | if (ret) | 949 | if (ret) |
891 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | 950 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", |
892 | port1, ret); | 951 | port1, ret); |
@@ -2440,7 +2499,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) | |||
2440 | #define HUB_SHORT_RESET_TIME 10 | 2499 | #define HUB_SHORT_RESET_TIME 10 |
2441 | #define HUB_BH_RESET_TIME 50 | 2500 | #define HUB_BH_RESET_TIME 50 |
2442 | #define HUB_LONG_RESET_TIME 200 | 2501 | #define HUB_LONG_RESET_TIME 200 |
2443 | #define HUB_RESET_TIMEOUT 500 | 2502 | #define HUB_RESET_TIMEOUT 800 |
2444 | 2503 | ||
2445 | static int hub_port_reset(struct usb_hub *hub, int port1, | 2504 | static int hub_port_reset(struct usb_hub *hub, int port1, |
2446 | struct usb_device *udev, unsigned int delay, bool warm); | 2505 | struct usb_device *udev, unsigned int delay, bool warm); |
@@ -2475,6 +2534,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2475 | if (ret < 0) | 2534 | if (ret < 0) |
2476 | return ret; | 2535 | return ret; |
2477 | 2536 | ||
2537 | /* The port state is unknown until the reset completes. */ | ||
2538 | if ((portstatus & USB_PORT_STAT_RESET)) | ||
2539 | goto delay; | ||
2540 | |||
2478 | /* | 2541 | /* |
2479 | * Some buggy devices require a warm reset to be issued even | 2542 | * Some buggy devices require a warm reset to be issued even |
2480 | * when the port appears not to be connected. | 2543 | * when the port appears not to be connected. |
@@ -2520,11 +2583,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2520 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | 2583 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) |
2521 | return -ENOTCONN; | 2584 | return -ENOTCONN; |
2522 | 2585 | ||
2523 | /* if we`ve finished resetting, then break out of | 2586 | if ((portstatus & USB_PORT_STAT_ENABLE)) { |
2524 | * the loop | ||
2525 | */ | ||
2526 | if (!(portstatus & USB_PORT_STAT_RESET) && | ||
2527 | (portstatus & USB_PORT_STAT_ENABLE)) { | ||
2528 | if (hub_is_wusb(hub)) | 2587 | if (hub_is_wusb(hub)) |
2529 | udev->speed = USB_SPEED_WIRELESS; | 2588 | udev->speed = USB_SPEED_WIRELESS; |
2530 | else if (hub_is_superspeed(hub->hdev)) | 2589 | else if (hub_is_superspeed(hub->hdev)) |
@@ -2538,10 +2597,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2538 | return 0; | 2597 | return 0; |
2539 | } | 2598 | } |
2540 | } else { | 2599 | } else { |
2541 | if (portchange & USB_PORT_STAT_C_BH_RESET) | 2600 | if (!(portstatus & USB_PORT_STAT_CONNECTION) || |
2542 | return 0; | 2601 | hub_port_warm_reset_required(hub, |
2602 | portstatus)) | ||
2603 | return -ENOTCONN; | ||
2604 | |||
2605 | return 0; | ||
2543 | } | 2606 | } |
2544 | 2607 | ||
2608 | delay: | ||
2545 | /* switch to the long delay after two short delay failures */ | 2609 | /* switch to the long delay after two short delay failures */ |
2546 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) | 2610 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) |
2547 | delay = HUB_LONG_RESET_TIME; | 2611 | delay = HUB_LONG_RESET_TIME; |
@@ -2565,14 +2629,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |||
2565 | msleep(10 + 40); | 2629 | msleep(10 + 40); |
2566 | update_devnum(udev, 0); | 2630 | update_devnum(udev, 0); |
2567 | hcd = bus_to_hcd(udev->bus); | 2631 | hcd = bus_to_hcd(udev->bus); |
2568 | if (hcd->driver->reset_device) { | 2632 | /* The xHC may think the device is already reset, |
2569 | *status = hcd->driver->reset_device(hcd, udev); | 2633 | * so ignore the status. |
2570 | if (*status < 0) { | 2634 | */ |
2571 | dev_err(&udev->dev, "Cannot reset " | 2635 | if (hcd->driver->reset_device) |
2572 | "HCD device state\n"); | 2636 | hcd->driver->reset_device(hcd, udev); |
2573 | break; | ||
2574 | } | ||
2575 | } | ||
2576 | } | 2637 | } |
2577 | /* FALL THROUGH */ | 2638 | /* FALL THROUGH */ |
2578 | case -ENOTCONN: | 2639 | case -ENOTCONN: |
@@ -2580,16 +2641,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |||
2580 | clear_port_feature(hub->hdev, | 2641 | clear_port_feature(hub->hdev, |
2581 | port1, USB_PORT_FEAT_C_RESET); | 2642 | port1, USB_PORT_FEAT_C_RESET); |
2582 | /* FIXME need disconnect() for NOTATTACHED device */ | 2643 | /* FIXME need disconnect() for NOTATTACHED device */ |
2583 | if (warm) { | 2644 | if (hub_is_superspeed(hub->hdev)) { |
2584 | clear_port_feature(hub->hdev, port1, | 2645 | clear_port_feature(hub->hdev, port1, |
2585 | USB_PORT_FEAT_C_BH_PORT_RESET); | 2646 | USB_PORT_FEAT_C_BH_PORT_RESET); |
2586 | clear_port_feature(hub->hdev, port1, | 2647 | clear_port_feature(hub->hdev, port1, |
2587 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 2648 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
2588 | } else { | 2649 | } |
2650 | if (!warm) | ||
2589 | usb_set_device_state(udev, *status | 2651 | usb_set_device_state(udev, *status |
2590 | ? USB_STATE_NOTATTACHED | 2652 | ? USB_STATE_NOTATTACHED |
2591 | : USB_STATE_DEFAULT); | 2653 | : USB_STATE_DEFAULT); |
2592 | } | ||
2593 | break; | 2654 | break; |
2594 | } | 2655 | } |
2595 | } | 2656 | } |
@@ -2939,7 +3000,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2939 | static int finish_port_resume(struct usb_device *udev) | 3000 | static int finish_port_resume(struct usb_device *udev) |
2940 | { | 3001 | { |
2941 | int status = 0; | 3002 | int status = 0; |
2942 | u16 devstatus; | 3003 | u16 devstatus = 0; |
2943 | 3004 | ||
2944 | /* caller owns the udev device lock */ | 3005 | /* caller owns the udev device lock */ |
2945 | dev_dbg(&udev->dev, "%s\n", | 3006 | dev_dbg(&udev->dev, "%s\n", |
@@ -2984,7 +3045,13 @@ static int finish_port_resume(struct usb_device *udev) | |||
2984 | if (status) { | 3045 | if (status) { |
2985 | dev_dbg(&udev->dev, "gone after usb resume? status %d\n", | 3046 | dev_dbg(&udev->dev, "gone after usb resume? status %d\n", |
2986 | status); | 3047 | status); |
2987 | } else if (udev->actconfig) { | 3048 | /* |
3049 | * There are a few quirky devices which violate the standard | ||
3050 | * by claiming to have remote wakeup enabled after a reset, | ||
3051 | * which crash if the feature is cleared, hence check for | ||
3052 | * udev->reset_resume | ||
3053 | */ | ||
3054 | } else if (udev->actconfig && !udev->reset_resume) { | ||
2988 | le16_to_cpus(&devstatus); | 3055 | le16_to_cpus(&devstatus); |
2989 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | 3056 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { |
2990 | status = usb_control_msg(udev, | 3057 | status = usb_control_msg(udev, |
@@ -4638,9 +4705,14 @@ static void hub_events(void) | |||
4638 | * SS.Inactive state. | 4705 | * SS.Inactive state. |
4639 | */ | 4706 | */ |
4640 | if (hub_port_warm_reset_required(hub, portstatus)) { | 4707 | if (hub_port_warm_reset_required(hub, portstatus)) { |
4708 | int status; | ||
4709 | |||
4641 | dev_dbg(hub_dev, "warm reset port %d\n", i); | 4710 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
4642 | hub_port_reset(hub, i, NULL, | 4711 | status = hub_port_reset(hub, i, NULL, |
4643 | HUB_BH_RESET_TIME, true); | 4712 | HUB_BH_RESET_TIME, true); |
4713 | if (status < 0) | ||
4714 | hub_port_disable(hub, i, 1); | ||
4715 | connect_change = 0; | ||
4644 | } | 4716 | } |
4645 | 4717 | ||
4646 | if (connect_change) | 4718 | if (connect_change) |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index fdefd9c7f7af..3113c1d71442 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -43,6 +43,9 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
43 | /* Creative SB Audigy 2 NX */ | 43 | /* Creative SB Audigy 2 NX */ |
44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
45 | 45 | ||
46 | /* Microsoft LifeCam-VX700 v2.0 */ | ||
47 | { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
48 | |||
46 | /* Logitech Quickcam Fusion */ | 49 | /* Logitech Quickcam Fusion */ |
47 | { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, | 50 | { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, |
48 | 51 | ||
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 92604b4f9712..5945aadaa1c9 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #define dump_register(nm) \ | 56 | #define dump_register(nm) \ |
57 | { \ | 57 | { \ |
58 | .name = __stringify(nm), \ | 58 | .name = __stringify(nm), \ |
59 | .offset = DWC3_ ##nm, \ | 59 | .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ |
60 | } | 60 | } |
61 | 61 | ||
62 | static const struct debugfs_reg32 dwc3_regs[] = { | 62 | static const struct debugfs_reg32 dwc3_regs[] = { |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2e43b332aae8..2fdd767f8fe8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) | |||
1605 | 1605 | ||
1606 | if (epnum == 0 || epnum == 1) { | 1606 | if (epnum == 0 || epnum == 1) { |
1607 | dep->endpoint.maxpacket = 512; | 1607 | dep->endpoint.maxpacket = 512; |
1608 | dep->endpoint.maxburst = 1; | ||
1608 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; | 1609 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; |
1609 | if (!epnum) | 1610 | if (!epnum) |
1610 | dwc->gadget.ep0 = &dep->endpoint; | 1611 | dwc->gadget.ep0 = &dep->endpoint; |
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index fc0ec5e0d58e..d9f6b9372491 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c | |||
@@ -3231,7 +3231,7 @@ static int udc_pci_probe( | |||
3231 | } | 3231 | } |
3232 | 3232 | ||
3233 | if (!pdev->irq) { | 3233 | if (!pdev->irq) { |
3234 | dev_err(&dev->pdev->dev, "irq not set\n"); | 3234 | dev_err(&pdev->dev, "irq not set\n"); |
3235 | kfree(dev); | 3235 | kfree(dev); |
3236 | dev = NULL; | 3236 | dev = NULL; |
3237 | retval = -ENODEV; | 3237 | retval = -ENODEV; |
@@ -3250,7 +3250,7 @@ static int udc_pci_probe( | |||
3250 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | 3250 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); |
3251 | 3251 | ||
3252 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | 3252 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { |
3253 | dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); | 3253 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); |
3254 | kfree(dev); | 3254 | kfree(dev); |
3255 | dev = NULL; | 3255 | dev = NULL; |
3256 | retval = -EBUSY; | 3256 | retval = -EBUSY; |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 95d584dbed13..8cf0c0f6fa1f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -130,10 +130,7 @@ static const char ep0name[] = "ep0"; | |||
130 | static const char *const ep_name[] = { | 130 | static const char *const ep_name[] = { |
131 | ep0name, /* everyone has ep0 */ | 131 | ep0name, /* everyone has ep0 */ |
132 | 132 | ||
133 | /* act like a net2280: high speed, six configurable endpoints */ | 133 | /* act like a pxa250: fifteen fixed function endpoints */ |
134 | "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", | ||
135 | |||
136 | /* or like pxa250: fifteen fixed function endpoints */ | ||
137 | "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", | 134 | "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", |
138 | "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", | 135 | "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", |
139 | "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", | 136 | "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", |
@@ -141,6 +138,10 @@ static const char *const ep_name[] = { | |||
141 | 138 | ||
142 | /* or like sa1100: two fixed function endpoints */ | 139 | /* or like sa1100: two fixed function endpoints */ |
143 | "ep1out-bulk", "ep2in-bulk", | 140 | "ep1out-bulk", "ep2in-bulk", |
141 | |||
142 | /* and now some generic EPs so we have enough in multi config */ | ||
143 | "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", | ||
144 | "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", | ||
144 | }; | 145 | }; |
145 | #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) | 146 | #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) |
146 | 147 | ||
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 4a6961c517f2..8c2f25121149 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c | |||
@@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) | |||
1153 | pr_err("%s: unmapped value: %lu\n", opts, value); | 1153 | pr_err("%s: unmapped value: %lu\n", opts, value); |
1154 | return -EINVAL; | 1154 | return -EINVAL; |
1155 | } | 1155 | } |
1156 | } | 1156 | } else if (!memcmp(opts, "gid", 3)) { |
1157 | else if (!memcmp(opts, "gid", 3)) | ||
1158 | data->perms.gid = make_kgid(current_user_ns(), value); | 1157 | data->perms.gid = make_kgid(current_user_ns(), value); |
1159 | if (!gid_valid(data->perms.gid)) { | 1158 | if (!gid_valid(data->perms.gid)) { |
1160 | pr_err("%s: unmapped value: %lu\n", opts, value); | 1159 | pr_err("%s: unmapped value: %lu\n", opts, value); |
1161 | return -EINVAL; | 1160 | return -EINVAL; |
1162 | } | 1161 | } |
1163 | else | 1162 | } else { |
1164 | goto invalid; | 1163 | goto invalid; |
1164 | } | ||
1165 | break; | 1165 | break; |
1166 | 1166 | ||
1167 | default: | 1167 | default: |
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 1b0f086426bd..d3bd7b095ba3 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c | |||
@@ -18,14 +18,13 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | static struct clk *mxc_ahb_clk; | 21 | static struct clk *mxc_ahb_clk; |
24 | static struct clk *mxc_per_clk; | 22 | static struct clk *mxc_per_clk; |
25 | static struct clk *mxc_ipg_clk; | 23 | static struct clk *mxc_ipg_clk; |
26 | 24 | ||
27 | /* workaround ENGcm09152 for i.MX35 */ | 25 | /* workaround ENGcm09152 for i.MX35 */ |
28 | #define USBPHYCTRL_OTGBASE_OFFSET 0x608 | 26 | #define MX35_USBPHYCTRL_OFFSET 0x600 |
27 | #define USBPHYCTRL_OTGBASE_OFFSET 0x8 | ||
29 | #define USBPHYCTRL_EVDO (1 << 23) | 28 | #define USBPHYCTRL_EVDO (1 << 23) |
30 | 29 | ||
31 | int fsl_udc_clk_init(struct platform_device *pdev) | 30 | int fsl_udc_clk_init(struct platform_device *pdev) |
@@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) | |||
59 | clk_prepare_enable(mxc_per_clk); | 58 | clk_prepare_enable(mxc_per_clk); |
60 | 59 | ||
61 | /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ | 60 | /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ |
62 | if (!cpu_is_mx51()) { | 61 | if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) { |
63 | freq = clk_get_rate(mxc_per_clk); | 62 | freq = clk_get_rate(mxc_per_clk); |
64 | if (pdata->phy_mode != FSL_USB2_PHY_ULPI && | 63 | if (pdata->phy_mode != FSL_USB2_PHY_ULPI && |
65 | (freq < 59999000 || freq > 60001000)) { | 64 | (freq < 59999000 || freq > 60001000)) { |
@@ -79,27 +78,40 @@ eclkrate: | |||
79 | return ret; | 78 | return ret; |
80 | } | 79 | } |
81 | 80 | ||
82 | void fsl_udc_clk_finalize(struct platform_device *pdev) | 81 | int fsl_udc_clk_finalize(struct platform_device *pdev) |
83 | { | 82 | { |
84 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | 83 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
85 | if (cpu_is_mx35()) { | 84 | int ret = 0; |
86 | unsigned int v; | ||
87 | 85 | ||
88 | /* workaround ENGcm09152 for i.MX35 */ | 86 | /* workaround ENGcm09152 for i.MX35 */ |
89 | if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { | 87 | if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { |
90 | v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + | 88 | unsigned int v; |
91 | USBPHYCTRL_OTGBASE_OFFSET)); | 89 | struct resource *res = platform_get_resource |
92 | writel(v | USBPHYCTRL_EVDO, | 90 | (pdev, IORESOURCE_MEM, 0); |
93 | MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + | 91 | void __iomem *phy_regs = ioremap(res->start + |
94 | USBPHYCTRL_OTGBASE_OFFSET)); | 92 | MX35_USBPHYCTRL_OFFSET, 512); |
93 | if (!phy_regs) { | ||
94 | dev_err(&pdev->dev, "ioremap for phy address fails\n"); | ||
95 | ret = -EINVAL; | ||
96 | goto ioremap_err; | ||
95 | } | 97 | } |
98 | |||
99 | v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET); | ||
100 | writel(v | USBPHYCTRL_EVDO, | ||
101 | phy_regs + USBPHYCTRL_OTGBASE_OFFSET); | ||
102 | |||
103 | iounmap(phy_regs); | ||
96 | } | 104 | } |
97 | 105 | ||
106 | |||
107 | ioremap_err: | ||
98 | /* ULPI transceivers don't need usbpll */ | 108 | /* ULPI transceivers don't need usbpll */ |
99 | if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { | 109 | if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { |
100 | clk_disable_unprepare(mxc_per_clk); | 110 | clk_disable_unprepare(mxc_per_clk); |
101 | mxc_per_clk = NULL; | 111 | mxc_per_clk = NULL; |
102 | } | 112 | } |
113 | |||
114 | return ret; | ||
103 | } | 115 | } |
104 | 116 | ||
105 | void fsl_udc_clk_release(void) | 117 | void fsl_udc_clk_release(void) |
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index c19f7f13790b..667275cb7bad 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/fsl_devices.h> | 41 | #include <linux/fsl_devices.h> |
42 | #include <linux/dmapool.h> | 42 | #include <linux/dmapool.h> |
43 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
44 | #include <linux/of_device.h> | ||
44 | 45 | ||
45 | #include <asm/byteorder.h> | 46 | #include <asm/byteorder.h> |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
@@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2438 | unsigned int i; | 2439 | unsigned int i; |
2439 | u32 dccparams; | 2440 | u32 dccparams; |
2440 | 2441 | ||
2441 | if (strcmp(pdev->name, driver_name)) { | ||
2442 | VDBG("Wrong device"); | ||
2443 | return -ENODEV; | ||
2444 | } | ||
2445 | |||
2446 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); | 2442 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); |
2447 | if (udc_controller == NULL) { | 2443 | if (udc_controller == NULL) { |
2448 | ERR("malloc udc failed\n"); | 2444 | ERR("malloc udc failed\n"); |
@@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2547 | dr_controller_setup(udc_controller); | 2543 | dr_controller_setup(udc_controller); |
2548 | } | 2544 | } |
2549 | 2545 | ||
2550 | fsl_udc_clk_finalize(pdev); | 2546 | ret = fsl_udc_clk_finalize(pdev); |
2547 | if (ret) | ||
2548 | goto err_free_irq; | ||
2551 | 2549 | ||
2552 | /* Setup gadget structure */ | 2550 | /* Setup gadget structure */ |
2553 | udc_controller->gadget.ops = &fsl_gadget_ops; | 2551 | udc_controller->gadget.ops = &fsl_gadget_ops; |
@@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev) | |||
2756 | 2754 | ||
2757 | return fsl_udc_resume(NULL); | 2755 | return fsl_udc_resume(NULL); |
2758 | } | 2756 | } |
2759 | |||
2760 | /*------------------------------------------------------------------------- | 2757 | /*------------------------------------------------------------------------- |
2761 | Register entry point for the peripheral controller driver | 2758 | Register entry point for the peripheral controller driver |
2762 | --------------------------------------------------------------------------*/ | 2759 | --------------------------------------------------------------------------*/ |
2763 | 2760 | static const struct platform_device_id fsl_udc_devtype[] = { | |
2761 | { | ||
2762 | .name = "imx-udc-mx27", | ||
2763 | }, { | ||
2764 | .name = "imx-udc-mx51", | ||
2765 | }, { | ||
2766 | /* sentinel */ | ||
2767 | } | ||
2768 | }; | ||
2769 | MODULE_DEVICE_TABLE(platform, fsl_udc_devtype); | ||
2764 | static struct platform_driver udc_driver = { | 2770 | static struct platform_driver udc_driver = { |
2765 | .remove = __exit_p(fsl_udc_remove), | 2771 | .remove = __exit_p(fsl_udc_remove), |
2772 | /* Just for FSL i.mx SoC currently */ | ||
2773 | .id_table = fsl_udc_devtype, | ||
2766 | /* these suspend and resume are not usb suspend and resume */ | 2774 | /* these suspend and resume are not usb suspend and resume */ |
2767 | .suspend = fsl_udc_suspend, | 2775 | .suspend = fsl_udc_suspend, |
2768 | .resume = fsl_udc_resume, | 2776 | .resume = fsl_udc_resume, |
2769 | .driver = { | 2777 | .driver = { |
2770 | .name = (char *)driver_name, | 2778 | .name = (char *)driver_name, |
2771 | .owner = THIS_MODULE, | 2779 | .owner = THIS_MODULE, |
2772 | /* udc suspend/resume called from OTG driver */ | 2780 | /* udc suspend/resume called from OTG driver */ |
2773 | .suspend = fsl_udc_otg_suspend, | 2781 | .suspend = fsl_udc_otg_suspend, |
2774 | .resume = fsl_udc_otg_resume, | 2782 | .resume = fsl_udc_otg_resume, |
2775 | }, | 2783 | }, |
2776 | }; | 2784 | }; |
2777 | 2785 | ||
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f61a967f7082..c6703bb07b23 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h | |||
@@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) | |||
592 | struct platform_device; | 592 | struct platform_device; |
593 | #ifdef CONFIG_ARCH_MXC | 593 | #ifdef CONFIG_ARCH_MXC |
594 | int fsl_udc_clk_init(struct platform_device *pdev); | 594 | int fsl_udc_clk_init(struct platform_device *pdev); |
595 | void fsl_udc_clk_finalize(struct platform_device *pdev); | 595 | int fsl_udc_clk_finalize(struct platform_device *pdev); |
596 | void fsl_udc_clk_release(void); | 596 | void fsl_udc_clk_release(void); |
597 | #else | 597 | #else |
598 | static inline int fsl_udc_clk_init(struct platform_device *pdev) | 598 | static inline int fsl_udc_clk_init(struct platform_device *pdev) |
599 | { | 599 | { |
600 | return 0; | 600 | return 0; |
601 | } | 601 | } |
602 | static inline void fsl_udc_clk_finalize(struct platform_device *pdev) | 602 | static inline int fsl_udc_clk_finalize(struct platform_device *pdev) |
603 | { | 603 | { |
604 | return 0; | ||
604 | } | 605 | } |
605 | static inline void fsl_udc_clk_release(void) | 606 | static inline void fsl_udc_clk_release(void) |
606 | { | 607 | { |
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 379aac7b82fc..6e8b1272ebce 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c | |||
@@ -1012,7 +1012,7 @@ static void udc_clock_enable(struct mv_udc *udc) | |||
1012 | unsigned int i; | 1012 | unsigned int i; |
1013 | 1013 | ||
1014 | for (i = 0; i < udc->clknum; i++) | 1014 | for (i = 0; i < udc->clknum; i++) |
1015 | clk_enable(udc->clk[i]); | 1015 | clk_prepare_enable(udc->clk[i]); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void udc_clock_disable(struct mv_udc *udc) | 1018 | static void udc_clock_disable(struct mv_udc *udc) |
@@ -1020,7 +1020,7 @@ static void udc_clock_disable(struct mv_udc *udc) | |||
1020 | unsigned int i; | 1020 | unsigned int i; |
1021 | 1021 | ||
1022 | for (i = 0; i < udc->clknum; i++) | 1022 | for (i = 0; i < udc->clknum; i++) |
1023 | clk_disable(udc->clk[i]); | 1023 | clk_disable_unprepare(udc->clk[i]); |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static void udc_stop(struct mv_udc *udc) | 1026 | static void udc_stop(struct mv_udc *udc) |
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 141971d9051e..439c3f972f8c 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -3477,12 +3477,11 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) | |||
3477 | /** | 3477 | /** |
3478 | * s3c_hsotg_release - release callback for hsotg device | 3478 | * s3c_hsotg_release - release callback for hsotg device |
3479 | * @dev: Device to for which release is called | 3479 | * @dev: Device to for which release is called |
3480 | * | ||
3481 | * Nothing to do as the resource is allocated using devm_ API. | ||
3480 | */ | 3482 | */ |
3481 | static void s3c_hsotg_release(struct device *dev) | 3483 | static void s3c_hsotg_release(struct device *dev) |
3482 | { | 3484 | { |
3483 | struct s3c_hsotg *hsotg = dev_get_drvdata(dev); | ||
3484 | |||
3485 | kfree(hsotg); | ||
3486 | } | 3485 | } |
3487 | 3486 | ||
3488 | /** | 3487 | /** |
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 4f7f76f00c74..7cacd6ae818e 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c | |||
@@ -1794,9 +1794,10 @@ static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg) | |||
1794 | tpg->tpg_nexus = NULL; | 1794 | tpg->tpg_nexus = NULL; |
1795 | 1795 | ||
1796 | kfree(tv_nexus); | 1796 | kfree(tv_nexus); |
1797 | ret = 0; | ||
1797 | out: | 1798 | out: |
1798 | mutex_unlock(&tpg->tpg_mutex); | 1799 | mutex_unlock(&tpg->tpg_mutex); |
1799 | return 0; | 1800 | return ret; |
1800 | } | 1801 | } |
1801 | 1802 | ||
1802 | static ssize_t tcm_usbg_tpg_store_nexus( | 1803 | static ssize_t tcm_usbg_tpg_store_nexus( |
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index d0f95482f40e..598dcc1212f0 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c | |||
@@ -887,7 +887,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
887 | pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", | 887 | pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", |
888 | port->port_num, tty, file); | 888 | port->port_num, tty, file); |
889 | 889 | ||
890 | wake_up_interruptible(&port->port.close_wait); | 890 | wake_up(&port->port.close_wait); |
891 | exit: | 891 | exit: |
892 | spin_unlock_irq(&port->port_lock); | 892 | spin_unlock_irq(&port->port_lock); |
893 | } | 893 | } |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d6bb128ce21e..3a21c5d683c0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -148,7 +148,7 @@ config USB_EHCI_FSL | |||
148 | Variation of ARC USB block used in some Freescale chips. | 148 | Variation of ARC USB block used in some Freescale chips. |
149 | 149 | ||
150 | config USB_EHCI_MXC | 150 | config USB_EHCI_MXC |
151 | bool "Support for Freescale i.MX on-chip EHCI USB controller" | 151 | tristate "Support for Freescale i.MX on-chip EHCI USB controller" |
152 | depends on USB_EHCI_HCD && ARCH_MXC | 152 | depends on USB_EHCI_HCD && ARCH_MXC |
153 | select USB_EHCI_ROOT_HUB_TT | 153 | select USB_EHCI_ROOT_HUB_TT |
154 | ---help--- | 154 | ---help--- |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1eb4c3006e9e..001fbff2fdef 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o | |||
26 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 26 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
27 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o | 27 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o |
28 | obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o | 28 | obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o |
29 | obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o | ||
29 | 30 | ||
30 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | 31 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o |
31 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 32 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index fd9b5424b860..d81d2fcbff18 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -230,7 +230,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
230 | 230 | ||
231 | switch (phy_mode) { | 231 | switch (phy_mode) { |
232 | case FSL_USB2_PHY_ULPI: | 232 | case FSL_USB2_PHY_ULPI: |
233 | if (pdata->controller_ver) { | 233 | if (pdata->have_sysif_regs && pdata->controller_ver) { |
234 | /* controller version 1.6 or above */ | 234 | /* controller version 1.6 or above */ |
235 | setbits32(non_ehci + FSL_SOC_USB_CTRL, | 235 | setbits32(non_ehci + FSL_SOC_USB_CTRL, |
236 | ULPI_PHY_CLK_SEL); | 236 | ULPI_PHY_CLK_SEL); |
@@ -251,7 +251,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
251 | portsc |= PORT_PTS_PTW; | 251 | portsc |= PORT_PTS_PTW; |
252 | /* fall through */ | 252 | /* fall through */ |
253 | case FSL_USB2_PHY_UTMI: | 253 | case FSL_USB2_PHY_UTMI: |
254 | if (pdata->controller_ver) { | 254 | if (pdata->have_sysif_regs && pdata->controller_ver) { |
255 | /* controller version 1.6 or above */ | 255 | /* controller version 1.6 or above */ |
256 | setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); | 256 | setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); |
257 | mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to | 257 | mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to |
@@ -267,7 +267,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
267 | break; | 267 | break; |
268 | } | 268 | } |
269 | 269 | ||
270 | if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) { | 270 | if (pdata->have_sysif_regs && pdata->controller_ver && |
271 | (phy_mode == FSL_USB2_PHY_ULPI)) { | ||
271 | /* check PHY_CLK_VALID to get phy clk valid */ | 272 | /* check PHY_CLK_VALID to get phy clk valid */ |
272 | if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & | 273 | if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & |
273 | PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { | 274 | PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { |
@@ -278,7 +279,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
278 | 279 | ||
279 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); | 280 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); |
280 | 281 | ||
281 | if (phy_mode != FSL_USB2_PHY_ULPI) | 282 | if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) |
282 | setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); | 283 | setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); |
283 | 284 | ||
284 | return 0; | 285 | return 0; |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c97503bb0b0e..09537b2f1002 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -74,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd"; | |||
74 | #undef VERBOSE_DEBUG | 74 | #undef VERBOSE_DEBUG |
75 | #undef EHCI_URB_TRACE | 75 | #undef EHCI_URB_TRACE |
76 | 76 | ||
77 | #ifdef DEBUG | ||
78 | #define EHCI_STATS | ||
79 | #endif | ||
80 | |||
81 | /* magic numbers that can affect system performance */ | 77 | /* magic numbers that can affect system performance */ |
82 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | 78 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ |
83 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | 79 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ |
@@ -1250,11 +1246,6 @@ MODULE_LICENSE ("GPL"); | |||
1250 | #define PLATFORM_DRIVER ehci_fsl_driver | 1246 | #define PLATFORM_DRIVER ehci_fsl_driver |
1251 | #endif | 1247 | #endif |
1252 | 1248 | ||
1253 | #ifdef CONFIG_USB_EHCI_MXC | ||
1254 | #include "ehci-mxc.c" | ||
1255 | #define PLATFORM_DRIVER ehci_mxc_driver | ||
1256 | #endif | ||
1257 | |||
1258 | #ifdef CONFIG_USB_EHCI_SH | 1249 | #ifdef CONFIG_USB_EHCI_SH |
1259 | #include "ehci-sh.c" | 1250 | #include "ehci-sh.c" |
1260 | #define PLATFORM_DRIVER ehci_hcd_sh_driver | 1251 | #define PLATFORM_DRIVER ehci_hcd_sh_driver |
@@ -1352,7 +1343,8 @@ MODULE_LICENSE ("GPL"); | |||
1352 | 1343 | ||
1353 | #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ | 1344 | #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ |
1354 | !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ | 1345 | !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ |
1355 | !defined(CONFIG_USB_CHIPIDEA_HOST) && \ | 1346 | !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ |
1347 | !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ | ||
1356 | !defined(PLATFORM_DRIVER) && \ | 1348 | !defined(PLATFORM_DRIVER) && \ |
1357 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ | 1349 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ |
1358 | !defined(OF_PLATFORM_DRIVER) && \ | 1350 | !defined(OF_PLATFORM_DRIVER) && \ |
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f7bfc0b898b9..6c56297ea16b 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c | |||
@@ -43,7 +43,7 @@ static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) | |||
43 | unsigned int i; | 43 | unsigned int i; |
44 | 44 | ||
45 | for (i = 0; i < ehci_mv->clknum; i++) | 45 | for (i = 0; i < ehci_mv->clknum; i++) |
46 | clk_enable(ehci_mv->clk[i]); | 46 | clk_prepare_enable(ehci_mv->clk[i]); |
47 | } | 47 | } |
48 | 48 | ||
49 | static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) | 49 | static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) |
@@ -51,7 +51,7 @@ static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) | |||
51 | unsigned int i; | 51 | unsigned int i; |
52 | 52 | ||
53 | for (i = 0; i < ehci_mv->clknum; i++) | 53 | for (i = 0; i < ehci_mv->clknum; i++) |
54 | clk_disable(ehci_mv->clk[i]); | 54 | clk_disable_unprepare(ehci_mv->clk[i]); |
55 | } | 55 | } |
56 | 56 | ||
57 | static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) | 57 | static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ec7f5d2c90de..dedb80bb8d40 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -17,75 +17,38 @@ | |||
17 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/io.h> | ||
20 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
21 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
22 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
23 | #include <linux/usb/otg.h> | 26 | #include <linux/usb/otg.h> |
24 | #include <linux/usb/ulpi.h> | 27 | #include <linux/usb/ulpi.h> |
25 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/usb.h> | ||
30 | #include <linux/usb/hcd.h> | ||
26 | 31 | ||
27 | #include <linux/platform_data/usb-ehci-mxc.h> | 32 | #include <linux/platform_data/usb-ehci-mxc.h> |
28 | 33 | ||
29 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
30 | 35 | ||
36 | #include "ehci.h" | ||
37 | |||
38 | #define DRIVER_DESC "Freescale On-Chip EHCI Host driver" | ||
39 | |||
40 | static const char hcd_name[] = "ehci-mxc"; | ||
41 | |||
31 | #define ULPI_VIEWPORT_OFFSET 0x170 | 42 | #define ULPI_VIEWPORT_OFFSET 0x170 |
32 | 43 | ||
33 | struct ehci_mxc_priv { | 44 | struct ehci_mxc_priv { |
34 | struct clk *usbclk, *ahbclk, *phyclk; | 45 | struct clk *usbclk, *ahbclk, *phyclk; |
35 | struct usb_hcd *hcd; | ||
36 | }; | 46 | }; |
37 | 47 | ||
38 | /* called during probe() after chip reset completes */ | 48 | static struct hc_driver __read_mostly ehci_mxc_hc_driver; |
39 | static int ehci_mxc_setup(struct usb_hcd *hcd) | ||
40 | { | ||
41 | hcd->has_tt = 1; | ||
42 | |||
43 | return ehci_setup(hcd); | ||
44 | } | ||
45 | 49 | ||
46 | static const struct hc_driver ehci_mxc_hc_driver = { | 50 | static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { |
47 | .description = hcd_name, | 51 | .extra_priv_size = sizeof(struct ehci_mxc_priv), |
48 | .product_desc = "Freescale On-Chip EHCI Host Controller", | ||
49 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
50 | |||
51 | /* | ||
52 | * generic hardware linkage | ||
53 | */ | ||
54 | .irq = ehci_irq, | ||
55 | .flags = HCD_USB2 | HCD_MEMORY, | ||
56 | |||
57 | /* | ||
58 | * basic lifecycle operations | ||
59 | */ | ||
60 | .reset = ehci_mxc_setup, | ||
61 | .start = ehci_run, | ||
62 | .stop = ehci_stop, | ||
63 | .shutdown = ehci_shutdown, | ||
64 | |||
65 | /* | ||
66 | * managing i/o requests and associated device resources | ||
67 | */ | ||
68 | .urb_enqueue = ehci_urb_enqueue, | ||
69 | .urb_dequeue = ehci_urb_dequeue, | ||
70 | .endpoint_disable = ehci_endpoint_disable, | ||
71 | .endpoint_reset = ehci_endpoint_reset, | ||
72 | |||
73 | /* | ||
74 | * scheduling support | ||
75 | */ | ||
76 | .get_frame_number = ehci_get_frame, | ||
77 | |||
78 | /* | ||
79 | * root hub support | ||
80 | */ | ||
81 | .hub_status_data = ehci_hub_status_data, | ||
82 | .hub_control = ehci_hub_control, | ||
83 | .bus_suspend = ehci_bus_suspend, | ||
84 | .bus_resume = ehci_bus_resume, | ||
85 | .relinquish_port = ehci_relinquish_port, | ||
86 | .port_handed_over = ehci_port_handed_over, | ||
87 | |||
88 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
89 | }; | 52 | }; |
90 | 53 | ||
91 | static int ehci_mxc_drv_probe(struct platform_device *pdev) | 54 | static int ehci_mxc_drv_probe(struct platform_device *pdev) |
@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
112 | if (!hcd) | 75 | if (!hcd) |
113 | return -ENOMEM; | 76 | return -ENOMEM; |
114 | 77 | ||
115 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
116 | if (!priv) { | ||
117 | ret = -ENOMEM; | ||
118 | goto err_alloc; | ||
119 | } | ||
120 | |||
121 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 78 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
122 | if (!res) { | 79 | if (!res) { |
123 | dev_err(dev, "Found HC with no register addr. Check setup!\n"); | 80 | dev_err(dev, "Found HC with no register addr. Check setup!\n"); |
@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
135 | goto err_alloc; | 92 | goto err_alloc; |
136 | } | 93 | } |
137 | 94 | ||
95 | hcd->has_tt = 1; | ||
96 | ehci = hcd_to_ehci(hcd); | ||
97 | priv = (struct ehci_mxc_priv *) ehci->priv; | ||
98 | |||
138 | /* enable clocks */ | 99 | /* enable clocks */ |
139 | priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); | 100 | priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); |
140 | if (IS_ERR(priv->usbclk)) { | 101 | if (IS_ERR(priv->usbclk)) { |
@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
169 | mdelay(10); | 130 | mdelay(10); |
170 | } | 131 | } |
171 | 132 | ||
172 | ehci = hcd_to_ehci(hcd); | ||
173 | |||
174 | /* EHCI registers start at offset 0x100 */ | 133 | /* EHCI registers start at offset 0x100 */ |
175 | ehci->caps = hcd->regs + 0x100; | 134 | ehci->caps = hcd->regs + 0x100; |
176 | ehci->regs = hcd->regs + 0x100 + | 135 | ehci->regs = hcd->regs + 0x100 + |
@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
198 | } | 157 | } |
199 | } | 158 | } |
200 | 159 | ||
201 | priv->hcd = hcd; | 160 | platform_set_drvdata(pdev, hcd); |
202 | platform_set_drvdata(pdev, priv); | ||
203 | 161 | ||
204 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | 162 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
205 | if (ret) | 163 | if (ret) |
@@ -244,8 +202,11 @@ err_alloc: | |||
244 | static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | 202 | static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) |
245 | { | 203 | { |
246 | struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; | 204 | struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; |
247 | struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); | 205 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
248 | struct usb_hcd *hcd = priv->hcd; | 206 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
207 | struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; | ||
208 | |||
209 | usb_remove_hcd(hcd); | ||
249 | 210 | ||
250 | if (pdata && pdata->exit) | 211 | if (pdata && pdata->exit) |
251 | pdata->exit(pdev); | 212 | pdata->exit(pdev); |
@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | |||
253 | if (pdata->otg) | 214 | if (pdata->otg) |
254 | usb_phy_shutdown(pdata->otg); | 215 | usb_phy_shutdown(pdata->otg); |
255 | 216 | ||
256 | usb_remove_hcd(hcd); | ||
257 | usb_put_hcd(hcd); | ||
258 | platform_set_drvdata(pdev, NULL); | ||
259 | |||
260 | clk_disable_unprepare(priv->usbclk); | 217 | clk_disable_unprepare(priv->usbclk); |
261 | clk_disable_unprepare(priv->ahbclk); | 218 | clk_disable_unprepare(priv->ahbclk); |
262 | 219 | ||
263 | if (priv->phyclk) | 220 | if (priv->phyclk) |
264 | clk_disable_unprepare(priv->phyclk); | 221 | clk_disable_unprepare(priv->phyclk); |
265 | 222 | ||
223 | usb_put_hcd(hcd); | ||
224 | platform_set_drvdata(pdev, NULL); | ||
266 | return 0; | 225 | return 0; |
267 | } | 226 | } |
268 | 227 | ||
269 | static void ehci_mxc_drv_shutdown(struct platform_device *pdev) | 228 | static void ehci_mxc_drv_shutdown(struct platform_device *pdev) |
270 | { | 229 | { |
271 | struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); | 230 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
272 | struct usb_hcd *hcd = priv->hcd; | ||
273 | 231 | ||
274 | if (hcd->driver->shutdown) | 232 | if (hcd->driver->shutdown) |
275 | hcd->driver->shutdown(hcd); | 233 | hcd->driver->shutdown(hcd); |
@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci"); | |||
279 | 237 | ||
280 | static struct platform_driver ehci_mxc_driver = { | 238 | static struct platform_driver ehci_mxc_driver = { |
281 | .probe = ehci_mxc_drv_probe, | 239 | .probe = ehci_mxc_drv_probe, |
282 | .remove = __exit_p(ehci_mxc_drv_remove), | 240 | .remove = ehci_mxc_drv_remove, |
283 | .shutdown = ehci_mxc_drv_shutdown, | 241 | .shutdown = ehci_mxc_drv_shutdown, |
284 | .driver = { | 242 | .driver = { |
285 | .name = "mxc-ehci", | 243 | .name = "mxc-ehci", |
286 | }, | 244 | }, |
287 | }; | 245 | }; |
246 | |||
247 | static int __init ehci_mxc_init(void) | ||
248 | { | ||
249 | if (usb_disabled()) | ||
250 | return -ENODEV; | ||
251 | |||
252 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
253 | |||
254 | ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides); | ||
255 | return platform_driver_register(&ehci_mxc_driver); | ||
256 | } | ||
257 | module_init(ehci_mxc_init); | ||
258 | |||
259 | static void __exit ehci_mxc_cleanup(void) | ||
260 | { | ||
261 | platform_driver_unregister(&ehci_mxc_driver); | ||
262 | } | ||
263 | module_exit(ehci_mxc_cleanup); | ||
264 | |||
265 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
266 | MODULE_AUTHOR("Sascha Hauer"); | ||
267 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dabb20494826..170b9399e09f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -200,6 +200,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
200 | break; | 200 | break; |
201 | } | 201 | } |
202 | 202 | ||
203 | /* optional debug port, normally in the first BAR */ | ||
204 | temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); | ||
205 | if (temp) { | ||
206 | pci_read_config_dword(pdev, temp, &temp); | ||
207 | temp >>= 16; | ||
208 | if (((temp >> 13) & 7) == 1) { | ||
209 | u32 hcs_params = ehci_readl(ehci, | ||
210 | &ehci->caps->hcs_params); | ||
211 | |||
212 | temp &= 0x1fff; | ||
213 | ehci->debug = hcd->regs + temp; | ||
214 | temp = ehci_readl(ehci, &ehci->debug->control); | ||
215 | ehci_info(ehci, "debug port %d%s\n", | ||
216 | HCS_DEBUG_PORT(hcs_params), | ||
217 | (temp & DBGP_ENABLED) ? " IN USE" : ""); | ||
218 | if (!(temp & DBGP_ENABLED)) | ||
219 | ehci->debug = NULL; | ||
220 | } | ||
221 | } | ||
222 | |||
203 | retval = ehci_setup(hcd); | 223 | retval = ehci_setup(hcd); |
204 | if (retval) | 224 | if (retval) |
205 | return retval; | 225 | return retval; |
@@ -228,25 +248,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
228 | break; | 248 | break; |
229 | } | 249 | } |
230 | 250 | ||
231 | /* optional debug port, normally in the first BAR */ | ||
232 | temp = pci_find_capability(pdev, 0x0a); | ||
233 | if (temp) { | ||
234 | pci_read_config_dword(pdev, temp, &temp); | ||
235 | temp >>= 16; | ||
236 | if ((temp & (3 << 13)) == (1 << 13)) { | ||
237 | temp &= 0x1fff; | ||
238 | ehci->debug = hcd->regs + temp; | ||
239 | temp = ehci_readl(ehci, &ehci->debug->control); | ||
240 | ehci_info(ehci, "debug port %d%s\n", | ||
241 | HCS_DEBUG_PORT(ehci->hcs_params), | ||
242 | (temp & DBGP_ENABLED) | ||
243 | ? " IN USE" | ||
244 | : ""); | ||
245 | if (!(temp & DBGP_ENABLED)) | ||
246 | ehci->debug = NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | /* at least the Genesys GL880S needs fixup here */ | 251 | /* at least the Genesys GL880S needs fixup here */ |
251 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); | 252 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); |
252 | temp &= 0x0f; | 253 | temp &= 0x0f; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9dadc7118d68..36c3a8210595 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16; | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | /* statistics can be kept for tuning/monitoring */ | 40 | /* statistics can be kept for tuning/monitoring */ |
41 | #ifdef DEBUG | ||
42 | #define EHCI_STATS | ||
43 | #endif | ||
44 | |||
41 | struct ehci_stats { | 45 | struct ehci_stats { |
42 | /* irq usage */ | 46 | /* irq usage */ |
43 | unsigned long normal; | 47 | unsigned long normal; |
@@ -221,6 +225,9 @@ struct ehci_hcd { /* one per controller */ | |||
221 | #ifdef DEBUG | 225 | #ifdef DEBUG |
222 | struct dentry *debug_dir; | 226 | struct dentry *debug_dir; |
223 | #endif | 227 | #endif |
228 | |||
229 | /* platform-specific data -- must come last */ | ||
230 | unsigned long priv[0] __aligned(sizeof(s64)); | ||
224 | }; | 231 | }; |
225 | 232 | ||
226 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ | 233 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 5105127c1d4b..11e0b79ff9d5 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c | |||
@@ -142,6 +142,9 @@ static int usb_get_ver_info(struct device_node *np) | |||
142 | return ver; | 142 | return ver; |
143 | } | 143 | } |
144 | 144 | ||
145 | if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr")) | ||
146 | return FSL_USB_VER_OLD; | ||
147 | |||
145 | if (of_device_is_compatible(np, "fsl-usb2-mph")) { | 148 | if (of_device_is_compatible(np, "fsl-usb2-mph")) { |
146 | if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) | 149 | if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) |
147 | ver = FSL_USB_VER_1_6; | 150 | ver = FSL_USB_VER_1_6; |
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index bd6a7447ccc9..f0ebe8e7c58b 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/usb.h> | 58 | #include <linux/usb.h> |
59 | #include <linux/usb/hcd.h> | 59 | #include <linux/usb/hcd.h> |
60 | #include <linux/dma-mapping.h> | 60 | #include <linux/dma-mapping.h> |
61 | #include <linux/module.h> | ||
61 | 62 | ||
62 | #include "imx21-hcd.h" | 63 | #include "imx21-hcd.h" |
63 | 64 | ||
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index d370245a4ee2..5e3a6deb62b1 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c | |||
@@ -128,7 +128,8 @@ static void tmio_start_hc(struct platform_device *dev) | |||
128 | tmio_iowrite8(2, tmio->ccr + CCR_INTC); | 128 | tmio_iowrite8(2, tmio->ccr + CCR_INTC); |
129 | 129 | ||
130 | dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", | 130 | dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", |
131 | tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq); | 131 | tmio_ioread8(tmio->ccr + CCR_REVID), |
132 | (u64) hcd->rsrc_start, hcd->irq); | ||
132 | } | 133 | } |
133 | 134 | ||
134 | static int ohci_tmio_start(struct usb_hcd *hcd) | 135 | static int ohci_tmio_start(struct usb_hcd *hcd) |
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4b9e9aba2665..4f64d24eebc8 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
447 | return IRQ_NONE; | 447 | return IRQ_NONE; |
448 | uhci_writew(uhci, status, USBSTS); /* Clear it */ | 448 | uhci_writew(uhci, status, USBSTS); /* Clear it */ |
449 | 449 | ||
450 | spin_lock(&uhci->lock); | ||
451 | if (unlikely(!uhci->is_initialized)) /* not yet configured */ | ||
452 | goto done; | ||
453 | |||
450 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | 454 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { |
451 | if (status & USBSTS_HSE) | 455 | if (status & USBSTS_HSE) |
452 | dev_err(uhci_dev(uhci), "host system error, " | 456 | dev_err(uhci_dev(uhci), "host system error, " |
@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
455 | dev_err(uhci_dev(uhci), "host controller process " | 459 | dev_err(uhci_dev(uhci), "host controller process " |
456 | "error, something bad happened!\n"); | 460 | "error, something bad happened!\n"); |
457 | if (status & USBSTS_HCH) { | 461 | if (status & USBSTS_HCH) { |
458 | spin_lock(&uhci->lock); | ||
459 | if (uhci->rh_state >= UHCI_RH_RUNNING) { | 462 | if (uhci->rh_state >= UHCI_RH_RUNNING) { |
460 | dev_err(uhci_dev(uhci), | 463 | dev_err(uhci_dev(uhci), |
461 | "host controller halted, " | 464 | "host controller halted, " |
@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
473 | * pending unlinks */ | 476 | * pending unlinks */ |
474 | mod_timer(&hcd->rh_timer, jiffies); | 477 | mod_timer(&hcd->rh_timer, jiffies); |
475 | } | 478 | } |
476 | spin_unlock(&uhci->lock); | ||
477 | } | 479 | } |
478 | } | 480 | } |
479 | 481 | ||
480 | if (status & USBSTS_RD) | 482 | if (status & USBSTS_RD) { |
483 | spin_unlock(&uhci->lock); | ||
481 | usb_hcd_poll_rh_status(hcd); | 484 | usb_hcd_poll_rh_status(hcd); |
482 | else { | 485 | } else { |
483 | spin_lock(&uhci->lock); | ||
484 | uhci_scan_schedule(uhci); | 486 | uhci_scan_schedule(uhci); |
487 | done: | ||
485 | spin_unlock(&uhci->lock); | 488 | spin_unlock(&uhci->lock); |
486 | } | 489 | } |
487 | 490 | ||
@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) | |||
662 | */ | 665 | */ |
663 | mb(); | 666 | mb(); |
664 | 667 | ||
668 | spin_lock_irq(&uhci->lock); | ||
665 | configure_hc(uhci); | 669 | configure_hc(uhci); |
666 | uhci->is_initialized = 1; | 670 | uhci->is_initialized = 1; |
667 | spin_lock_irq(&uhci->lock); | ||
668 | start_rh(uhci); | 671 | start_rh(uhci); |
669 | spin_unlock_irq(&uhci->lock); | 672 | spin_unlock_irq(&uhci->lock); |
670 | return 0; | 673 | return 0; |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a686cf4905bb..68914429482f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
761 | break; | 761 | break; |
762 | case USB_PORT_FEAT_LINK_STATE: | 762 | case USB_PORT_FEAT_LINK_STATE: |
763 | temp = xhci_readl(xhci, port_array[wIndex]); | 763 | temp = xhci_readl(xhci, port_array[wIndex]); |
764 | |||
765 | /* Disable port */ | ||
766 | if (link_state == USB_SS_PORT_LS_SS_DISABLED) { | ||
767 | xhci_dbg(xhci, "Disable port %d\n", wIndex); | ||
768 | temp = xhci_port_state_to_neutral(temp); | ||
769 | /* | ||
770 | * Clear all change bits, so that we get a new | ||
771 | * connection event. | ||
772 | */ | ||
773 | temp |= PORT_CSC | PORT_PEC | PORT_WRC | | ||
774 | PORT_OCC | PORT_RC | PORT_PLC | | ||
775 | PORT_CEC; | ||
776 | xhci_writel(xhci, temp | PORT_PE, | ||
777 | port_array[wIndex]); | ||
778 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
779 | break; | ||
780 | } | ||
781 | |||
782 | /* Put link in RxDetect (enable port) */ | ||
783 | if (link_state == USB_SS_PORT_LS_RX_DETECT) { | ||
784 | xhci_dbg(xhci, "Enable port %d\n", wIndex); | ||
785 | xhci_set_link_state(xhci, port_array, wIndex, | ||
786 | link_state); | ||
787 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
788 | break; | ||
789 | } | ||
790 | |||
764 | /* Software should not attempt to set | 791 | /* Software should not attempt to set |
765 | * port link state above '5' (Rx.Detect) and the port | 792 | * port link state above '3' (U3) and the port |
766 | * must be enabled. | 793 | * must be enabled. |
767 | */ | 794 | */ |
768 | if ((temp & PORT_PE) == 0 || | 795 | if ((temp & PORT_PE) == 0 || |
769 | (link_state > USB_SS_PORT_LS_RX_DETECT)) { | 796 | (link_state > USB_SS_PORT_LS_U3)) { |
770 | xhci_warn(xhci, "Cannot set link state.\n"); | 797 | xhci_warn(xhci, "Cannot set link state.\n"); |
771 | goto error; | 798 | goto error; |
772 | } | 799 | } |
@@ -957,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
957 | int max_ports; | 984 | int max_ports; |
958 | __le32 __iomem **port_array; | 985 | __le32 __iomem **port_array; |
959 | struct xhci_bus_state *bus_state; | 986 | struct xhci_bus_state *bus_state; |
987 | bool reset_change = false; | ||
960 | 988 | ||
961 | max_ports = xhci_get_ports(hcd, &port_array); | 989 | max_ports = xhci_get_ports(hcd, &port_array); |
962 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 990 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
@@ -988,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
988 | buf[(i + 1) / 8] |= 1 << (i + 1) % 8; | 1016 | buf[(i + 1) / 8] |= 1 << (i + 1) % 8; |
989 | status = 1; | 1017 | status = 1; |
990 | } | 1018 | } |
1019 | if ((temp & PORT_RC)) | ||
1020 | reset_change = true; | ||
1021 | } | ||
1022 | if (!status && !reset_change) { | ||
1023 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); | ||
1024 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
991 | } | 1025 | } |
992 | spin_unlock_irqrestore(&xhci->lock, flags); | 1026 | spin_unlock_irqrestore(&xhci->lock, flags); |
993 | return status ? retval : 0; | 1027 | return status ? retval : 0; |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fb51c7085ad0..35616ffbe3ae 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, | |||
1250 | static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, | 1250 | static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, |
1251 | struct usb_host_endpoint *ep) | 1251 | struct usb_host_endpoint *ep) |
1252 | { | 1252 | { |
1253 | if (ep->desc.bInterval == 0) | ||
1254 | return 0; | ||
1253 | return xhci_microframes_to_exponent(udev, ep, | 1255 | return xhci_microframes_to_exponent(udev, ep, |
1254 | ep->desc.bInterval, 0, 15); | 1256 | ep->desc.bInterval, 0, 15); |
1255 | } | 1257 | } |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index cbb44b7b9d65..59fb5c677dbe 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1725,6 +1725,15 @@ cleanup: | |||
1725 | if (bogus_port_status) | 1725 | if (bogus_port_status) |
1726 | return; | 1726 | return; |
1727 | 1727 | ||
1728 | /* | ||
1729 | * xHCI port-status-change events occur when the "or" of all the | ||
1730 | * status-change bits in the portsc register changes from 0 to 1. | ||
1731 | * New status changes won't cause an event if any other change | ||
1732 | * bits are still set. When an event occurs, switch over to | ||
1733 | * polling to avoid losing status changes. | ||
1734 | */ | ||
1735 | xhci_dbg(xhci, "%s: starting port polling.\n", __func__); | ||
1736 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
1728 | spin_unlock(&xhci->lock); | 1737 | spin_unlock(&xhci->lock); |
1729 | /* Pass this up to the core */ | 1738 | /* Pass this up to the core */ |
1730 | usb_hcd_poll_rh_status(hcd); | 1739 | usb_hcd_poll_rh_status(hcd); |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5c72c431bab1..f1f01a834ba7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -884,6 +884,11 @@ int xhci_suspend(struct xhci_hcd *xhci) | |||
884 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) | 884 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) |
885 | return -EINVAL; | 885 | return -EINVAL; |
886 | 886 | ||
887 | /* Don't poll the roothubs on bus suspend. */ | ||
888 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); | ||
889 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
890 | del_timer_sync(&hcd->rh_timer); | ||
891 | |||
887 | spin_lock_irq(&xhci->lock); | 892 | spin_lock_irq(&xhci->lock); |
888 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 893 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
889 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); | 894 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); |
@@ -1069,6 +1074,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) | |||
1069 | if (xhci->quirks & XHCI_COMP_MODE_QUIRK) | 1074 | if (xhci->quirks & XHCI_COMP_MODE_QUIRK) |
1070 | compliance_mode_recovery_timer_init(xhci); | 1075 | compliance_mode_recovery_timer_init(xhci); |
1071 | 1076 | ||
1077 | /* Re-enable port polling. */ | ||
1078 | xhci_dbg(xhci, "%s: starting port polling.\n", __func__); | ||
1079 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
1080 | usb_hcd_poll_rh_status(hcd); | ||
1081 | |||
1072 | return retval; | 1082 | return retval; |
1073 | } | 1083 | } |
1074 | #endif /* CONFIG_PM */ | 1084 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 7667b12f2ff5..268148de9714 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -2179,7 +2179,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2179 | if (dev->out_pipe == 0 || !param->length || param->sglen < 4) | 2179 | if (dev->out_pipe == 0 || !param->length || param->sglen < 4) |
2180 | break; | 2180 | break; |
2181 | retval = 0; | 2181 | retval = 0; |
2182 | dev_info(&intf->dev, "TEST 17: unlink from %d queues of " | 2182 | dev_info(&intf->dev, "TEST 24: unlink from %d queues of " |
2183 | "%d %d-byte writes\n", | 2183 | "%d %d-byte writes\n", |
2184 | param->iterations, param->sglen, param->length); | 2184 | param->iterations, param->sglen, param->length); |
2185 | for (i = param->iterations; retval == 0 && i > 0; --i) { | 2185 | for (i = param->iterations; retval == 0 && i > 0; --i) { |
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 0968dd7a859d..f522000e8f06 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr) | |||
105 | musb_writel(&tx->tx_complete, 0, ptr); | 105 | musb_writel(&tx->tx_complete, 0, ptr); |
106 | } | 106 | } |
107 | 107 | ||
108 | static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) | 108 | static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) |
109 | { | 109 | { |
110 | int j; | 110 | int j; |
111 | 111 | ||
@@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c) | |||
150 | c->last_processed = NULL; | 150 | c->last_processed = NULL; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int __init cppi_controller_start(struct dma_controller *c) | 153 | static int cppi_controller_start(struct dma_controller *c) |
154 | { | 154 | { |
155 | struct cppi *controller; | 155 | struct cppi *controller; |
156 | void __iomem *tibase; | 156 | void __iomem *tibase; |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index f1c6c5470b92..fd3486745e64 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -2298,10 +2298,7 @@ static int __init musb_init(void) | |||
2298 | if (usb_disabled()) | 2298 | if (usb_disabled()) |
2299 | return 0; | 2299 | return 0; |
2300 | 2300 | ||
2301 | pr_info("%s: version " MUSB_VERSION ", " | 2301 | pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", |
2302 | "?dma?" | ||
2303 | ", " | ||
2304 | "otg (peripheral+host)", | ||
2305 | musb_driver_name); | 2302 | musb_driver_name); |
2306 | return platform_driver_register(&musb_driver); | 2303 | return platform_driver_register(&musb_driver); |
2307 | } | 2304 | } |
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index e6f2ae8368bb..f7d764de6fda 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -134,6 +134,11 @@ static const resource_size_t dsps_control_module_phys[] = { | |||
134 | DSPS_AM33XX_CONTROL_MODULE_PHYS_1, | 134 | DSPS_AM33XX_CONTROL_MODULE_PHYS_1, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | #define USBPHY_CM_PWRDN (1 << 0) | ||
138 | #define USBPHY_OTG_PWRDN (1 << 1) | ||
139 | #define USBPHY_OTGVDET_EN (1 << 19) | ||
140 | #define USBPHY_OTGSESSEND_EN (1 << 20) | ||
141 | |||
137 | /** | 142 | /** |
138 | * musb_dsps_phy_control - phy on/off | 143 | * musb_dsps_phy_control - phy on/off |
139 | * @glue: struct dsps_glue * | 144 | * @glue: struct dsps_glue * |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 6223062d5d1b..37962c99ff1e 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -110,7 +110,7 @@ config AB8500_USB | |||
110 | 110 | ||
111 | config FSL_USB2_OTG | 111 | config FSL_USB2_OTG |
112 | bool "Freescale USB OTG Transceiver Driver" | 112 | bool "Freescale USB OTG Transceiver Driver" |
113 | depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND | 113 | depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND |
114 | select USB_OTG | 114 | select USB_OTG |
115 | select USB_OTG_UTILS | 115 | select USB_OTG_UTILS |
116 | help | 116 | help |
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 1dd57504186d..eace975991a8 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c | |||
@@ -240,7 +240,7 @@ static void otg_clock_enable(struct mv_otg *mvotg) | |||
240 | unsigned int i; | 240 | unsigned int i; |
241 | 241 | ||
242 | for (i = 0; i < mvotg->clknum; i++) | 242 | for (i = 0; i < mvotg->clknum; i++) |
243 | clk_enable(mvotg->clk[i]); | 243 | clk_prepare_enable(mvotg->clk[i]); |
244 | } | 244 | } |
245 | 245 | ||
246 | static void otg_clock_disable(struct mv_otg *mvotg) | 246 | static void otg_clock_disable(struct mv_otg *mvotg) |
@@ -248,7 +248,7 @@ static void otg_clock_disable(struct mv_otg *mvotg) | |||
248 | unsigned int i; | 248 | unsigned int i; |
249 | 249 | ||
250 | for (i = 0; i < mvotg->clknum; i++) | 250 | for (i = 0; i < mvotg->clknum; i++) |
251 | clk_disable(mvotg->clk[i]); | 251 | clk_disable_unprepare(mvotg->clk[i]); |
252 | } | 252 | } |
253 | 253 | ||
254 | static int mv_otg_enable_internal(struct mv_otg *mvotg) | 254 | static int mv_otg_enable_internal(struct mv_otg *mvotg) |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index dd41f61893ef..f2985cd88021 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -545,15 +545,6 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep) | |||
545 | return 0; | 545 | return 0; |
546 | } | 546 | } |
547 | 547 | ||
548 | static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv) | ||
549 | { | ||
550 | int i; | ||
551 | struct usbhsg_uep *uep; | ||
552 | |||
553 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) | ||
554 | uep->pipe = NULL; | ||
555 | } | ||
556 | |||
557 | /* | 548 | /* |
558 | * | 549 | * |
559 | * usb_ep_ops | 550 | * usb_ep_ops |
@@ -610,7 +601,12 @@ static int usbhsg_ep_disable(struct usb_ep *ep) | |||
610 | { | 601 | { |
611 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 602 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
612 | 603 | ||
613 | return usbhsg_pipe_disable(uep); | 604 | usbhsg_pipe_disable(uep); |
605 | |||
606 | uep->pipe->mod_private = NULL; | ||
607 | uep->pipe = NULL; | ||
608 | |||
609 | return 0; | ||
614 | } | 610 | } |
615 | 611 | ||
616 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | 612 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, |
@@ -761,9 +757,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
761 | usbhs_pipe_init(priv, | 757 | usbhs_pipe_init(priv, |
762 | usbhsg_dma_map_ctrl); | 758 | usbhsg_dma_map_ctrl); |
763 | usbhs_fifo_init(priv); | 759 | usbhs_fifo_init(priv); |
764 | usbhsg_uep_init(gpriv); | ||
765 | 760 | ||
766 | /* dcp init */ | 761 | /* dcp init instead of usbhsg_ep_enable() */ |
767 | dcp->pipe = usbhs_dcp_malloc(priv); | 762 | dcp->pipe = usbhs_dcp_malloc(priv); |
768 | dcp->pipe->mod_private = dcp; | 763 | dcp->pipe->mod_private = dcp; |
769 | usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); | 764 | usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); |
@@ -825,7 +820,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
825 | usbhs_sys_set_test_mode(priv, 0); | 820 | usbhs_sys_set_test_mode(priv, 0); |
826 | usbhs_sys_function_ctrl(priv, 0); | 821 | usbhs_sys_function_ctrl(priv, 0); |
827 | 822 | ||
828 | usbhsg_pipe_disable(dcp); | 823 | usbhsg_ep_disable(&dcp->ep); |
829 | 824 | ||
830 | dev_dbg(dev, "stop gadget\n"); | 825 | dev_dbg(dev, "stop gadget\n"); |
831 | 826 | ||
@@ -998,6 +993,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
998 | */ | 993 | */ |
999 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { | 994 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { |
1000 | uep->gpriv = gpriv; | 995 | uep->gpriv = gpriv; |
996 | uep->pipe = NULL; | ||
1001 | snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); | 997 | snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); |
1002 | 998 | ||
1003 | uep->ep.name = uep->ep_name; | 999 | uep->ep.name = uep->ep_name; |
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 3d3cd6ca2689..b86815421c8d 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -661,9 +661,10 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) | |||
661 | status = -ESHUTDOWN; | 661 | status = -ESHUTDOWN; |
662 | 662 | ||
663 | urb->actual_length = pkt->actual; | 663 | urb->actual_length = pkt->actual; |
664 | usbhsh_ureq_free(hpriv, ureq); | ||
665 | 664 | ||
666 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); | 665 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); |
666 | usbhsh_ureq_free(hpriv, ureq); | ||
667 | |||
667 | usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); | 668 | usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); |
668 | 669 | ||
669 | usb_hcd_unlink_urb_from_ep(hcd, urb); | 670 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0a373b3ae96a..ba68835d06a6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -875,6 +875,8 @@ static struct usb_device_id id_table_combined [] = { | |||
875 | { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), | 875 | { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), |
876 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 876 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
877 | { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, | 877 | { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, |
878 | /* Crucible Devices */ | ||
879 | { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, | ||
878 | { }, /* Optional parameter entry */ | 880 | { }, /* Optional parameter entry */ |
879 | { } /* Terminating entry */ | 881 | { } /* Terminating entry */ |
880 | }; | 882 | }; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 049b6e715fa4..fa5d56038276 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -1259,3 +1259,9 @@ | |||
1259 | * ATI command output: Cinterion MC55i | 1259 | * ATI command output: Cinterion MC55i |
1260 | */ | 1260 | */ |
1261 | #define FTDI_CINTERION_MC55I_PID 0xA951 | 1261 | #define FTDI_CINTERION_MC55I_PID 0xA951 |
1262 | |||
1263 | /* | ||
1264 | * Product: Comet Caller ID decoder | ||
1265 | * Manufacturer: Crucible Technologies | ||
1266 | */ | ||
1267 | #define FTDI_CT_COMET_PID 0x8e08 | ||
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 58184f3de686..82afc4d6a327 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
530 | wait_queue_t wait; | 530 | wait_queue_t wait; |
531 | unsigned long flags; | 531 | unsigned long flags; |
532 | 532 | ||
533 | if (!tty) | ||
534 | return; | ||
535 | |||
533 | if (!timeout) | 536 | if (!timeout) |
534 | timeout = (HZ * EDGE_CLOSING_WAIT)/100; | 537 | timeout = (HZ * EDGE_CLOSING_WAIT)/100; |
535 | 538 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e6f87b76c715..0d9dac9e7f93 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -288,6 +288,7 @@ static void option_instat_callback(struct urb *urb); | |||
288 | #define ALCATEL_VENDOR_ID 0x1bbb | 288 | #define ALCATEL_VENDOR_ID 0x1bbb |
289 | #define ALCATEL_PRODUCT_X060S_X200 0x0000 | 289 | #define ALCATEL_PRODUCT_X060S_X200 0x0000 |
290 | #define ALCATEL_PRODUCT_X220_X500D 0x0017 | 290 | #define ALCATEL_PRODUCT_X220_X500D 0x0017 |
291 | #define ALCATEL_PRODUCT_L100V 0x011e | ||
291 | 292 | ||
292 | #define PIRELLI_VENDOR_ID 0x1266 | 293 | #define PIRELLI_VENDOR_ID 0x1266 |
293 | #define PIRELLI_PRODUCT_C100_1 0x1002 | 294 | #define PIRELLI_PRODUCT_C100_1 0x1002 |
@@ -429,9 +430,12 @@ static void option_instat_callback(struct urb *urb); | |||
429 | #define MEDIATEK_VENDOR_ID 0x0e8d | 430 | #define MEDIATEK_VENDOR_ID 0x0e8d |
430 | #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 | 431 | #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 |
431 | #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 | 432 | #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 |
433 | #define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 | ||
432 | #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 | 434 | #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 |
433 | #define MEDIATEK_PRODUCT_7208_1COM 0x7101 | 435 | #define MEDIATEK_PRODUCT_7208_1COM 0x7101 |
434 | #define MEDIATEK_PRODUCT_7208_2COM 0x7102 | 436 | #define MEDIATEK_PRODUCT_7208_2COM 0x7102 |
437 | #define MEDIATEK_PRODUCT_7103_2COM 0x7103 | ||
438 | #define MEDIATEK_PRODUCT_7106_2COM 0x7106 | ||
435 | #define MEDIATEK_PRODUCT_FP_1COM 0x0003 | 439 | #define MEDIATEK_PRODUCT_FP_1COM 0x0003 |
436 | #define MEDIATEK_PRODUCT_FP_2COM 0x0023 | 440 | #define MEDIATEK_PRODUCT_FP_2COM 0x0023 |
437 | #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 | 441 | #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 |
@@ -441,6 +445,14 @@ static void option_instat_callback(struct urb *urb); | |||
441 | #define CELLIENT_VENDOR_ID 0x2692 | 445 | #define CELLIENT_VENDOR_ID 0x2692 |
442 | #define CELLIENT_PRODUCT_MEN200 0x9005 | 446 | #define CELLIENT_PRODUCT_MEN200 0x9005 |
443 | 447 | ||
448 | /* Hyundai Petatel Inc. products */ | ||
449 | #define PETATEL_VENDOR_ID 0x1ff4 | ||
450 | #define PETATEL_PRODUCT_NP10T 0x600e | ||
451 | |||
452 | /* TP-LINK Incorporated products */ | ||
453 | #define TPLINK_VENDOR_ID 0x2357 | ||
454 | #define TPLINK_PRODUCT_MA180 0x0201 | ||
455 | |||
444 | /* some devices interfaces need special handling due to a number of reasons */ | 456 | /* some devices interfaces need special handling due to a number of reasons */ |
445 | enum option_blacklist_reason { | 457 | enum option_blacklist_reason { |
446 | OPTION_BLACKLIST_NONE = 0, | 458 | OPTION_BLACKLIST_NONE = 0, |
@@ -922,8 +934,10 @@ static const struct usb_device_id option_ids[] = { | |||
922 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, | 934 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, |
923 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ | 935 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ |
924 | .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, | 936 | .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, |
925 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, | 937 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ |
926 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, | 938 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
939 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ | ||
940 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
927 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, | 941 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, |
928 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), | 942 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), |
929 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | 943 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
@@ -1190,6 +1204,8 @@ static const struct usb_device_id option_ids[] = { | |||
1190 | .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist | 1204 | .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist |
1191 | }, | 1205 | }, |
1192 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, | 1206 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, |
1207 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), | ||
1208 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
1193 | { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, | 1209 | { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, |
1194 | { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, | 1210 | { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, |
1195 | { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), | 1211 | { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), |
@@ -1294,7 +1310,14 @@ static const struct usb_device_id option_ids[] = { | |||
1294 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, | 1310 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, |
1295 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, | 1311 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, |
1296 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, | 1312 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, |
1313 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, | ||
1314 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, | ||
1315 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, | ||
1316 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, | ||
1297 | { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, | 1317 | { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, |
1318 | { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, | ||
1319 | { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), | ||
1320 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
1298 | { } /* Terminating entry */ | 1321 | { } /* Terminating entry */ |
1299 | }; | 1322 | }; |
1300 | MODULE_DEVICE_TABLE(usb, option_ids); | 1323 | MODULE_DEVICE_TABLE(usb, option_ids); |
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 4362d9e7baa3..f72323ef618f 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c | |||
@@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf, | |||
240 | filled = 1; | 240 | filled = 1; |
241 | } else { | 241 | } else { |
242 | /* Drop writes, fill reads with FF */ | 242 | /* Drop writes, fill reads with FF */ |
243 | filled = min((size_t)(x_end - pos), count); | ||
243 | if (!iswrite) { | 244 | if (!iswrite) { |
244 | char val = 0xFF; | 245 | char val = 0xFF; |
245 | size_t i; | 246 | size_t i; |
246 | 247 | ||
247 | for (i = 0; i < x_end - pos; i++) { | 248 | for (i = 0; i < filled; i++) { |
248 | if (put_user(val, buf + i)) | 249 | if (put_user(val, buf + i)) |
249 | goto out; | 250 | goto out; |
250 | } | 251 | } |
251 | } | 252 | } |
252 | 253 | ||
253 | filled = x_end - pos; | ||
254 | } | 254 | } |
255 | 255 | ||
256 | count -= filled; | 256 | count -= filled; |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 12526787a7c7..0abf2bf20836 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -139,6 +139,7 @@ struct imxfb_info { | |||
139 | struct clk *clk_ahb; | 139 | struct clk *clk_ahb; |
140 | struct clk *clk_per; | 140 | struct clk *clk_per; |
141 | enum imxfb_type devtype; | 141 | enum imxfb_type devtype; |
142 | bool enabled; | ||
142 | 143 | ||
143 | /* | 144 | /* |
144 | * These are the addresses we mapped | 145 | * These are the addresses we mapped |
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) | |||
536 | 537 | ||
537 | static void imxfb_enable_controller(struct imxfb_info *fbi) | 538 | static void imxfb_enable_controller(struct imxfb_info *fbi) |
538 | { | 539 | { |
540 | |||
541 | if (fbi->enabled) | ||
542 | return; | ||
543 | |||
539 | pr_debug("Enabling LCD controller\n"); | 544 | pr_debug("Enabling LCD controller\n"); |
540 | 545 | ||
541 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); | 546 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); |
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
556 | clk_prepare_enable(fbi->clk_ipg); | 561 | clk_prepare_enable(fbi->clk_ipg); |
557 | clk_prepare_enable(fbi->clk_ahb); | 562 | clk_prepare_enable(fbi->clk_ahb); |
558 | clk_prepare_enable(fbi->clk_per); | 563 | clk_prepare_enable(fbi->clk_per); |
564 | fbi->enabled = true; | ||
559 | 565 | ||
560 | if (fbi->backlight_power) | 566 | if (fbi->backlight_power) |
561 | fbi->backlight_power(1); | 567 | fbi->backlight_power(1); |
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
565 | 571 | ||
566 | static void imxfb_disable_controller(struct imxfb_info *fbi) | 572 | static void imxfb_disable_controller(struct imxfb_info *fbi) |
567 | { | 573 | { |
574 | if (!fbi->enabled) | ||
575 | return; | ||
576 | |||
568 | pr_debug("Disabling LCD controller\n"); | 577 | pr_debug("Disabling LCD controller\n"); |
569 | 578 | ||
570 | if (fbi->backlight_power) | 579 | if (fbi->backlight_power) |
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) | |||
575 | clk_disable_unprepare(fbi->clk_per); | 584 | clk_disable_unprepare(fbi->clk_per); |
576 | clk_disable_unprepare(fbi->clk_ipg); | 585 | clk_disable_unprepare(fbi->clk_ipg); |
577 | clk_disable_unprepare(fbi->clk_ahb); | 586 | clk_disable_unprepare(fbi->clk_ahb); |
587 | fbi->enabled = false; | ||
578 | 588 | ||
579 | writel(0, fbi->regs + LCDC_RMCR); | 589 | writel(0, fbi->regs + LCDC_RMCR); |
580 | } | 590 | } |
@@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) | |||
729 | 739 | ||
730 | memset(fbi, 0, sizeof(struct imxfb_info)); | 740 | memset(fbi, 0, sizeof(struct imxfb_info)); |
731 | 741 | ||
742 | fbi->devtype = pdev->id_entry->driver_data; | ||
743 | |||
732 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); | 744 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); |
733 | 745 | ||
734 | info->fix.type = FB_TYPE_PACKED_PIXELS; | 746 | info->fix.type = FB_TYPE_PACKED_PIXELS; |
@@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
789 | return -ENOMEM; | 801 | return -ENOMEM; |
790 | 802 | ||
791 | fbi = info->par; | 803 | fbi = info->par; |
792 | fbi->devtype = pdev->id_entry->driver_data; | ||
793 | 804 | ||
794 | if (!fb_mode) | 805 | if (!fb_mode) |
795 | fb_mode = pdata->mode[0].mode.name; | 806 | fb_mode = pdata->mode[0].mode.name; |
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 4d99dd7a6831..395cb6a8d8f3 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c | |||
@@ -145,8 +145,8 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par) | |||
145 | u32 page_length = SSD1307FB_WIDTH * i; | 145 | u32 page_length = SSD1307FB_WIDTH * i; |
146 | u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; | 146 | u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; |
147 | u8 byte = *(vmem + index); | 147 | u8 byte = *(vmem + index); |
148 | u8 bit = byte & (1 << (7 - (j % 8))); | 148 | u8 bit = byte & (1 << (j % 8)); |
149 | bit = bit >> (7 - (j % 8)); | 149 | bit = bit >> (j % 8); |
150 | buf |= bit << k; | 150 | buf |= bit << k; |
151 | } | 151 | } |
152 | ssd1307fb_write_data(par->client, buf); | 152 | ssd1307fb_write_data(par->client, buf); |
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 4dcfced107f5..084041d42c9a 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c | |||
@@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu) | |||
25 | static int vcpu_online(unsigned int cpu) | 25 | static int vcpu_online(unsigned int cpu) |
26 | { | 26 | { |
27 | int err; | 27 | int err; |
28 | char dir[32], state[32]; | 28 | char dir[16], state[16]; |
29 | 29 | ||
30 | sprintf(dir, "cpu/%u", cpu); | 30 | sprintf(dir, "cpu/%u", cpu); |
31 | err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); | 31 | err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state); |
32 | if (err != 1) { | 32 | if (err != 1) { |
33 | if (!xen_initial_domain()) | 33 | if (!xen_initial_domain()) |
34 | printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); | 34 | printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); |
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 2e22df2f7a3f..3c8803feba26 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by " | |||
56 | static atomic_t pages_mapped = ATOMIC_INIT(0); | 56 | static atomic_t pages_mapped = ATOMIC_INIT(0); |
57 | 57 | ||
58 | static int use_ptemod; | 58 | static int use_ptemod; |
59 | #define populate_freeable_maps use_ptemod | ||
59 | 60 | ||
60 | struct gntdev_priv { | 61 | struct gntdev_priv { |
62 | /* maps with visible offsets in the file descriptor */ | ||
61 | struct list_head maps; | 63 | struct list_head maps; |
62 | /* lock protects maps from concurrent changes */ | 64 | /* maps that are not visible; will be freed on munmap. |
65 | * Only populated if populate_freeable_maps == 1 */ | ||
66 | struct list_head freeable_maps; | ||
67 | /* lock protects maps and freeable_maps */ | ||
63 | spinlock_t lock; | 68 | spinlock_t lock; |
64 | struct mm_struct *mm; | 69 | struct mm_struct *mm; |
65 | struct mmu_notifier mn; | 70 | struct mmu_notifier mn; |
@@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, | |||
193 | return NULL; | 198 | return NULL; |
194 | } | 199 | } |
195 | 200 | ||
196 | static void gntdev_put_map(struct grant_map *map) | 201 | static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) |
197 | { | 202 | { |
198 | if (!map) | 203 | if (!map) |
199 | return; | 204 | return; |
@@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map) | |||
208 | evtchn_put(map->notify.event); | 213 | evtchn_put(map->notify.event); |
209 | } | 214 | } |
210 | 215 | ||
216 | if (populate_freeable_maps && priv) { | ||
217 | spin_lock(&priv->lock); | ||
218 | list_del(&map->next); | ||
219 | spin_unlock(&priv->lock); | ||
220 | } | ||
221 | |||
211 | if (map->pages && !use_ptemod) | 222 | if (map->pages && !use_ptemod) |
212 | unmap_grant_pages(map, 0, map->count); | 223 | unmap_grant_pages(map, 0, map->count); |
213 | gntdev_free_map(map); | 224 | gntdev_free_map(map); |
@@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
301 | 312 | ||
302 | if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { | 313 | if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { |
303 | int pgno = (map->notify.addr >> PAGE_SHIFT); | 314 | int pgno = (map->notify.addr >> PAGE_SHIFT); |
304 | if (pgno >= offset && pgno < offset + pages && use_ptemod) { | 315 | if (pgno >= offset && pgno < offset + pages) { |
305 | void __user *tmp = (void __user *) | 316 | /* No need for kmap, pages are in lowmem */ |
306 | map->vma->vm_start + map->notify.addr; | 317 | uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno])); |
307 | err = copy_to_user(tmp, &err, 1); | ||
308 | if (err) | ||
309 | return -EFAULT; | ||
310 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; | ||
311 | } else if (pgno >= offset && pgno < offset + pages) { | ||
312 | uint8_t *tmp = kmap(map->pages[pgno]); | ||
313 | tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; | 318 | tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; |
314 | kunmap(map->pages[pgno]); | ||
315 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; | 319 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; |
316 | } | 320 | } |
317 | } | 321 | } |
@@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma) | |||
376 | static void gntdev_vma_close(struct vm_area_struct *vma) | 380 | static void gntdev_vma_close(struct vm_area_struct *vma) |
377 | { | 381 | { |
378 | struct grant_map *map = vma->vm_private_data; | 382 | struct grant_map *map = vma->vm_private_data; |
383 | struct file *file = vma->vm_file; | ||
384 | struct gntdev_priv *priv = file->private_data; | ||
379 | 385 | ||
380 | pr_debug("gntdev_vma_close %p\n", vma); | 386 | pr_debug("gntdev_vma_close %p\n", vma); |
381 | map->vma = NULL; | 387 | if (use_ptemod) { |
388 | /* It is possible that an mmu notifier could be running | ||
389 | * concurrently, so take priv->lock to ensure that the vma won't | ||
390 | * vanishing during the unmap_grant_pages call, since we will | ||
391 | * spin here until that completes. Such a concurrent call will | ||
392 | * not do any unmapping, since that has been done prior to | ||
393 | * closing the vma, but it may still iterate the unmap_ops list. | ||
394 | */ | ||
395 | spin_lock(&priv->lock); | ||
396 | map->vma = NULL; | ||
397 | spin_unlock(&priv->lock); | ||
398 | } | ||
382 | vma->vm_private_data = NULL; | 399 | vma->vm_private_data = NULL; |
383 | gntdev_put_map(map); | 400 | gntdev_put_map(priv, map); |
384 | } | 401 | } |
385 | 402 | ||
386 | static struct vm_operations_struct gntdev_vmops = { | 403 | static struct vm_operations_struct gntdev_vmops = { |
@@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = { | |||
390 | 407 | ||
391 | /* ------------------------------------------------------------------ */ | 408 | /* ------------------------------------------------------------------ */ |
392 | 409 | ||
410 | static void unmap_if_in_range(struct grant_map *map, | ||
411 | unsigned long start, unsigned long end) | ||
412 | { | ||
413 | unsigned long mstart, mend; | ||
414 | int err; | ||
415 | |||
416 | if (!map->vma) | ||
417 | return; | ||
418 | if (map->vma->vm_start >= end) | ||
419 | return; | ||
420 | if (map->vma->vm_end <= start) | ||
421 | return; | ||
422 | mstart = max(start, map->vma->vm_start); | ||
423 | mend = min(end, map->vma->vm_end); | ||
424 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", | ||
425 | map->index, map->count, | ||
426 | map->vma->vm_start, map->vma->vm_end, | ||
427 | start, end, mstart, mend); | ||
428 | err = unmap_grant_pages(map, | ||
429 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, | ||
430 | (mend - mstart) >> PAGE_SHIFT); | ||
431 | WARN_ON(err); | ||
432 | } | ||
433 | |||
393 | static void mn_invl_range_start(struct mmu_notifier *mn, | 434 | static void mn_invl_range_start(struct mmu_notifier *mn, |
394 | struct mm_struct *mm, | 435 | struct mm_struct *mm, |
395 | unsigned long start, unsigned long end) | 436 | unsigned long start, unsigned long end) |
396 | { | 437 | { |
397 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); | 438 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); |
398 | struct grant_map *map; | 439 | struct grant_map *map; |
399 | unsigned long mstart, mend; | ||
400 | int err; | ||
401 | 440 | ||
402 | spin_lock(&priv->lock); | 441 | spin_lock(&priv->lock); |
403 | list_for_each_entry(map, &priv->maps, next) { | 442 | list_for_each_entry(map, &priv->maps, next) { |
404 | if (!map->vma) | 443 | unmap_if_in_range(map, start, end); |
405 | continue; | 444 | } |
406 | if (map->vma->vm_start >= end) | 445 | list_for_each_entry(map, &priv->freeable_maps, next) { |
407 | continue; | 446 | unmap_if_in_range(map, start, end); |
408 | if (map->vma->vm_end <= start) | ||
409 | continue; | ||
410 | mstart = max(start, map->vma->vm_start); | ||
411 | mend = min(end, map->vma->vm_end); | ||
412 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", | ||
413 | map->index, map->count, | ||
414 | map->vma->vm_start, map->vma->vm_end, | ||
415 | start, end, mstart, mend); | ||
416 | err = unmap_grant_pages(map, | ||
417 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, | ||
418 | (mend - mstart) >> PAGE_SHIFT); | ||
419 | WARN_ON(err); | ||
420 | } | 447 | } |
421 | spin_unlock(&priv->lock); | 448 | spin_unlock(&priv->lock); |
422 | } | 449 | } |
@@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn, | |||
445 | err = unmap_grant_pages(map, /* offset */ 0, map->count); | 472 | err = unmap_grant_pages(map, /* offset */ 0, map->count); |
446 | WARN_ON(err); | 473 | WARN_ON(err); |
447 | } | 474 | } |
475 | list_for_each_entry(map, &priv->freeable_maps, next) { | ||
476 | if (!map->vma) | ||
477 | continue; | ||
478 | pr_debug("map %d+%d (%lx %lx)\n", | ||
479 | map->index, map->count, | ||
480 | map->vma->vm_start, map->vma->vm_end); | ||
481 | err = unmap_grant_pages(map, /* offset */ 0, map->count); | ||
482 | WARN_ON(err); | ||
483 | } | ||
448 | spin_unlock(&priv->lock); | 484 | spin_unlock(&priv->lock); |
449 | } | 485 | } |
450 | 486 | ||
@@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) | |||
466 | return -ENOMEM; | 502 | return -ENOMEM; |
467 | 503 | ||
468 | INIT_LIST_HEAD(&priv->maps); | 504 | INIT_LIST_HEAD(&priv->maps); |
505 | INIT_LIST_HEAD(&priv->freeable_maps); | ||
469 | spin_lock_init(&priv->lock); | 506 | spin_lock_init(&priv->lock); |
470 | 507 | ||
471 | if (use_ptemod) { | 508 | if (use_ptemod) { |
@@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip) | |||
500 | while (!list_empty(&priv->maps)) { | 537 | while (!list_empty(&priv->maps)) { |
501 | map = list_entry(priv->maps.next, struct grant_map, next); | 538 | map = list_entry(priv->maps.next, struct grant_map, next); |
502 | list_del(&map->next); | 539 | list_del(&map->next); |
503 | gntdev_put_map(map); | 540 | gntdev_put_map(NULL /* already removed */, map); |
504 | } | 541 | } |
542 | WARN_ON(!list_empty(&priv->freeable_maps)); | ||
505 | 543 | ||
506 | if (use_ptemod) | 544 | if (use_ptemod) |
507 | mmu_notifier_unregister(&priv->mn, priv->mm); | 545 | mmu_notifier_unregister(&priv->mn, priv->mm); |
@@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, | |||
529 | 567 | ||
530 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { | 568 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { |
531 | pr_debug("can't map: over limit\n"); | 569 | pr_debug("can't map: over limit\n"); |
532 | gntdev_put_map(map); | 570 | gntdev_put_map(NULL, map); |
533 | return err; | 571 | return err; |
534 | } | 572 | } |
535 | 573 | ||
536 | if (copy_from_user(map->grants, &u->refs, | 574 | if (copy_from_user(map->grants, &u->refs, |
537 | sizeof(map->grants[0]) * op.count) != 0) { | 575 | sizeof(map->grants[0]) * op.count) != 0) { |
538 | gntdev_put_map(map); | 576 | gntdev_put_map(NULL, map); |
539 | return err; | 577 | return -EFAULT; |
540 | } | 578 | } |
541 | 579 | ||
542 | spin_lock(&priv->lock); | 580 | spin_lock(&priv->lock); |
@@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, | |||
565 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); | 603 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); |
566 | if (map) { | 604 | if (map) { |
567 | list_del(&map->next); | 605 | list_del(&map->next); |
606 | if (populate_freeable_maps) | ||
607 | list_add_tail(&map->next, &priv->freeable_maps); | ||
568 | err = 0; | 608 | err = 0; |
569 | } | 609 | } |
570 | spin_unlock(&priv->lock); | 610 | spin_unlock(&priv->lock); |
571 | if (map) | 611 | if (map) |
572 | gntdev_put_map(map); | 612 | gntdev_put_map(priv, map); |
573 | return err; | 613 | return err; |
574 | } | 614 | } |
575 | 615 | ||
@@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, | |||
579 | struct ioctl_gntdev_get_offset_for_vaddr op; | 619 | struct ioctl_gntdev_get_offset_for_vaddr op; |
580 | struct vm_area_struct *vma; | 620 | struct vm_area_struct *vma; |
581 | struct grant_map *map; | 621 | struct grant_map *map; |
622 | int rv = -EINVAL; | ||
582 | 623 | ||
583 | if (copy_from_user(&op, u, sizeof(op)) != 0) | 624 | if (copy_from_user(&op, u, sizeof(op)) != 0) |
584 | return -EFAULT; | 625 | return -EFAULT; |
585 | pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); | 626 | pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); |
586 | 627 | ||
628 | down_read(¤t->mm->mmap_sem); | ||
587 | vma = find_vma(current->mm, op.vaddr); | 629 | vma = find_vma(current->mm, op.vaddr); |
588 | if (!vma || vma->vm_ops != &gntdev_vmops) | 630 | if (!vma || vma->vm_ops != &gntdev_vmops) |
589 | return -EINVAL; | 631 | goto out_unlock; |
590 | 632 | ||
591 | map = vma->vm_private_data; | 633 | map = vma->vm_private_data; |
592 | if (!map) | 634 | if (!map) |
593 | return -EINVAL; | 635 | goto out_unlock; |
594 | 636 | ||
595 | op.offset = map->index << PAGE_SHIFT; | 637 | op.offset = map->index << PAGE_SHIFT; |
596 | op.count = map->count; | 638 | op.count = map->count; |
639 | rv = 0; | ||
597 | 640 | ||
598 | if (copy_to_user(u, &op, sizeof(op)) != 0) | 641 | out_unlock: |
642 | up_read(¤t->mm->mmap_sem); | ||
643 | |||
644 | if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0) | ||
599 | return -EFAULT; | 645 | return -EFAULT; |
600 | return 0; | 646 | return rv; |
601 | } | 647 | } |
602 | 648 | ||
603 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) | 649 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) |
@@ -778,7 +824,7 @@ out_unlock_put: | |||
778 | out_put_map: | 824 | out_put_map: |
779 | if (use_ptemod) | 825 | if (use_ptemod) |
780 | map->vma = NULL; | 826 | map->vma = NULL; |
781 | gntdev_put_map(map); | 827 | gntdev_put_map(priv, map); |
782 | return err; | 828 | return err; |
783 | } | 829 | } |
784 | 830 | ||
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7038de53652b..157c0ccda3ef 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -56,10 +56,6 @@ | |||
56 | /* External tools reserve first few grant table entries. */ | 56 | /* External tools reserve first few grant table entries. */ |
57 | #define NR_RESERVED_ENTRIES 8 | 57 | #define NR_RESERVED_ENTRIES 8 |
58 | #define GNTTAB_LIST_END 0xffffffff | 58 | #define GNTTAB_LIST_END 0xffffffff |
59 | #define GREFS_PER_GRANT_FRAME \ | ||
60 | (grant_table_version == 1 ? \ | ||
61 | (PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ | ||
62 | (PAGE_SIZE / sizeof(union grant_entry_v2))) | ||
63 | 59 | ||
64 | static grant_ref_t **gnttab_list; | 60 | static grant_ref_t **gnttab_list; |
65 | static unsigned int nr_grant_frames; | 61 | static unsigned int nr_grant_frames; |
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; | |||
154 | static grant_status_t *grstatus; | 150 | static grant_status_t *grstatus; |
155 | 151 | ||
156 | static int grant_table_version; | 152 | static int grant_table_version; |
153 | static int grefs_per_grant_frame; | ||
157 | 154 | ||
158 | static struct gnttab_free_callback *gnttab_free_callback_list; | 155 | static struct gnttab_free_callback *gnttab_free_callback_list; |
159 | 156 | ||
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
767 | unsigned int new_nr_grant_frames, extra_entries, i; | 764 | unsigned int new_nr_grant_frames, extra_entries, i; |
768 | unsigned int nr_glist_frames, new_nr_glist_frames; | 765 | unsigned int nr_glist_frames, new_nr_glist_frames; |
769 | 766 | ||
767 | BUG_ON(grefs_per_grant_frame == 0); | ||
768 | |||
770 | new_nr_grant_frames = nr_grant_frames + more_frames; | 769 | new_nr_grant_frames = nr_grant_frames + more_frames; |
771 | extra_entries = more_frames * GREFS_PER_GRANT_FRAME; | 770 | extra_entries = more_frames * grefs_per_grant_frame; |
772 | 771 | ||
773 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 772 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
774 | new_nr_glist_frames = | 773 | new_nr_glist_frames = |
775 | (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 774 | (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
776 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { | 775 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { |
777 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); | 776 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); |
778 | if (!gnttab_list[i]) | 777 | if (!gnttab_list[i]) |
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
780 | } | 779 | } |
781 | 780 | ||
782 | 781 | ||
783 | for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 782 | for (i = grefs_per_grant_frame * nr_grant_frames; |
784 | i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) | 783 | i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) |
785 | gnttab_entry(i) = i + 1; | 784 | gnttab_entry(i) = i + 1; |
786 | 785 | ||
787 | gnttab_entry(i) = gnttab_free_head; | 786 | gnttab_entry(i) = gnttab_free_head; |
788 | gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 787 | gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; |
789 | gnttab_free_count += extra_entries; | 788 | gnttab_free_count += extra_entries; |
790 | 789 | ||
791 | nr_grant_frames = new_nr_grant_frames; | 790 | nr_grant_frames = new_nr_grant_frames; |
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | |||
957 | 956 | ||
958 | static unsigned nr_status_frames(unsigned nr_grant_frames) | 957 | static unsigned nr_status_frames(unsigned nr_grant_frames) |
959 | { | 958 | { |
960 | return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; | 959 | BUG_ON(grefs_per_grant_frame == 0); |
960 | return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; | ||
961 | } | 961 | } |
962 | 962 | ||
963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) | 963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) |
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) | |||
1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); | 1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); |
1116 | if (rc == 0 && gsv.version == 2) { | 1116 | if (rc == 0 && gsv.version == 2) { |
1117 | grant_table_version = 2; | 1117 | grant_table_version = 2; |
1118 | grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); | ||
1118 | gnttab_interface = &gnttab_v2_ops; | 1119 | gnttab_interface = &gnttab_v2_ops; |
1119 | } else if (grant_table_version == 2) { | 1120 | } else if (grant_table_version == 2) { |
1120 | /* | 1121 | /* |
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) | |||
1127 | panic("we need grant tables version 2, but only version 1 is available"); | 1128 | panic("we need grant tables version 2, but only version 1 is available"); |
1128 | } else { | 1129 | } else { |
1129 | grant_table_version = 1; | 1130 | grant_table_version = 1; |
1131 | grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); | ||
1130 | gnttab_interface = &gnttab_v1_ops; | 1132 | gnttab_interface = &gnttab_v1_ops; |
1131 | } | 1133 | } |
1132 | printk(KERN_INFO "Grant tables using version %d layout.\n", | 1134 | printk(KERN_INFO "Grant tables using version %d layout.\n", |
1133 | grant_table_version); | 1135 | grant_table_version); |
1134 | } | 1136 | } |
1135 | 1137 | ||
1136 | int gnttab_resume(void) | 1138 | static int gnttab_setup(void) |
1137 | { | 1139 | { |
1138 | unsigned int max_nr_gframes; | 1140 | unsigned int max_nr_gframes; |
1139 | 1141 | ||
1140 | gnttab_request_version(); | ||
1141 | max_nr_gframes = gnttab_max_grant_frames(); | 1142 | max_nr_gframes = gnttab_max_grant_frames(); |
1142 | if (max_nr_gframes < nr_grant_frames) | 1143 | if (max_nr_gframes < nr_grant_frames) |
1143 | return -ENOSYS; | 1144 | return -ENOSYS; |
@@ -1160,6 +1161,12 @@ int gnttab_resume(void) | |||
1160 | return 0; | 1161 | return 0; |
1161 | } | 1162 | } |
1162 | 1163 | ||
1164 | int gnttab_resume(void) | ||
1165 | { | ||
1166 | gnttab_request_version(); | ||
1167 | return gnttab_setup(); | ||
1168 | } | ||
1169 | |||
1163 | int gnttab_suspend(void) | 1170 | int gnttab_suspend(void) |
1164 | { | 1171 | { |
1165 | gnttab_interface->unmap_frames(); | 1172 | gnttab_interface->unmap_frames(); |
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) | |||
1171 | int rc; | 1178 | int rc; |
1172 | unsigned int cur, extra; | 1179 | unsigned int cur, extra; |
1173 | 1180 | ||
1181 | BUG_ON(grefs_per_grant_frame == 0); | ||
1174 | cur = nr_grant_frames; | 1182 | cur = nr_grant_frames; |
1175 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 1183 | extra = ((req_entries + (grefs_per_grant_frame-1)) / |
1176 | GREFS_PER_GRANT_FRAME); | 1184 | grefs_per_grant_frame); |
1177 | if (cur + extra > gnttab_max_grant_frames()) | 1185 | if (cur + extra > gnttab_max_grant_frames()) |
1178 | return -ENOSPC; | 1186 | return -ENOSPC; |
1179 | 1187 | ||
@@ -1191,21 +1199,23 @@ int gnttab_init(void) | |||
1191 | unsigned int nr_init_grefs; | 1199 | unsigned int nr_init_grefs; |
1192 | int ret; | 1200 | int ret; |
1193 | 1201 | ||
1202 | gnttab_request_version(); | ||
1194 | nr_grant_frames = 1; | 1203 | nr_grant_frames = 1; |
1195 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 1204 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
1196 | 1205 | ||
1197 | /* Determine the maximum number of frames required for the | 1206 | /* Determine the maximum number of frames required for the |
1198 | * grant reference free list on the current hypervisor. | 1207 | * grant reference free list on the current hypervisor. |
1199 | */ | 1208 | */ |
1209 | BUG_ON(grefs_per_grant_frame == 0); | ||
1200 | max_nr_glist_frames = (boot_max_nr_grant_frames * | 1210 | max_nr_glist_frames = (boot_max_nr_grant_frames * |
1201 | GREFS_PER_GRANT_FRAME / RPP); | 1211 | grefs_per_grant_frame / RPP); |
1202 | 1212 | ||
1203 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), | 1213 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), |
1204 | GFP_KERNEL); | 1214 | GFP_KERNEL); |
1205 | if (gnttab_list == NULL) | 1215 | if (gnttab_list == NULL) |
1206 | return -ENOMEM; | 1216 | return -ENOMEM; |
1207 | 1217 | ||
1208 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 1218 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
1209 | for (i = 0; i < nr_glist_frames; i++) { | 1219 | for (i = 0; i < nr_glist_frames; i++) { |
1210 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); | 1220 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); |
1211 | if (gnttab_list[i] == NULL) { | 1221 | if (gnttab_list[i] == NULL) { |
@@ -1214,12 +1224,12 @@ int gnttab_init(void) | |||
1214 | } | 1224 | } |
1215 | } | 1225 | } |
1216 | 1226 | ||
1217 | if (gnttab_resume() < 0) { | 1227 | if (gnttab_setup() < 0) { |
1218 | ret = -ENODEV; | 1228 | ret = -ENODEV; |
1219 | goto ini_nomem; | 1229 | goto ini_nomem; |
1220 | } | 1230 | } |
1221 | 1231 | ||
1222 | nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; | 1232 | nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; |
1223 | 1233 | ||
1224 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) | 1234 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) |
1225 | gnttab_entry(i) = i + 1; | 1235 | gnttab_entry(i) = i + 1; |
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 0bbbccbb1f12..ca2b00e9d558 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata) | |||
199 | LIST_HEAD(pagelist); | 199 | LIST_HEAD(pagelist); |
200 | struct mmap_mfn_state state; | 200 | struct mmap_mfn_state state; |
201 | 201 | ||
202 | if (!xen_initial_domain()) | ||
203 | return -EPERM; | ||
204 | |||
205 | /* We only support privcmd_ioctl_mmap_batch for auto translated. */ | 202 | /* We only support privcmd_ioctl_mmap_batch for auto translated. */ |
206 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 203 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
207 | return -ENOSYS; | 204 | return -ENOSYS; |
@@ -261,11 +258,12 @@ struct mmap_batch_state { | |||
261 | * -ENOENT if at least 1 -ENOENT has happened. | 258 | * -ENOENT if at least 1 -ENOENT has happened. |
262 | */ | 259 | */ |
263 | int global_error; | 260 | int global_error; |
264 | /* An array for individual errors */ | 261 | int version; |
265 | int *err; | ||
266 | 262 | ||
267 | /* User-space mfn array to store errors in the second pass for V1. */ | 263 | /* User-space mfn array to store errors in the second pass for V1. */ |
268 | xen_pfn_t __user *user_mfn; | 264 | xen_pfn_t __user *user_mfn; |
265 | /* User-space int array to store errors in the second pass for V2. */ | ||
266 | int __user *user_err; | ||
269 | }; | 267 | }; |
270 | 268 | ||
271 | /* auto translated dom0 note: if domU being created is PV, then mfn is | 269 | /* auto translated dom0 note: if domU being created is PV, then mfn is |
@@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state) | |||
288 | &cur_page); | 286 | &cur_page); |
289 | 287 | ||
290 | /* Store error code for second pass. */ | 288 | /* Store error code for second pass. */ |
291 | *(st->err++) = ret; | 289 | if (st->version == 1) { |
290 | if (ret < 0) { | ||
291 | /* | ||
292 | * V1 encodes the error codes in the 32bit top nibble of the | ||
293 | * mfn (with its known limitations vis-a-vis 64 bit callers). | ||
294 | */ | ||
295 | *mfnp |= (ret == -ENOENT) ? | ||
296 | PRIVCMD_MMAPBATCH_PAGED_ERROR : | ||
297 | PRIVCMD_MMAPBATCH_MFN_ERROR; | ||
298 | } | ||
299 | } else { /* st->version == 2 */ | ||
300 | *((int *) mfnp) = ret; | ||
301 | } | ||
292 | 302 | ||
293 | /* And see if it affects the global_error. */ | 303 | /* And see if it affects the global_error. */ |
294 | if (ret < 0) { | 304 | if (ret < 0) { |
@@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state) | |||
305 | return 0; | 315 | return 0; |
306 | } | 316 | } |
307 | 317 | ||
308 | static int mmap_return_errors_v1(void *data, void *state) | 318 | static int mmap_return_errors(void *data, void *state) |
309 | { | 319 | { |
310 | xen_pfn_t *mfnp = data; | ||
311 | struct mmap_batch_state *st = state; | 320 | struct mmap_batch_state *st = state; |
312 | int err = *(st->err++); | ||
313 | 321 | ||
314 | /* | 322 | if (st->version == 1) { |
315 | * V1 encodes the error codes in the 32bit top nibble of the | 323 | xen_pfn_t mfnp = *((xen_pfn_t *) data); |
316 | * mfn (with its known limitations vis-a-vis 64 bit callers). | 324 | if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR) |
317 | */ | 325 | return __put_user(mfnp, st->user_mfn++); |
318 | *mfnp |= (err == -ENOENT) ? | 326 | else |
319 | PRIVCMD_MMAPBATCH_PAGED_ERROR : | 327 | st->user_mfn++; |
320 | PRIVCMD_MMAPBATCH_MFN_ERROR; | 328 | } else { /* st->version == 2 */ |
321 | return __put_user(*mfnp, st->user_mfn++); | 329 | int err = *((int *) data); |
330 | if (err) | ||
331 | return __put_user(err, st->user_err++); | ||
332 | else | ||
333 | st->user_err++; | ||
334 | } | ||
335 | |||
336 | return 0; | ||
322 | } | 337 | } |
323 | 338 | ||
324 | /* Allocate pfns that are then mapped with gmfns from foreign domid. Update | 339 | /* Allocate pfns that are then mapped with gmfns from foreign domid. Update |
@@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
357 | struct vm_area_struct *vma; | 372 | struct vm_area_struct *vma; |
358 | unsigned long nr_pages; | 373 | unsigned long nr_pages; |
359 | LIST_HEAD(pagelist); | 374 | LIST_HEAD(pagelist); |
360 | int *err_array = NULL; | ||
361 | struct mmap_batch_state state; | 375 | struct mmap_batch_state state; |
362 | 376 | ||
363 | if (!xen_initial_domain()) | ||
364 | return -EPERM; | ||
365 | |||
366 | switch (version) { | 377 | switch (version) { |
367 | case 1: | 378 | case 1: |
368 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) | 379 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) |
@@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
396 | goto out; | 407 | goto out; |
397 | } | 408 | } |
398 | 409 | ||
399 | err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); | 410 | if (version == 2) { |
400 | if (err_array == NULL) { | 411 | /* Zero error array now to only copy back actual errors. */ |
401 | ret = -ENOMEM; | 412 | if (clear_user(m.err, sizeof(int) * m.num)) { |
402 | goto out; | 413 | ret = -EFAULT; |
414 | goto out; | ||
415 | } | ||
403 | } | 416 | } |
404 | 417 | ||
405 | down_write(&mm->mmap_sem); | 418 | down_write(&mm->mmap_sem); |
@@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
427 | state.va = m.addr; | 440 | state.va = m.addr; |
428 | state.index = 0; | 441 | state.index = 0; |
429 | state.global_error = 0; | 442 | state.global_error = 0; |
430 | state.err = err_array; | 443 | state.version = version; |
431 | 444 | ||
432 | /* mmap_batch_fn guarantees ret == 0 */ | 445 | /* mmap_batch_fn guarantees ret == 0 */ |
433 | BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), | 446 | BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), |
@@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
435 | 448 | ||
436 | up_write(&mm->mmap_sem); | 449 | up_write(&mm->mmap_sem); |
437 | 450 | ||
438 | if (version == 1) { | 451 | if (state.global_error) { |
439 | if (state.global_error) { | 452 | /* Write back errors in second pass. */ |
440 | /* Write back errors in second pass. */ | 453 | state.user_mfn = (xen_pfn_t *)m.arr; |
441 | state.user_mfn = (xen_pfn_t *)m.arr; | 454 | state.user_err = m.err; |
442 | state.err = err_array; | 455 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), |
443 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), | 456 | &pagelist, mmap_return_errors, &state); |
444 | &pagelist, mmap_return_errors_v1, &state); | 457 | } else |
445 | } else | 458 | ret = 0; |
446 | ret = 0; | ||
447 | |||
448 | } else if (version == 2) { | ||
449 | ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); | ||
450 | if (ret) | ||
451 | ret = -EFAULT; | ||
452 | } | ||
453 | 459 | ||
454 | /* If we have not had any EFAULT-like global errors then set the global | 460 | /* If we have not had any EFAULT-like global errors then set the global |
455 | * error to -ENOENT if necessary. */ | 461 | * error to -ENOENT if necessary. */ |
@@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
457 | ret = -ENOENT; | 463 | ret = -ENOENT; |
458 | 464 | ||
459 | out: | 465 | out: |
460 | kfree(err_array); | ||
461 | free_page_list(&pagelist); | 466 | free_page_list(&pagelist); |
462 | 467 | ||
463 | return ret; | 468 | return ret; |
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index a7def010eba3..f72af87640e0 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h | |||
@@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, | |||
124 | static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, | 124 | static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, |
125 | struct pci_dev *dev) | 125 | struct pci_dev *dev) |
126 | { | 126 | { |
127 | if (xen_pcibk_backend && xen_pcibk_backend->free) | 127 | if (xen_pcibk_backend && xen_pcibk_backend->release) |
128 | return xen_pcibk_backend->release(pdev, dev); | 128 | return xen_pcibk_backend->release(pdev, dev); |
129 | } | 129 | } |
130 | 130 | ||
diff --git a/fs/Kconfig b/fs/Kconfig index cfe512fd1caf..780725a463b1 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -68,16 +68,6 @@ source "fs/quota/Kconfig" | |||
68 | source "fs/autofs4/Kconfig" | 68 | source "fs/autofs4/Kconfig" |
69 | source "fs/fuse/Kconfig" | 69 | source "fs/fuse/Kconfig" |
70 | 70 | ||
71 | config CUSE | ||
72 | tristate "Character device in Userspace support" | ||
73 | depends on FUSE_FS | ||
74 | help | ||
75 | This FUSE extension allows character devices to be | ||
76 | implemented in userspace. | ||
77 | |||
78 | If you want to develop or use userspace character device | ||
79 | based on CUSE, answer Y or M. | ||
80 | |||
81 | config GENERIC_ACL | 71 | config GENERIC_ACL |
82 | bool | 72 | bool |
83 | select FS_POSIX_ACL | 73 | select FS_POSIX_ACL |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 521e9d4424f6..a8b8adc05070 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3997,7 +3997,7 @@ again: | |||
3997 | * We make the other tasks wait for the flush only when we can flush | 3997 | * We make the other tasks wait for the flush only when we can flush |
3998 | * all things. | 3998 | * all things. |
3999 | */ | 3999 | */ |
4000 | if (ret && flush == BTRFS_RESERVE_FLUSH_ALL) { | 4000 | if (ret && flush != BTRFS_RESERVE_NO_FLUSH) { |
4001 | flushing = true; | 4001 | flushing = true; |
4002 | space_info->flush = 1; | 4002 | space_info->flush = 1; |
4003 | } | 4003 | } |
@@ -5560,7 +5560,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
5560 | int empty_cluster = 2 * 1024 * 1024; | 5560 | int empty_cluster = 2 * 1024 * 1024; |
5561 | struct btrfs_space_info *space_info; | 5561 | struct btrfs_space_info *space_info; |
5562 | int loop = 0; | 5562 | int loop = 0; |
5563 | int index = 0; | 5563 | int index = __get_raid_index(data); |
5564 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? | 5564 | int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ? |
5565 | RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC; | 5565 | RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC; |
5566 | bool found_uncached_bg = false; | 5566 | bool found_uncached_bg = false; |
@@ -6788,11 +6788,13 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans, | |||
6788 | &wc->flags[level]); | 6788 | &wc->flags[level]); |
6789 | if (ret < 0) { | 6789 | if (ret < 0) { |
6790 | btrfs_tree_unlock_rw(eb, path->locks[level]); | 6790 | btrfs_tree_unlock_rw(eb, path->locks[level]); |
6791 | path->locks[level] = 0; | ||
6791 | return ret; | 6792 | return ret; |
6792 | } | 6793 | } |
6793 | BUG_ON(wc->refs[level] == 0); | 6794 | BUG_ON(wc->refs[level] == 0); |
6794 | if (wc->refs[level] == 1) { | 6795 | if (wc->refs[level] == 1) { |
6795 | btrfs_tree_unlock_rw(eb, path->locks[level]); | 6796 | btrfs_tree_unlock_rw(eb, path->locks[level]); |
6797 | path->locks[level] = 0; | ||
6796 | return 1; | 6798 | return 1; |
6797 | } | 6799 | } |
6798 | } | 6800 | } |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index f169d6b11d7f..2e8cae63d247 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -171,6 +171,10 @@ static int mergable_maps(struct extent_map *prev, struct extent_map *next) | |||
171 | if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags)) | 171 | if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags)) |
172 | return 0; | 172 | return 0; |
173 | 173 | ||
174 | if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) || | ||
175 | test_bit(EXTENT_FLAG_LOGGING, &next->flags)) | ||
176 | return 0; | ||
177 | |||
174 | if (extent_map_end(prev) == next->start && | 178 | if (extent_map_end(prev) == next->start && |
175 | prev->flags == next->flags && | 179 | prev->flags == next->flags && |
176 | prev->bdev == next->bdev && | 180 | prev->bdev == next->bdev && |
@@ -255,7 +259,8 @@ int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, | |||
255 | if (!em) | 259 | if (!em) |
256 | goto out; | 260 | goto out; |
257 | 261 | ||
258 | list_move(&em->list, &tree->modified_extents); | 262 | if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags)) |
263 | list_move(&em->list, &tree->modified_extents); | ||
259 | em->generation = gen; | 264 | em->generation = gen; |
260 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | 265 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); |
261 | em->mod_start = em->start; | 266 | em->mod_start = em->start; |
@@ -280,6 +285,12 @@ out: | |||
280 | 285 | ||
281 | } | 286 | } |
282 | 287 | ||
288 | void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em) | ||
289 | { | ||
290 | clear_bit(EXTENT_FLAG_LOGGING, &em->flags); | ||
291 | try_merge_map(tree, em); | ||
292 | } | ||
293 | |||
283 | /** | 294 | /** |
284 | * add_extent_mapping - add new extent map to the extent tree | 295 | * add_extent_mapping - add new extent map to the extent tree |
285 | * @tree: tree to insert new map in | 296 | * @tree: tree to insert new map in |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index 922943ce29e8..c6598c89cff8 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -69,6 +69,7 @@ void free_extent_map(struct extent_map *em); | |||
69 | int __init extent_map_init(void); | 69 | int __init extent_map_init(void); |
70 | void extent_map_exit(void); | 70 | void extent_map_exit(void); |
71 | int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen); | 71 | int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen); |
72 | void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em); | ||
72 | struct extent_map *search_extent_mapping(struct extent_map_tree *tree, | 73 | struct extent_map *search_extent_mapping(struct extent_map_tree *tree, |
73 | u64 start, u64 len); | 74 | u64 start, u64 len); |
74 | #endif | 75 | #endif |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index bd38cef42358..94aa53b38721 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -460,8 +460,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
460 | if (!contig) | 460 | if (!contig) |
461 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 461 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
462 | 462 | ||
463 | if (!contig && (offset >= ordered->file_offset + ordered->len || | 463 | if (offset >= ordered->file_offset + ordered->len || |
464 | offset < ordered->file_offset)) { | 464 | offset < ordered->file_offset) { |
465 | unsigned long bytes_left; | 465 | unsigned long bytes_left; |
466 | sums->len = this_sum_bytes; | 466 | sums->len = this_sum_bytes; |
467 | this_sum_bytes = 0; | 467 | this_sum_bytes = 0; |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 77061bf43edb..f76b1fd160d4 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -2241,6 +2241,7 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) | |||
2241 | if (lockend <= lockstart) | 2241 | if (lockend <= lockstart) |
2242 | lockend = lockstart + root->sectorsize; | 2242 | lockend = lockstart + root->sectorsize; |
2243 | 2243 | ||
2244 | lockend--; | ||
2244 | len = lockend - lockstart + 1; | 2245 | len = lockend - lockstart + 1; |
2245 | 2246 | ||
2246 | len = max_t(u64, len, root->sectorsize); | 2247 | len = max_t(u64, len, root->sectorsize); |
@@ -2307,9 +2308,12 @@ static int find_desired_extent(struct inode *inode, loff_t *offset, int whence) | |||
2307 | } | 2308 | } |
2308 | } | 2309 | } |
2309 | 2310 | ||
2310 | *offset = start; | 2311 | if (!test_bit(EXTENT_FLAG_PREALLOC, |
2311 | free_extent_map(em); | 2312 | &em->flags)) { |
2312 | break; | 2313 | *offset = start; |
2314 | free_extent_map(em); | ||
2315 | break; | ||
2316 | } | ||
2313 | } | 2317 | } |
2314 | } | 2318 | } |
2315 | 2319 | ||
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 59ea2e4349c9..0be7a8742a43 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -1862,11 +1862,13 @@ int btrfs_remove_free_space(struct btrfs_block_group_cache *block_group, | |||
1862 | { | 1862 | { |
1863 | struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; | 1863 | struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl; |
1864 | struct btrfs_free_space *info; | 1864 | struct btrfs_free_space *info; |
1865 | int ret = 0; | 1865 | int ret; |
1866 | bool re_search = false; | ||
1866 | 1867 | ||
1867 | spin_lock(&ctl->tree_lock); | 1868 | spin_lock(&ctl->tree_lock); |
1868 | 1869 | ||
1869 | again: | 1870 | again: |
1871 | ret = 0; | ||
1870 | if (!bytes) | 1872 | if (!bytes) |
1871 | goto out_lock; | 1873 | goto out_lock; |
1872 | 1874 | ||
@@ -1879,17 +1881,17 @@ again: | |||
1879 | info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), | 1881 | info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), |
1880 | 1, 0); | 1882 | 1, 0); |
1881 | if (!info) { | 1883 | if (!info) { |
1882 | /* the tree logging code might be calling us before we | 1884 | /* |
1883 | * have fully loaded the free space rbtree for this | 1885 | * If we found a partial bit of our free space in a |
1884 | * block group. So it is possible the entry won't | 1886 | * bitmap but then couldn't find the other part this may |
1885 | * be in the rbtree yet at all. The caching code | 1887 | * be a problem, so WARN about it. |
1886 | * will make sure not to put it in the rbtree if | ||
1887 | * the logging code has pinned it. | ||
1888 | */ | 1888 | */ |
1889 | WARN_ON(re_search); | ||
1889 | goto out_lock; | 1890 | goto out_lock; |
1890 | } | 1891 | } |
1891 | } | 1892 | } |
1892 | 1893 | ||
1894 | re_search = false; | ||
1893 | if (!info->bitmap) { | 1895 | if (!info->bitmap) { |
1894 | unlink_free_space(ctl, info); | 1896 | unlink_free_space(ctl, info); |
1895 | if (offset == info->offset) { | 1897 | if (offset == info->offset) { |
@@ -1935,8 +1937,10 @@ again: | |||
1935 | } | 1937 | } |
1936 | 1938 | ||
1937 | ret = remove_from_bitmap(ctl, info, &offset, &bytes); | 1939 | ret = remove_from_bitmap(ctl, info, &offset, &bytes); |
1938 | if (ret == -EAGAIN) | 1940 | if (ret == -EAGAIN) { |
1941 | re_search = true; | ||
1939 | goto again; | 1942 | goto again; |
1943 | } | ||
1940 | BUG_ON(ret); /* logic error */ | 1944 | BUG_ON(ret); /* logic error */ |
1941 | out_lock: | 1945 | out_lock: |
1942 | spin_unlock(&ctl->tree_lock); | 1946 | spin_unlock(&ctl->tree_lock); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 16d9e8e191e6..cc93b23ca352 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -88,7 +88,7 @@ static unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = { | |||
88 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, | 88 | [S_IFLNK >> S_SHIFT] = BTRFS_FT_SYMLINK, |
89 | }; | 89 | }; |
90 | 90 | ||
91 | static int btrfs_setsize(struct inode *inode, loff_t newsize); | 91 | static int btrfs_setsize(struct inode *inode, struct iattr *attr); |
92 | static int btrfs_truncate(struct inode *inode); | 92 | static int btrfs_truncate(struct inode *inode); |
93 | static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent); | 93 | static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent); |
94 | static noinline int cow_file_range(struct inode *inode, | 94 | static noinline int cow_file_range(struct inode *inode, |
@@ -2478,6 +2478,18 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2478 | continue; | 2478 | continue; |
2479 | } | 2479 | } |
2480 | nr_truncate++; | 2480 | nr_truncate++; |
2481 | |||
2482 | /* 1 for the orphan item deletion. */ | ||
2483 | trans = btrfs_start_transaction(root, 1); | ||
2484 | if (IS_ERR(trans)) { | ||
2485 | ret = PTR_ERR(trans); | ||
2486 | goto out; | ||
2487 | } | ||
2488 | ret = btrfs_orphan_add(trans, inode); | ||
2489 | btrfs_end_transaction(trans, root); | ||
2490 | if (ret) | ||
2491 | goto out; | ||
2492 | |||
2481 | ret = btrfs_truncate(inode); | 2493 | ret = btrfs_truncate(inode); |
2482 | } else { | 2494 | } else { |
2483 | nr_unlink++; | 2495 | nr_unlink++; |
@@ -3665,6 +3677,7 @@ int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size) | |||
3665 | block_end - cur_offset, 0); | 3677 | block_end - cur_offset, 0); |
3666 | if (IS_ERR(em)) { | 3678 | if (IS_ERR(em)) { |
3667 | err = PTR_ERR(em); | 3679 | err = PTR_ERR(em); |
3680 | em = NULL; | ||
3668 | break; | 3681 | break; |
3669 | } | 3682 | } |
3670 | last_byte = min(extent_map_end(em), block_end); | 3683 | last_byte = min(extent_map_end(em), block_end); |
@@ -3748,16 +3761,27 @@ next: | |||
3748 | return err; | 3761 | return err; |
3749 | } | 3762 | } |
3750 | 3763 | ||
3751 | static int btrfs_setsize(struct inode *inode, loff_t newsize) | 3764 | static int btrfs_setsize(struct inode *inode, struct iattr *attr) |
3752 | { | 3765 | { |
3753 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3766 | struct btrfs_root *root = BTRFS_I(inode)->root; |
3754 | struct btrfs_trans_handle *trans; | 3767 | struct btrfs_trans_handle *trans; |
3755 | loff_t oldsize = i_size_read(inode); | 3768 | loff_t oldsize = i_size_read(inode); |
3769 | loff_t newsize = attr->ia_size; | ||
3770 | int mask = attr->ia_valid; | ||
3756 | int ret; | 3771 | int ret; |
3757 | 3772 | ||
3758 | if (newsize == oldsize) | 3773 | if (newsize == oldsize) |
3759 | return 0; | 3774 | return 0; |
3760 | 3775 | ||
3776 | /* | ||
3777 | * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a | ||
3778 | * special case where we need to update the times despite not having | ||
3779 | * these flags set. For all other operations the VFS set these flags | ||
3780 | * explicitly if it wants a timestamp update. | ||
3781 | */ | ||
3782 | if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME)))) | ||
3783 | inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); | ||
3784 | |||
3761 | if (newsize > oldsize) { | 3785 | if (newsize > oldsize) { |
3762 | truncate_pagecache(inode, oldsize, newsize); | 3786 | truncate_pagecache(inode, oldsize, newsize); |
3763 | ret = btrfs_cont_expand(inode, oldsize, newsize); | 3787 | ret = btrfs_cont_expand(inode, oldsize, newsize); |
@@ -3783,9 +3807,34 @@ static int btrfs_setsize(struct inode *inode, loff_t newsize) | |||
3783 | set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, | 3807 | set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE, |
3784 | &BTRFS_I(inode)->runtime_flags); | 3808 | &BTRFS_I(inode)->runtime_flags); |
3785 | 3809 | ||
3810 | /* | ||
3811 | * 1 for the orphan item we're going to add | ||
3812 | * 1 for the orphan item deletion. | ||
3813 | */ | ||
3814 | trans = btrfs_start_transaction(root, 2); | ||
3815 | if (IS_ERR(trans)) | ||
3816 | return PTR_ERR(trans); | ||
3817 | |||
3818 | /* | ||
3819 | * We need to do this in case we fail at _any_ point during the | ||
3820 | * actual truncate. Once we do the truncate_setsize we could | ||
3821 | * invalidate pages which forces any outstanding ordered io to | ||
3822 | * be instantly completed which will give us extents that need | ||
3823 | * to be truncated. If we fail to get an orphan inode down we | ||
3824 | * could have left over extents that were never meant to live, | ||
3825 | * so we need to garuntee from this point on that everything | ||
3826 | * will be consistent. | ||
3827 | */ | ||
3828 | ret = btrfs_orphan_add(trans, inode); | ||
3829 | btrfs_end_transaction(trans, root); | ||
3830 | if (ret) | ||
3831 | return ret; | ||
3832 | |||
3786 | /* we don't support swapfiles, so vmtruncate shouldn't fail */ | 3833 | /* we don't support swapfiles, so vmtruncate shouldn't fail */ |
3787 | truncate_setsize(inode, newsize); | 3834 | truncate_setsize(inode, newsize); |
3788 | ret = btrfs_truncate(inode); | 3835 | ret = btrfs_truncate(inode); |
3836 | if (ret && inode->i_nlink) | ||
3837 | btrfs_orphan_del(NULL, inode); | ||
3789 | } | 3838 | } |
3790 | 3839 | ||
3791 | return ret; | 3840 | return ret; |
@@ -3805,7 +3854,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
3805 | return err; | 3854 | return err; |
3806 | 3855 | ||
3807 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { | 3856 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { |
3808 | err = btrfs_setsize(inode, attr->ia_size); | 3857 | err = btrfs_setsize(inode, attr); |
3809 | if (err) | 3858 | if (err) |
3810 | return err; | 3859 | return err; |
3811 | } | 3860 | } |
@@ -5572,10 +5621,13 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag | |||
5572 | return em; | 5621 | return em; |
5573 | if (em) { | 5622 | if (em) { |
5574 | /* | 5623 | /* |
5575 | * if our em maps to a hole, there might | 5624 | * if our em maps to |
5576 | * actually be delalloc bytes behind it | 5625 | * - a hole or |
5626 | * - a pre-alloc extent, | ||
5627 | * there might actually be delalloc bytes behind it. | ||
5577 | */ | 5628 | */ |
5578 | if (em->block_start != EXTENT_MAP_HOLE) | 5629 | if (em->block_start != EXTENT_MAP_HOLE && |
5630 | !test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) | ||
5579 | return em; | 5631 | return em; |
5580 | else | 5632 | else |
5581 | hole_em = em; | 5633 | hole_em = em; |
@@ -5657,6 +5709,8 @@ struct extent_map *btrfs_get_extent_fiemap(struct inode *inode, struct page *pag | |||
5657 | */ | 5709 | */ |
5658 | em->block_start = hole_em->block_start; | 5710 | em->block_start = hole_em->block_start; |
5659 | em->block_len = hole_len; | 5711 | em->block_len = hole_len; |
5712 | if (test_bit(EXTENT_FLAG_PREALLOC, &hole_em->flags)) | ||
5713 | set_bit(EXTENT_FLAG_PREALLOC, &em->flags); | ||
5660 | } else { | 5714 | } else { |
5661 | em->start = range_start; | 5715 | em->start = range_start; |
5662 | em->len = found; | 5716 | em->len = found; |
@@ -6915,11 +6969,9 @@ static int btrfs_truncate(struct inode *inode) | |||
6915 | 6969 | ||
6916 | /* | 6970 | /* |
6917 | * 1 for the truncate slack space | 6971 | * 1 for the truncate slack space |
6918 | * 1 for the orphan item we're going to add | ||
6919 | * 1 for the orphan item deletion | ||
6920 | * 1 for updating the inode. | 6972 | * 1 for updating the inode. |
6921 | */ | 6973 | */ |
6922 | trans = btrfs_start_transaction(root, 4); | 6974 | trans = btrfs_start_transaction(root, 2); |
6923 | if (IS_ERR(trans)) { | 6975 | if (IS_ERR(trans)) { |
6924 | err = PTR_ERR(trans); | 6976 | err = PTR_ERR(trans); |
6925 | goto out; | 6977 | goto out; |
@@ -6930,12 +6982,6 @@ static int btrfs_truncate(struct inode *inode) | |||
6930 | min_size); | 6982 | min_size); |
6931 | BUG_ON(ret); | 6983 | BUG_ON(ret); |
6932 | 6984 | ||
6933 | ret = btrfs_orphan_add(trans, inode); | ||
6934 | if (ret) { | ||
6935 | btrfs_end_transaction(trans, root); | ||
6936 | goto out; | ||
6937 | } | ||
6938 | |||
6939 | /* | 6985 | /* |
6940 | * setattr is responsible for setting the ordered_data_close flag, | 6986 | * setattr is responsible for setting the ordered_data_close flag, |
6941 | * but that is only tested during the last file release. That | 6987 | * but that is only tested during the last file release. That |
@@ -7004,12 +7050,6 @@ static int btrfs_truncate(struct inode *inode) | |||
7004 | ret = btrfs_orphan_del(trans, inode); | 7050 | ret = btrfs_orphan_del(trans, inode); |
7005 | if (ret) | 7051 | if (ret) |
7006 | err = ret; | 7052 | err = ret; |
7007 | } else if (ret && inode->i_nlink > 0) { | ||
7008 | /* | ||
7009 | * Failed to do the truncate, remove us from the in memory | ||
7010 | * orphan list. | ||
7011 | */ | ||
7012 | ret = btrfs_orphan_del(NULL, inode); | ||
7013 | } | 7053 | } |
7014 | 7054 | ||
7015 | if (trans) { | 7055 | if (trans) { |
@@ -7531,41 +7571,61 @@ void btrfs_wait_and_free_delalloc_work(struct btrfs_delalloc_work *work) | |||
7531 | */ | 7571 | */ |
7532 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | 7572 | int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) |
7533 | { | 7573 | { |
7534 | struct list_head *head = &root->fs_info->delalloc_inodes; | ||
7535 | struct btrfs_inode *binode; | 7574 | struct btrfs_inode *binode; |
7536 | struct inode *inode; | 7575 | struct inode *inode; |
7537 | struct btrfs_delalloc_work *work, *next; | 7576 | struct btrfs_delalloc_work *work, *next; |
7538 | struct list_head works; | 7577 | struct list_head works; |
7578 | struct list_head splice; | ||
7539 | int ret = 0; | 7579 | int ret = 0; |
7540 | 7580 | ||
7541 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 7581 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
7542 | return -EROFS; | 7582 | return -EROFS; |
7543 | 7583 | ||
7544 | INIT_LIST_HEAD(&works); | 7584 | INIT_LIST_HEAD(&works); |
7545 | 7585 | INIT_LIST_HEAD(&splice); | |
7586 | again: | ||
7546 | spin_lock(&root->fs_info->delalloc_lock); | 7587 | spin_lock(&root->fs_info->delalloc_lock); |
7547 | while (!list_empty(head)) { | 7588 | list_splice_init(&root->fs_info->delalloc_inodes, &splice); |
7548 | binode = list_entry(head->next, struct btrfs_inode, | 7589 | while (!list_empty(&splice)) { |
7590 | binode = list_entry(splice.next, struct btrfs_inode, | ||
7549 | delalloc_inodes); | 7591 | delalloc_inodes); |
7592 | |||
7593 | list_del_init(&binode->delalloc_inodes); | ||
7594 | |||
7550 | inode = igrab(&binode->vfs_inode); | 7595 | inode = igrab(&binode->vfs_inode); |
7551 | if (!inode) | 7596 | if (!inode) |
7552 | list_del_init(&binode->delalloc_inodes); | 7597 | continue; |
7598 | |||
7599 | list_add_tail(&binode->delalloc_inodes, | ||
7600 | &root->fs_info->delalloc_inodes); | ||
7553 | spin_unlock(&root->fs_info->delalloc_lock); | 7601 | spin_unlock(&root->fs_info->delalloc_lock); |
7554 | if (inode) { | 7602 | |
7555 | work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); | 7603 | work = btrfs_alloc_delalloc_work(inode, 0, delay_iput); |
7556 | if (!work) { | 7604 | if (unlikely(!work)) { |
7557 | ret = -ENOMEM; | 7605 | ret = -ENOMEM; |
7558 | goto out; | 7606 | goto out; |
7559 | } | ||
7560 | list_add_tail(&work->list, &works); | ||
7561 | btrfs_queue_worker(&root->fs_info->flush_workers, | ||
7562 | &work->work); | ||
7563 | } | 7607 | } |
7608 | list_add_tail(&work->list, &works); | ||
7609 | btrfs_queue_worker(&root->fs_info->flush_workers, | ||
7610 | &work->work); | ||
7611 | |||
7564 | cond_resched(); | 7612 | cond_resched(); |
7565 | spin_lock(&root->fs_info->delalloc_lock); | 7613 | spin_lock(&root->fs_info->delalloc_lock); |
7566 | } | 7614 | } |
7567 | spin_unlock(&root->fs_info->delalloc_lock); | 7615 | spin_unlock(&root->fs_info->delalloc_lock); |
7568 | 7616 | ||
7617 | list_for_each_entry_safe(work, next, &works, list) { | ||
7618 | list_del_init(&work->list); | ||
7619 | btrfs_wait_and_free_delalloc_work(work); | ||
7620 | } | ||
7621 | |||
7622 | spin_lock(&root->fs_info->delalloc_lock); | ||
7623 | if (!list_empty(&root->fs_info->delalloc_inodes)) { | ||
7624 | spin_unlock(&root->fs_info->delalloc_lock); | ||
7625 | goto again; | ||
7626 | } | ||
7627 | spin_unlock(&root->fs_info->delalloc_lock); | ||
7628 | |||
7569 | /* the filemap_flush will queue IO into the worker threads, but | 7629 | /* the filemap_flush will queue IO into the worker threads, but |
7570 | * we have to make sure the IO is actually started and that | 7630 | * we have to make sure the IO is actually started and that |
7571 | * ordered extents get created before we return | 7631 | * ordered extents get created before we return |
@@ -7578,11 +7638,18 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput) | |||
7578 | atomic_read(&root->fs_info->async_delalloc_pages) == 0)); | 7638 | atomic_read(&root->fs_info->async_delalloc_pages) == 0)); |
7579 | } | 7639 | } |
7580 | atomic_dec(&root->fs_info->async_submit_draining); | 7640 | atomic_dec(&root->fs_info->async_submit_draining); |
7641 | return 0; | ||
7581 | out: | 7642 | out: |
7582 | list_for_each_entry_safe(work, next, &works, list) { | 7643 | list_for_each_entry_safe(work, next, &works, list) { |
7583 | list_del_init(&work->list); | 7644 | list_del_init(&work->list); |
7584 | btrfs_wait_and_free_delalloc_work(work); | 7645 | btrfs_wait_and_free_delalloc_work(work); |
7585 | } | 7646 | } |
7647 | |||
7648 | if (!list_empty_careful(&splice)) { | ||
7649 | spin_lock(&root->fs_info->delalloc_lock); | ||
7650 | list_splice_tail(&splice, &root->fs_info->delalloc_inodes); | ||
7651 | spin_unlock(&root->fs_info->delalloc_lock); | ||
7652 | } | ||
7586 | return ret; | 7653 | return ret; |
7587 | } | 7654 | } |
7588 | 7655 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4b4516770f05..5b22d45d3c6a 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1339,7 +1339,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1339 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 1339 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
1340 | 1)) { | 1340 | 1)) { |
1341 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 1341 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
1342 | return -EINPROGRESS; | 1342 | mnt_drop_write_file(file); |
1343 | return -EINVAL; | ||
1343 | } | 1344 | } |
1344 | 1345 | ||
1345 | mutex_lock(&root->fs_info->volume_mutex); | 1346 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -1362,6 +1363,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1362 | printk(KERN_INFO "btrfs: resizing devid %llu\n", | 1363 | printk(KERN_INFO "btrfs: resizing devid %llu\n", |
1363 | (unsigned long long)devid); | 1364 | (unsigned long long)devid); |
1364 | } | 1365 | } |
1366 | |||
1365 | device = btrfs_find_device(root->fs_info, devid, NULL, NULL); | 1367 | device = btrfs_find_device(root->fs_info, devid, NULL, NULL); |
1366 | if (!device) { | 1368 | if (!device) { |
1367 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", | 1369 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", |
@@ -1369,9 +1371,10 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1369 | ret = -EINVAL; | 1371 | ret = -EINVAL; |
1370 | goto out_free; | 1372 | goto out_free; |
1371 | } | 1373 | } |
1372 | if (device->fs_devices && device->fs_devices->seeding) { | 1374 | |
1375 | if (!device->writeable) { | ||
1373 | printk(KERN_INFO "btrfs: resizer unable to apply on " | 1376 | printk(KERN_INFO "btrfs: resizer unable to apply on " |
1374 | "seeding device %llu\n", | 1377 | "readonly device %llu\n", |
1375 | (unsigned long long)devid); | 1378 | (unsigned long long)devid); |
1376 | ret = -EINVAL; | 1379 | ret = -EINVAL; |
1377 | goto out_free; | 1380 | goto out_free; |
@@ -1443,8 +1446,8 @@ out_free: | |||
1443 | kfree(vol_args); | 1446 | kfree(vol_args); |
1444 | out: | 1447 | out: |
1445 | mutex_unlock(&root->fs_info->volume_mutex); | 1448 | mutex_unlock(&root->fs_info->volume_mutex); |
1446 | mnt_drop_write_file(file); | ||
1447 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 1449 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
1450 | mnt_drop_write_file(file); | ||
1448 | return ret; | 1451 | return ret; |
1449 | } | 1452 | } |
1450 | 1453 | ||
@@ -2095,13 +2098,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2095 | err = inode_permission(inode, MAY_WRITE | MAY_EXEC); | 2098 | err = inode_permission(inode, MAY_WRITE | MAY_EXEC); |
2096 | if (err) | 2099 | if (err) |
2097 | goto out_dput; | 2100 | goto out_dput; |
2098 | |||
2099 | /* check if subvolume may be deleted by a non-root user */ | ||
2100 | err = btrfs_may_delete(dir, dentry, 1); | ||
2101 | if (err) | ||
2102 | goto out_dput; | ||
2103 | } | 2101 | } |
2104 | 2102 | ||
2103 | /* check if subvolume may be deleted by a user */ | ||
2104 | err = btrfs_may_delete(dir, dentry, 1); | ||
2105 | if (err) | ||
2106 | goto out_dput; | ||
2107 | |||
2105 | if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { | 2108 | if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { |
2106 | err = -EINVAL; | 2109 | err = -EINVAL; |
2107 | goto out_dput; | 2110 | goto out_dput; |
@@ -2183,19 +2186,20 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2183 | struct btrfs_ioctl_defrag_range_args *range; | 2186 | struct btrfs_ioctl_defrag_range_args *range; |
2184 | int ret; | 2187 | int ret; |
2185 | 2188 | ||
2186 | if (btrfs_root_readonly(root)) | 2189 | ret = mnt_want_write_file(file); |
2187 | return -EROFS; | 2190 | if (ret) |
2191 | return ret; | ||
2188 | 2192 | ||
2189 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 2193 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2190 | 1)) { | 2194 | 1)) { |
2191 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 2195 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2192 | return -EINPROGRESS; | 2196 | mnt_drop_write_file(file); |
2197 | return -EINVAL; | ||
2193 | } | 2198 | } |
2194 | ret = mnt_want_write_file(file); | 2199 | |
2195 | if (ret) { | 2200 | if (btrfs_root_readonly(root)) { |
2196 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | 2201 | ret = -EROFS; |
2197 | 0); | 2202 | goto out; |
2198 | return ret; | ||
2199 | } | 2203 | } |
2200 | 2204 | ||
2201 | switch (inode->i_mode & S_IFMT) { | 2205 | switch (inode->i_mode & S_IFMT) { |
@@ -2247,8 +2251,8 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2247 | ret = -EINVAL; | 2251 | ret = -EINVAL; |
2248 | } | 2252 | } |
2249 | out: | 2253 | out: |
2250 | mnt_drop_write_file(file); | ||
2251 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 2254 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
2255 | mnt_drop_write_file(file); | ||
2252 | return ret; | 2256 | return ret; |
2253 | } | 2257 | } |
2254 | 2258 | ||
@@ -2263,7 +2267,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
2263 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 2267 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2264 | 1)) { | 2268 | 1)) { |
2265 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 2269 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2266 | return -EINPROGRESS; | 2270 | return -EINVAL; |
2267 | } | 2271 | } |
2268 | 2272 | ||
2269 | mutex_lock(&root->fs_info->volume_mutex); | 2273 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -2300,7 +2304,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2300 | 1)) { | 2304 | 1)) { |
2301 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 2305 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2302 | mnt_drop_write_file(file); | 2306 | mnt_drop_write_file(file); |
2303 | return -EINPROGRESS; | 2307 | return -EINVAL; |
2304 | } | 2308 | } |
2305 | 2309 | ||
2306 | mutex_lock(&root->fs_info->volume_mutex); | 2310 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -2316,8 +2320,8 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2316 | kfree(vol_args); | 2320 | kfree(vol_args); |
2317 | out: | 2321 | out: |
2318 | mutex_unlock(&root->fs_info->volume_mutex); | 2322 | mutex_unlock(&root->fs_info->volume_mutex); |
2319 | mnt_drop_write_file(file); | ||
2320 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 2323 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
2324 | mnt_drop_write_file(file); | ||
2321 | return ret; | 2325 | return ret; |
2322 | } | 2326 | } |
2323 | 2327 | ||
@@ -3437,8 +3441,8 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3437 | struct btrfs_fs_info *fs_info = root->fs_info; | 3441 | struct btrfs_fs_info *fs_info = root->fs_info; |
3438 | struct btrfs_ioctl_balance_args *bargs; | 3442 | struct btrfs_ioctl_balance_args *bargs; |
3439 | struct btrfs_balance_control *bctl; | 3443 | struct btrfs_balance_control *bctl; |
3444 | bool need_unlock; /* for mut. excl. ops lock */ | ||
3440 | int ret; | 3445 | int ret; |
3441 | int need_to_clear_lock = 0; | ||
3442 | 3446 | ||
3443 | if (!capable(CAP_SYS_ADMIN)) | 3447 | if (!capable(CAP_SYS_ADMIN)) |
3444 | return -EPERM; | 3448 | return -EPERM; |
@@ -3447,14 +3451,61 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3447 | if (ret) | 3451 | if (ret) |
3448 | return ret; | 3452 | return ret; |
3449 | 3453 | ||
3450 | mutex_lock(&fs_info->volume_mutex); | 3454 | again: |
3455 | if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { | ||
3456 | mutex_lock(&fs_info->volume_mutex); | ||
3457 | mutex_lock(&fs_info->balance_mutex); | ||
3458 | need_unlock = true; | ||
3459 | goto locked; | ||
3460 | } | ||
3461 | |||
3462 | /* | ||
3463 | * mut. excl. ops lock is locked. Three possibilites: | ||
3464 | * (1) some other op is running | ||
3465 | * (2) balance is running | ||
3466 | * (3) balance is paused -- special case (think resume) | ||
3467 | */ | ||
3451 | mutex_lock(&fs_info->balance_mutex); | 3468 | mutex_lock(&fs_info->balance_mutex); |
3469 | if (fs_info->balance_ctl) { | ||
3470 | /* this is either (2) or (3) */ | ||
3471 | if (!atomic_read(&fs_info->balance_running)) { | ||
3472 | mutex_unlock(&fs_info->balance_mutex); | ||
3473 | if (!mutex_trylock(&fs_info->volume_mutex)) | ||
3474 | goto again; | ||
3475 | mutex_lock(&fs_info->balance_mutex); | ||
3476 | |||
3477 | if (fs_info->balance_ctl && | ||
3478 | !atomic_read(&fs_info->balance_running)) { | ||
3479 | /* this is (3) */ | ||
3480 | need_unlock = false; | ||
3481 | goto locked; | ||
3482 | } | ||
3483 | |||
3484 | mutex_unlock(&fs_info->balance_mutex); | ||
3485 | mutex_unlock(&fs_info->volume_mutex); | ||
3486 | goto again; | ||
3487 | } else { | ||
3488 | /* this is (2) */ | ||
3489 | mutex_unlock(&fs_info->balance_mutex); | ||
3490 | ret = -EINPROGRESS; | ||
3491 | goto out; | ||
3492 | } | ||
3493 | } else { | ||
3494 | /* this is (1) */ | ||
3495 | mutex_unlock(&fs_info->balance_mutex); | ||
3496 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3497 | ret = -EINVAL; | ||
3498 | goto out; | ||
3499 | } | ||
3500 | |||
3501 | locked: | ||
3502 | BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running)); | ||
3452 | 3503 | ||
3453 | if (arg) { | 3504 | if (arg) { |
3454 | bargs = memdup_user(arg, sizeof(*bargs)); | 3505 | bargs = memdup_user(arg, sizeof(*bargs)); |
3455 | if (IS_ERR(bargs)) { | 3506 | if (IS_ERR(bargs)) { |
3456 | ret = PTR_ERR(bargs); | 3507 | ret = PTR_ERR(bargs); |
3457 | goto out; | 3508 | goto out_unlock; |
3458 | } | 3509 | } |
3459 | 3510 | ||
3460 | if (bargs->flags & BTRFS_BALANCE_RESUME) { | 3511 | if (bargs->flags & BTRFS_BALANCE_RESUME) { |
@@ -3474,13 +3525,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3474 | bargs = NULL; | 3525 | bargs = NULL; |
3475 | } | 3526 | } |
3476 | 3527 | ||
3477 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 3528 | if (fs_info->balance_ctl) { |
3478 | 1)) { | ||
3479 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3480 | ret = -EINPROGRESS; | 3529 | ret = -EINPROGRESS; |
3481 | goto out_bargs; | 3530 | goto out_bargs; |
3482 | } | 3531 | } |
3483 | need_to_clear_lock = 1; | ||
3484 | 3532 | ||
3485 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | 3533 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); |
3486 | if (!bctl) { | 3534 | if (!bctl) { |
@@ -3501,11 +3549,17 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3501 | } | 3549 | } |
3502 | 3550 | ||
3503 | do_balance: | 3551 | do_balance: |
3504 | ret = btrfs_balance(bctl, bargs); | ||
3505 | /* | 3552 | /* |
3506 | * bctl is freed in __cancel_balance or in free_fs_info if | 3553 | * Ownership of bctl and mutually_exclusive_operation_running |
3507 | * restriper was paused all the way until unmount | 3554 | * goes to to btrfs_balance. bctl is freed in __cancel_balance, |
3555 | * or, if restriper was paused all the way until unmount, in | ||
3556 | * free_fs_info. mutually_exclusive_operation_running is | ||
3557 | * cleared in __cancel_balance. | ||
3508 | */ | 3558 | */ |
3559 | need_unlock = false; | ||
3560 | |||
3561 | ret = btrfs_balance(bctl, bargs); | ||
3562 | |||
3509 | if (arg) { | 3563 | if (arg) { |
3510 | if (copy_to_user(arg, bargs, sizeof(*bargs))) | 3564 | if (copy_to_user(arg, bargs, sizeof(*bargs))) |
3511 | ret = -EFAULT; | 3565 | ret = -EFAULT; |
@@ -3513,12 +3567,12 @@ do_balance: | |||
3513 | 3567 | ||
3514 | out_bargs: | 3568 | out_bargs: |
3515 | kfree(bargs); | 3569 | kfree(bargs); |
3516 | out: | 3570 | out_unlock: |
3517 | if (need_to_clear_lock) | ||
3518 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | ||
3519 | 0); | ||
3520 | mutex_unlock(&fs_info->balance_mutex); | 3571 | mutex_unlock(&fs_info->balance_mutex); |
3521 | mutex_unlock(&fs_info->volume_mutex); | 3572 | mutex_unlock(&fs_info->volume_mutex); |
3573 | if (need_unlock) | ||
3574 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | ||
3575 | out: | ||
3522 | mnt_drop_write_file(file); | 3576 | mnt_drop_write_file(file); |
3523 | return ret; | 3577 | return ret; |
3524 | } | 3578 | } |
@@ -3698,6 +3752,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) | |||
3698 | goto drop_write; | 3752 | goto drop_write; |
3699 | } | 3753 | } |
3700 | 3754 | ||
3755 | if (!sa->qgroupid) { | ||
3756 | ret = -EINVAL; | ||
3757 | goto out; | ||
3758 | } | ||
3759 | |||
3701 | trans = btrfs_join_transaction(root); | 3760 | trans = btrfs_join_transaction(root); |
3702 | if (IS_ERR(trans)) { | 3761 | if (IS_ERR(trans)) { |
3703 | ret = PTR_ERR(trans); | 3762 | ret = PTR_ERR(trans); |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index fe9d02c45f8e..a5c856234323 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
@@ -379,6 +379,13 @@ next1: | |||
379 | 379 | ||
380 | ret = add_relation_rb(fs_info, found_key.objectid, | 380 | ret = add_relation_rb(fs_info, found_key.objectid, |
381 | found_key.offset); | 381 | found_key.offset); |
382 | if (ret == -ENOENT) { | ||
383 | printk(KERN_WARNING | ||
384 | "btrfs: orphan qgroup relation 0x%llx->0x%llx\n", | ||
385 | (unsigned long long)found_key.objectid, | ||
386 | (unsigned long long)found_key.offset); | ||
387 | ret = 0; /* ignore the error */ | ||
388 | } | ||
382 | if (ret) | 389 | if (ret) |
383 | goto out; | 390 | goto out; |
384 | next2: | 391 | next2: |
@@ -956,17 +963,28 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, | |||
956 | struct btrfs_fs_info *fs_info, u64 qgroupid) | 963 | struct btrfs_fs_info *fs_info, u64 qgroupid) |
957 | { | 964 | { |
958 | struct btrfs_root *quota_root; | 965 | struct btrfs_root *quota_root; |
966 | struct btrfs_qgroup *qgroup; | ||
959 | int ret = 0; | 967 | int ret = 0; |
960 | 968 | ||
961 | quota_root = fs_info->quota_root; | 969 | quota_root = fs_info->quota_root; |
962 | if (!quota_root) | 970 | if (!quota_root) |
963 | return -EINVAL; | 971 | return -EINVAL; |
964 | 972 | ||
973 | /* check if there are no relations to this qgroup */ | ||
974 | spin_lock(&fs_info->qgroup_lock); | ||
975 | qgroup = find_qgroup_rb(fs_info, qgroupid); | ||
976 | if (qgroup) { | ||
977 | if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) { | ||
978 | spin_unlock(&fs_info->qgroup_lock); | ||
979 | return -EBUSY; | ||
980 | } | ||
981 | } | ||
982 | spin_unlock(&fs_info->qgroup_lock); | ||
983 | |||
965 | ret = del_qgroup_item(trans, quota_root, qgroupid); | 984 | ret = del_qgroup_item(trans, quota_root, qgroupid); |
966 | 985 | ||
967 | spin_lock(&fs_info->qgroup_lock); | 986 | spin_lock(&fs_info->qgroup_lock); |
968 | del_qgroup_rb(quota_root->fs_info, qgroupid); | 987 | del_qgroup_rb(quota_root->fs_info, qgroupid); |
969 | |||
970 | spin_unlock(&fs_info->qgroup_lock); | 988 | spin_unlock(&fs_info->qgroup_lock); |
971 | 989 | ||
972 | return ret; | 990 | return ret; |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 54454542ad40..321b7fb4e441 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1814,8 +1814,10 @@ static int name_cache_insert(struct send_ctx *sctx, | |||
1814 | (unsigned long)nce->ino); | 1814 | (unsigned long)nce->ino); |
1815 | if (!nce_head) { | 1815 | if (!nce_head) { |
1816 | nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS); | 1816 | nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS); |
1817 | if (!nce_head) | 1817 | if (!nce_head) { |
1818 | kfree(nce); | ||
1818 | return -ENOMEM; | 1819 | return -ENOMEM; |
1820 | } | ||
1819 | INIT_LIST_HEAD(nce_head); | 1821 | INIT_LIST_HEAD(nce_head); |
1820 | 1822 | ||
1821 | ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head); | 1823 | ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 99545df1b86c..d8982e9601d3 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -267,7 +267,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans, | |||
267 | function, line, errstr); | 267 | function, line, errstr); |
268 | return; | 268 | return; |
269 | } | 269 | } |
270 | trans->transaction->aborted = errno; | 270 | ACCESS_ONCE(trans->transaction->aborted) = errno; |
271 | __btrfs_std_error(root->fs_info, function, line, errno, NULL); | 271 | __btrfs_std_error(root->fs_info, function, line, errno, NULL); |
272 | } | 272 | } |
273 | /* | 273 | /* |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 87fac9a21ea5..f15494699f3b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1468,7 +1468,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1468 | goto cleanup_transaction; | 1468 | goto cleanup_transaction; |
1469 | } | 1469 | } |
1470 | 1470 | ||
1471 | if (cur_trans->aborted) { | 1471 | /* Stop the commit early if ->aborted is set */ |
1472 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { | ||
1472 | ret = cur_trans->aborted; | 1473 | ret = cur_trans->aborted; |
1473 | goto cleanup_transaction; | 1474 | goto cleanup_transaction; |
1474 | } | 1475 | } |
@@ -1574,6 +1575,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1574 | wait_event(cur_trans->writer_wait, | 1575 | wait_event(cur_trans->writer_wait, |
1575 | atomic_read(&cur_trans->num_writers) == 1); | 1576 | atomic_read(&cur_trans->num_writers) == 1); |
1576 | 1577 | ||
1578 | /* ->aborted might be set after the previous check, so check it */ | ||
1579 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { | ||
1580 | ret = cur_trans->aborted; | ||
1581 | goto cleanup_transaction; | ||
1582 | } | ||
1577 | /* | 1583 | /* |
1578 | * the reloc mutex makes sure that we stop | 1584 | * the reloc mutex makes sure that we stop |
1579 | * the balancing code from coming in and moving | 1585 | * the balancing code from coming in and moving |
@@ -1657,6 +1663,17 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1657 | goto cleanup_transaction; | 1663 | goto cleanup_transaction; |
1658 | } | 1664 | } |
1659 | 1665 | ||
1666 | /* | ||
1667 | * The tasks which save the space cache and inode cache may also | ||
1668 | * update ->aborted, check it. | ||
1669 | */ | ||
1670 | if (unlikely(ACCESS_ONCE(cur_trans->aborted))) { | ||
1671 | ret = cur_trans->aborted; | ||
1672 | mutex_unlock(&root->fs_info->tree_log_mutex); | ||
1673 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
1674 | goto cleanup_transaction; | ||
1675 | } | ||
1676 | |||
1660 | btrfs_prepare_extent_commit(trans, root); | 1677 | btrfs_prepare_extent_commit(trans, root); |
1661 | 1678 | ||
1662 | cur_trans = root->fs_info->running_transaction; | 1679 | cur_trans = root->fs_info->running_transaction; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 83186c7e45d4..9027bb1e7466 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -3357,6 +3357,11 @@ static int log_one_extent(struct btrfs_trans_handle *trans, | |||
3357 | if (skip_csum) | 3357 | if (skip_csum) |
3358 | return 0; | 3358 | return 0; |
3359 | 3359 | ||
3360 | if (em->compress_type) { | ||
3361 | csum_offset = 0; | ||
3362 | csum_len = block_len; | ||
3363 | } | ||
3364 | |||
3360 | /* block start is already adjusted for the file extent offset. */ | 3365 | /* block start is already adjusted for the file extent offset. */ |
3361 | ret = btrfs_lookup_csums_range(log->fs_info->csum_root, | 3366 | ret = btrfs_lookup_csums_range(log->fs_info->csum_root, |
3362 | em->block_start + csum_offset, | 3367 | em->block_start + csum_offset, |
@@ -3410,13 +3415,13 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
3410 | em = list_entry(extents.next, struct extent_map, list); | 3415 | em = list_entry(extents.next, struct extent_map, list); |
3411 | 3416 | ||
3412 | list_del_init(&em->list); | 3417 | list_del_init(&em->list); |
3413 | clear_bit(EXTENT_FLAG_LOGGING, &em->flags); | ||
3414 | 3418 | ||
3415 | /* | 3419 | /* |
3416 | * If we had an error we just need to delete everybody from our | 3420 | * If we had an error we just need to delete everybody from our |
3417 | * private list. | 3421 | * private list. |
3418 | */ | 3422 | */ |
3419 | if (ret) { | 3423 | if (ret) { |
3424 | clear_em_logging(tree, em); | ||
3420 | free_extent_map(em); | 3425 | free_extent_map(em); |
3421 | continue; | 3426 | continue; |
3422 | } | 3427 | } |
@@ -3424,8 +3429,9 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans, | |||
3424 | write_unlock(&tree->lock); | 3429 | write_unlock(&tree->lock); |
3425 | 3430 | ||
3426 | ret = log_one_extent(trans, inode, root, em, path); | 3431 | ret = log_one_extent(trans, inode, root, em, path); |
3427 | free_extent_map(em); | ||
3428 | write_lock(&tree->lock); | 3432 | write_lock(&tree->lock); |
3433 | clear_em_logging(tree, em); | ||
3434 | free_extent_map(em); | ||
3429 | } | 3435 | } |
3430 | WARN_ON(!list_empty(&extents)); | 3436 | WARN_ON(!list_empty(&extents)); |
3431 | write_unlock(&tree->lock); | 3437 | write_unlock(&tree->lock); |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 5cce6aa74012..15f6efdf6463 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1431,7 +1431,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path) | |||
1431 | } | 1431 | } |
1432 | } else { | 1432 | } else { |
1433 | ret = btrfs_get_bdev_and_sb(device_path, | 1433 | ret = btrfs_get_bdev_and_sb(device_path, |
1434 | FMODE_READ | FMODE_EXCL, | 1434 | FMODE_WRITE | FMODE_EXCL, |
1435 | root->fs_info->bdev_holder, 0, | 1435 | root->fs_info->bdev_holder, 0, |
1436 | &bdev, &bh); | 1436 | &bdev, &bh); |
1437 | if (ret) | 1437 | if (ret) |
@@ -2614,7 +2614,14 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset, | |||
2614 | cache = btrfs_lookup_block_group(fs_info, chunk_offset); | 2614 | cache = btrfs_lookup_block_group(fs_info, chunk_offset); |
2615 | chunk_used = btrfs_block_group_used(&cache->item); | 2615 | chunk_used = btrfs_block_group_used(&cache->item); |
2616 | 2616 | ||
2617 | user_thresh = div_factor_fine(cache->key.offset, bargs->usage); | 2617 | if (bargs->usage == 0) |
2618 | user_thresh = 0; | ||
2619 | else if (bargs->usage > 100) | ||
2620 | user_thresh = cache->key.offset; | ||
2621 | else | ||
2622 | user_thresh = div_factor_fine(cache->key.offset, | ||
2623 | bargs->usage); | ||
2624 | |||
2618 | if (chunk_used < user_thresh) | 2625 | if (chunk_used < user_thresh) |
2619 | ret = 0; | 2626 | ret = 0; |
2620 | 2627 | ||
@@ -2959,6 +2966,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) | |||
2959 | unset_balance_control(fs_info); | 2966 | unset_balance_control(fs_info); |
2960 | ret = del_balance_item(fs_info->tree_root); | 2967 | ret = del_balance_item(fs_info->tree_root); |
2961 | BUG_ON(ret); | 2968 | BUG_ON(ret); |
2969 | |||
2970 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | ||
2962 | } | 2971 | } |
2963 | 2972 | ||
2964 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, | 2973 | void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, |
@@ -3138,8 +3147,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
3138 | out: | 3147 | out: |
3139 | if (bctl->flags & BTRFS_BALANCE_RESUME) | 3148 | if (bctl->flags & BTRFS_BALANCE_RESUME) |
3140 | __cancel_balance(fs_info); | 3149 | __cancel_balance(fs_info); |
3141 | else | 3150 | else { |
3142 | kfree(bctl); | 3151 | kfree(bctl); |
3152 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | ||
3153 | } | ||
3143 | return ret; | 3154 | return ret; |
3144 | } | 3155 | } |
3145 | 3156 | ||
@@ -3156,7 +3167,6 @@ static int balance_kthread(void *data) | |||
3156 | ret = btrfs_balance(fs_info->balance_ctl, NULL); | 3167 | ret = btrfs_balance(fs_info->balance_ctl, NULL); |
3157 | } | 3168 | } |
3158 | 3169 | ||
3159 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | ||
3160 | mutex_unlock(&fs_info->balance_mutex); | 3170 | mutex_unlock(&fs_info->balance_mutex); |
3161 | mutex_unlock(&fs_info->volume_mutex); | 3171 | mutex_unlock(&fs_info->volume_mutex); |
3162 | 3172 | ||
@@ -3179,7 +3189,6 @@ int btrfs_resume_balance_async(struct btrfs_fs_info *fs_info) | |||
3179 | return 0; | 3189 | return 0; |
3180 | } | 3190 | } |
3181 | 3191 | ||
3182 | WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)); | ||
3183 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); | 3192 | tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance"); |
3184 | if (IS_ERR(tsk)) | 3193 | if (IS_ERR(tsk)) |
3185 | return PTR_ERR(tsk); | 3194 | return PTR_ERR(tsk); |
@@ -3233,6 +3242,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info) | |||
3233 | btrfs_balance_sys(leaf, item, &disk_bargs); | 3242 | btrfs_balance_sys(leaf, item, &disk_bargs); |
3234 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); | 3243 | btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs); |
3235 | 3244 | ||
3245 | WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)); | ||
3246 | |||
3236 | mutex_lock(&fs_info->volume_mutex); | 3247 | mutex_lock(&fs_info->volume_mutex); |
3237 | mutex_lock(&fs_info->balance_mutex); | 3248 | mutex_lock(&fs_info->balance_mutex); |
3238 | 3249 | ||
@@ -3496,7 +3507,7 @@ struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { | |||
3496 | { 1, 1, 2, 2, 2, 2 /* raid1 */ }, | 3507 | { 1, 1, 2, 2, 2, 2 /* raid1 */ }, |
3497 | { 1, 2, 1, 1, 1, 2 /* dup */ }, | 3508 | { 1, 2, 1, 1, 1, 2 /* dup */ }, |
3498 | { 1, 1, 0, 2, 1, 1 /* raid0 */ }, | 3509 | { 1, 1, 0, 2, 1, 1 /* raid0 */ }, |
3499 | { 1, 1, 0, 1, 1, 1 /* single */ }, | 3510 | { 1, 1, 1, 1, 1, 1 /* single */ }, |
3500 | }; | 3511 | }; |
3501 | 3512 | ||
3502 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, | 3513 | static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, |
diff --git a/fs/buffer.c b/fs/buffer.c index c017a2dfb909..7a75c3e0fd58 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -2935,6 +2935,7 @@ static void guard_bh_eod(int rw, struct bio *bio, struct buffer_head *bh) | |||
2935 | void *kaddr = kmap_atomic(bh->b_page); | 2935 | void *kaddr = kmap_atomic(bh->b_page); |
2936 | memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); | 2936 | memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes); |
2937 | kunmap_atomic(kaddr); | 2937 | kunmap_atomic(kaddr); |
2938 | flush_dcache_page(bh->b_page); | ||
2938 | } | 2939 | } |
2939 | } | 2940 | } |
2940 | 2941 | ||
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index ce5cbd717bfc..210fce2df308 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -226,6 +226,8 @@ compose_mount_options_out: | |||
226 | compose_mount_options_err: | 226 | compose_mount_options_err: |
227 | kfree(mountdata); | 227 | kfree(mountdata); |
228 | mountdata = ERR_PTR(rc); | 228 | mountdata = ERR_PTR(rc); |
229 | kfree(*devname); | ||
230 | *devname = NULL; | ||
229 | goto compose_mount_options_out; | 231 | goto compose_mount_options_out; |
230 | } | 232 | } |
231 | 233 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 17c3643e5950..12b3da39733b 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -1917,7 +1917,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs) | |||
1917 | } | 1917 | } |
1918 | case AF_INET6: { | 1918 | case AF_INET6: { |
1919 | struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; | 1919 | struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr; |
1920 | struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs; | 1920 | struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs; |
1921 | return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); | 1921 | return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr); |
1922 | } | 1922 | } |
1923 | default: | 1923 | default: |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 153bb1e42e63..a5f12b7e228d 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -176,7 +176,7 @@ static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts) | |||
176 | opts->uid = uid; | 176 | opts->uid = uid; |
177 | break; | 177 | break; |
178 | case Opt_gid: | 178 | case Opt_gid: |
179 | if (match_octal(&args[0], &option)) | 179 | if (match_int(&args[0], &option)) |
180 | return -EINVAL; | 180 | return -EINVAL; |
181 | gid = make_kgid(current_user_ns(), option); | 181 | gid = make_kgid(current_user_ns(), option); |
182 | if (!gid_valid(gid)) | 182 | if (!gid_valid(gid)) |
@@ -434,8 +434,9 @@ static int count(struct user_arg_ptr argv, int max) | |||
434 | if (IS_ERR(p)) | 434 | if (IS_ERR(p)) |
435 | return -EFAULT; | 435 | return -EFAULT; |
436 | 436 | ||
437 | if (i++ >= max) | 437 | if (i >= max) |
438 | return -E2BIG; | 438 | return -E2BIG; |
439 | ++i; | ||
439 | 440 | ||
440 | if (fatal_signal_pending(current)) | 441 | if (fatal_signal_pending(current)) |
441 | return -ERESTARTNOHAND; | 442 | return -ERESTARTNOHAND; |
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index e95b94945d5f..137af4255da6 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c | |||
@@ -191,15 +191,14 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type) | |||
191 | retval = f2fs_getxattr(inode, name_index, "", value, retval); | 191 | retval = f2fs_getxattr(inode, name_index, "", value, retval); |
192 | } | 192 | } |
193 | 193 | ||
194 | if (retval < 0) { | 194 | if (retval > 0) |
195 | if (retval == -ENODATA) | ||
196 | acl = NULL; | ||
197 | else | ||
198 | acl = ERR_PTR(retval); | ||
199 | } else { | ||
200 | acl = f2fs_acl_from_disk(value, retval); | 195 | acl = f2fs_acl_from_disk(value, retval); |
201 | } | 196 | else if (retval == -ENODATA) |
197 | acl = NULL; | ||
198 | else | ||
199 | acl = ERR_PTR(retval); | ||
202 | kfree(value); | 200 | kfree(value); |
201 | |||
203 | if (!IS_ERR(acl)) | 202 | if (!IS_ERR(acl)) |
204 | set_cached_acl(inode, type, acl); | 203 | set_cached_acl(inode, type, acl); |
205 | 204 | ||
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 6ef36c37e2be..ff3c8439af87 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c | |||
@@ -214,7 +214,6 @@ retry: | |||
214 | goto retry; | 214 | goto retry; |
215 | } | 215 | } |
216 | new->ino = ino; | 216 | new->ino = ino; |
217 | INIT_LIST_HEAD(&new->list); | ||
218 | 217 | ||
219 | /* add new_oentry into list which is sorted by inode number */ | 218 | /* add new_oentry into list which is sorted by inode number */ |
220 | if (orphan) { | 219 | if (orphan) { |
@@ -772,7 +771,7 @@ void init_orphan_info(struct f2fs_sb_info *sbi) | |||
772 | sbi->n_orphans = 0; | 771 | sbi->n_orphans = 0; |
773 | } | 772 | } |
774 | 773 | ||
775 | int create_checkpoint_caches(void) | 774 | int __init create_checkpoint_caches(void) |
776 | { | 775 | { |
777 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", | 776 | orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", |
778 | sizeof(struct orphan_inode_entry), NULL); | 777 | sizeof(struct orphan_inode_entry), NULL); |
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 3aa5ce7cab83..7bd22a201125 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c | |||
@@ -547,6 +547,15 @@ redirty_out: | |||
547 | 547 | ||
548 | #define MAX_DESIRED_PAGES_WP 4096 | 548 | #define MAX_DESIRED_PAGES_WP 4096 |
549 | 549 | ||
550 | static int __f2fs_writepage(struct page *page, struct writeback_control *wbc, | ||
551 | void *data) | ||
552 | { | ||
553 | struct address_space *mapping = data; | ||
554 | int ret = mapping->a_ops->writepage(page, wbc); | ||
555 | mapping_set_error(mapping, ret); | ||
556 | return ret; | ||
557 | } | ||
558 | |||
550 | static int f2fs_write_data_pages(struct address_space *mapping, | 559 | static int f2fs_write_data_pages(struct address_space *mapping, |
551 | struct writeback_control *wbc) | 560 | struct writeback_control *wbc) |
552 | { | 561 | { |
@@ -563,7 +572,7 @@ static int f2fs_write_data_pages(struct address_space *mapping, | |||
563 | 572 | ||
564 | if (!S_ISDIR(inode->i_mode)) | 573 | if (!S_ISDIR(inode->i_mode)) |
565 | mutex_lock(&sbi->writepages); | 574 | mutex_lock(&sbi->writepages); |
566 | ret = generic_writepages(mapping, wbc); | 575 | ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); |
567 | if (!S_ISDIR(inode->i_mode)) | 576 | if (!S_ISDIR(inode->i_mode)) |
568 | mutex_unlock(&sbi->writepages); | 577 | mutex_unlock(&sbi->writepages); |
569 | f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL)); | 578 | f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL)); |
@@ -689,6 +698,11 @@ static int f2fs_set_data_page_dirty(struct page *page) | |||
689 | return 0; | 698 | return 0; |
690 | } | 699 | } |
691 | 700 | ||
701 | static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) | ||
702 | { | ||
703 | return generic_block_bmap(mapping, block, get_data_block_ro); | ||
704 | } | ||
705 | |||
692 | const struct address_space_operations f2fs_dblock_aops = { | 706 | const struct address_space_operations f2fs_dblock_aops = { |
693 | .readpage = f2fs_read_data_page, | 707 | .readpage = f2fs_read_data_page, |
694 | .readpages = f2fs_read_data_pages, | 708 | .readpages = f2fs_read_data_pages, |
@@ -700,4 +714,5 @@ const struct address_space_operations f2fs_dblock_aops = { | |||
700 | .invalidatepage = f2fs_invalidate_data_page, | 714 | .invalidatepage = f2fs_invalidate_data_page, |
701 | .releasepage = f2fs_release_data_page, | 715 | .releasepage = f2fs_release_data_page, |
702 | .direct_IO = f2fs_direct_IO, | 716 | .direct_IO = f2fs_direct_IO, |
717 | .bmap = f2fs_bmap, | ||
703 | }; | 718 | }; |
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c index 0e0380a588ad..c8c37307b326 100644 --- a/fs/f2fs/debug.c +++ b/fs/f2fs/debug.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | static LIST_HEAD(f2fs_stat_list); | 27 | static LIST_HEAD(f2fs_stat_list); |
28 | static struct dentry *debugfs_root; | 28 | static struct dentry *debugfs_root; |
29 | static DEFINE_MUTEX(f2fs_stat_mutex); | ||
29 | 30 | ||
30 | static void update_general_status(struct f2fs_sb_info *sbi) | 31 | static void update_general_status(struct f2fs_sb_info *sbi) |
31 | { | 32 | { |
@@ -180,18 +181,14 @@ static int stat_show(struct seq_file *s, void *v) | |||
180 | int i = 0; | 181 | int i = 0; |
181 | int j; | 182 | int j; |
182 | 183 | ||
184 | mutex_lock(&f2fs_stat_mutex); | ||
183 | list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { | 185 | list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) { |
184 | 186 | ||
185 | mutex_lock(&si->stat_lock); | ||
186 | if (!si->sbi) { | ||
187 | mutex_unlock(&si->stat_lock); | ||
188 | continue; | ||
189 | } | ||
190 | update_general_status(si->sbi); | 187 | update_general_status(si->sbi); |
191 | 188 | ||
192 | seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++); | 189 | seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++); |
193 | seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ", | 190 | seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", |
194 | si->nat_area_segs, si->sit_area_segs); | 191 | si->sit_area_segs, si->nat_area_segs); |
195 | seq_printf(s, "[SSA: %d] [MAIN: %d", | 192 | seq_printf(s, "[SSA: %d] [MAIN: %d", |
196 | si->ssa_area_segs, si->main_area_segs); | 193 | si->ssa_area_segs, si->main_area_segs); |
197 | seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", | 194 | seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", |
@@ -286,8 +283,8 @@ static int stat_show(struct seq_file *s, void *v) | |||
286 | seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", | 283 | seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", |
287 | (si->base_mem + si->cache_mem) >> 10, | 284 | (si->base_mem + si->cache_mem) >> 10, |
288 | si->base_mem >> 10, si->cache_mem >> 10); | 285 | si->base_mem >> 10, si->cache_mem >> 10); |
289 | mutex_unlock(&si->stat_lock); | ||
290 | } | 286 | } |
287 | mutex_unlock(&f2fs_stat_mutex); | ||
291 | return 0; | 288 | return 0; |
292 | } | 289 | } |
293 | 290 | ||
@@ -303,7 +300,7 @@ static const struct file_operations stat_fops = { | |||
303 | .release = single_release, | 300 | .release = single_release, |
304 | }; | 301 | }; |
305 | 302 | ||
306 | static int init_stats(struct f2fs_sb_info *sbi) | 303 | int f2fs_build_stats(struct f2fs_sb_info *sbi) |
307 | { | 304 | { |
308 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 305 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
309 | struct f2fs_stat_info *si; | 306 | struct f2fs_stat_info *si; |
@@ -313,9 +310,6 @@ static int init_stats(struct f2fs_sb_info *sbi) | |||
313 | return -ENOMEM; | 310 | return -ENOMEM; |
314 | 311 | ||
315 | si = sbi->stat_info; | 312 | si = sbi->stat_info; |
316 | mutex_init(&si->stat_lock); | ||
317 | list_add_tail(&si->stat_list, &f2fs_stat_list); | ||
318 | |||
319 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); | 313 | si->all_area_segs = le32_to_cpu(raw_super->segment_count); |
320 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); | 314 | si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); |
321 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); | 315 | si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); |
@@ -325,21 +319,11 @@ static int init_stats(struct f2fs_sb_info *sbi) | |||
325 | si->main_area_zones = si->main_area_sections / | 319 | si->main_area_zones = si->main_area_sections / |
326 | le32_to_cpu(raw_super->secs_per_zone); | 320 | le32_to_cpu(raw_super->secs_per_zone); |
327 | si->sbi = sbi; | 321 | si->sbi = sbi; |
328 | return 0; | ||
329 | } | ||
330 | 322 | ||
331 | int f2fs_build_stats(struct f2fs_sb_info *sbi) | 323 | mutex_lock(&f2fs_stat_mutex); |
332 | { | 324 | list_add_tail(&si->stat_list, &f2fs_stat_list); |
333 | int retval; | 325 | mutex_unlock(&f2fs_stat_mutex); |
334 | |||
335 | retval = init_stats(sbi); | ||
336 | if (retval) | ||
337 | return retval; | ||
338 | |||
339 | if (!debugfs_root) | ||
340 | debugfs_root = debugfs_create_dir("f2fs", NULL); | ||
341 | 326 | ||
342 | debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops); | ||
343 | return 0; | 327 | return 0; |
344 | } | 328 | } |
345 | 329 | ||
@@ -347,14 +331,22 @@ void f2fs_destroy_stats(struct f2fs_sb_info *sbi) | |||
347 | { | 331 | { |
348 | struct f2fs_stat_info *si = sbi->stat_info; | 332 | struct f2fs_stat_info *si = sbi->stat_info; |
349 | 333 | ||
334 | mutex_lock(&f2fs_stat_mutex); | ||
350 | list_del(&si->stat_list); | 335 | list_del(&si->stat_list); |
351 | mutex_lock(&si->stat_lock); | 336 | mutex_unlock(&f2fs_stat_mutex); |
352 | si->sbi = NULL; | 337 | |
353 | mutex_unlock(&si->stat_lock); | ||
354 | kfree(sbi->stat_info); | 338 | kfree(sbi->stat_info); |
355 | } | 339 | } |
356 | 340 | ||
357 | void destroy_root_stats(void) | 341 | void __init f2fs_create_root_stats(void) |
342 | { | ||
343 | debugfs_root = debugfs_create_dir("f2fs", NULL); | ||
344 | if (debugfs_root) | ||
345 | debugfs_create_file("status", S_IRUGO, debugfs_root, | ||
346 | NULL, &stat_fops); | ||
347 | } | ||
348 | |||
349 | void f2fs_destroy_root_stats(void) | ||
358 | { | 350 | { |
359 | debugfs_remove_recursive(debugfs_root); | 351 | debugfs_remove_recursive(debugfs_root); |
360 | debugfs_root = NULL; | 352 | debugfs_root = NULL; |
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 951ed52748f6..989980e16d0b 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c | |||
@@ -503,7 +503,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, | |||
503 | } | 503 | } |
504 | 504 | ||
505 | if (inode) { | 505 | if (inode) { |
506 | inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 506 | inode->i_ctime = CURRENT_TIME; |
507 | drop_nlink(inode); | 507 | drop_nlink(inode); |
508 | if (S_ISDIR(inode->i_mode)) { | 508 | if (S_ISDIR(inode->i_mode)) { |
509 | drop_nlink(inode); | 509 | drop_nlink(inode); |
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 13c6dfbb7183..c8e2d751ef9c 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -211,11 +211,11 @@ struct dnode_of_data { | |||
211 | static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, | 211 | static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, |
212 | struct page *ipage, struct page *npage, nid_t nid) | 212 | struct page *ipage, struct page *npage, nid_t nid) |
213 | { | 213 | { |
214 | memset(dn, 0, sizeof(*dn)); | ||
214 | dn->inode = inode; | 215 | dn->inode = inode; |
215 | dn->inode_page = ipage; | 216 | dn->inode_page = ipage; |
216 | dn->node_page = npage; | 217 | dn->node_page = npage; |
217 | dn->nid = nid; | 218 | dn->nid = nid; |
218 | dn->inode_page_locked = 0; | ||
219 | } | 219 | } |
220 | 220 | ||
221 | /* | 221 | /* |
@@ -877,6 +877,8 @@ bool f2fs_empty_dir(struct inode *); | |||
877 | * super.c | 877 | * super.c |
878 | */ | 878 | */ |
879 | int f2fs_sync_fs(struct super_block *, int); | 879 | int f2fs_sync_fs(struct super_block *, int); |
880 | extern __printf(3, 4) | ||
881 | void f2fs_msg(struct super_block *, const char *, const char *, ...); | ||
880 | 882 | ||
881 | /* | 883 | /* |
882 | * hash.c | 884 | * hash.c |
@@ -912,7 +914,7 @@ int restore_node_summary(struct f2fs_sb_info *, unsigned int, | |||
912 | void flush_nat_entries(struct f2fs_sb_info *); | 914 | void flush_nat_entries(struct f2fs_sb_info *); |
913 | int build_node_manager(struct f2fs_sb_info *); | 915 | int build_node_manager(struct f2fs_sb_info *); |
914 | void destroy_node_manager(struct f2fs_sb_info *); | 916 | void destroy_node_manager(struct f2fs_sb_info *); |
915 | int create_node_manager_caches(void); | 917 | int __init create_node_manager_caches(void); |
916 | void destroy_node_manager_caches(void); | 918 | void destroy_node_manager_caches(void); |
917 | 919 | ||
918 | /* | 920 | /* |
@@ -964,7 +966,7 @@ void sync_dirty_dir_inodes(struct f2fs_sb_info *); | |||
964 | void block_operations(struct f2fs_sb_info *); | 966 | void block_operations(struct f2fs_sb_info *); |
965 | void write_checkpoint(struct f2fs_sb_info *, bool, bool); | 967 | void write_checkpoint(struct f2fs_sb_info *, bool, bool); |
966 | void init_orphan_info(struct f2fs_sb_info *); | 968 | void init_orphan_info(struct f2fs_sb_info *); |
967 | int create_checkpoint_caches(void); | 969 | int __init create_checkpoint_caches(void); |
968 | void destroy_checkpoint_caches(void); | 970 | void destroy_checkpoint_caches(void); |
969 | 971 | ||
970 | /* | 972 | /* |
@@ -984,9 +986,9 @@ int do_write_data_page(struct page *); | |||
984 | int start_gc_thread(struct f2fs_sb_info *); | 986 | int start_gc_thread(struct f2fs_sb_info *); |
985 | void stop_gc_thread(struct f2fs_sb_info *); | 987 | void stop_gc_thread(struct f2fs_sb_info *); |
986 | block_t start_bidx_of_node(unsigned int); | 988 | block_t start_bidx_of_node(unsigned int); |
987 | int f2fs_gc(struct f2fs_sb_info *, int); | 989 | int f2fs_gc(struct f2fs_sb_info *); |
988 | void build_gc_manager(struct f2fs_sb_info *); | 990 | void build_gc_manager(struct f2fs_sb_info *); |
989 | int create_gc_caches(void); | 991 | int __init create_gc_caches(void); |
990 | void destroy_gc_caches(void); | 992 | void destroy_gc_caches(void); |
991 | 993 | ||
992 | /* | 994 | /* |
@@ -1058,7 +1060,8 @@ struct f2fs_stat_info { | |||
1058 | 1060 | ||
1059 | int f2fs_build_stats(struct f2fs_sb_info *); | 1061 | int f2fs_build_stats(struct f2fs_sb_info *); |
1060 | void f2fs_destroy_stats(struct f2fs_sb_info *); | 1062 | void f2fs_destroy_stats(struct f2fs_sb_info *); |
1061 | void destroy_root_stats(void); | 1063 | void __init f2fs_create_root_stats(void); |
1064 | void f2fs_destroy_root_stats(void); | ||
1062 | #else | 1065 | #else |
1063 | #define stat_inc_call_count(si) | 1066 | #define stat_inc_call_count(si) |
1064 | #define stat_inc_seg_count(si, type) | 1067 | #define stat_inc_seg_count(si, type) |
@@ -1068,7 +1071,8 @@ void destroy_root_stats(void); | |||
1068 | 1071 | ||
1069 | static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } | 1072 | static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } |
1070 | static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } | 1073 | static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } |
1071 | static inline void destroy_root_stats(void) { } | 1074 | static inline void __init f2fs_create_root_stats(void) { } |
1075 | static inline void f2fs_destroy_root_stats(void) { } | ||
1072 | #endif | 1076 | #endif |
1073 | 1077 | ||
1074 | extern const struct file_operations f2fs_dir_operations; | 1078 | extern const struct file_operations f2fs_dir_operations; |
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 7f9ea9271ebe..3191b52aafb0 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c | |||
@@ -96,8 +96,9 @@ out: | |||
96 | } | 96 | } |
97 | 97 | ||
98 | static const struct vm_operations_struct f2fs_file_vm_ops = { | 98 | static const struct vm_operations_struct f2fs_file_vm_ops = { |
99 | .fault = filemap_fault, | 99 | .fault = filemap_fault, |
100 | .page_mkwrite = f2fs_vm_page_mkwrite, | 100 | .page_mkwrite = f2fs_vm_page_mkwrite, |
101 | .remap_pages = generic_file_remap_pages, | ||
101 | }; | 102 | }; |
102 | 103 | ||
103 | static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) | 104 | static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode) |
@@ -137,6 +138,9 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) | |||
137 | if (ret) | 138 | if (ret) |
138 | return ret; | 139 | return ret; |
139 | 140 | ||
141 | /* guarantee free sections for fsync */ | ||
142 | f2fs_balance_fs(sbi); | ||
143 | |||
140 | mutex_lock(&inode->i_mutex); | 144 | mutex_lock(&inode->i_mutex); |
141 | 145 | ||
142 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 146 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
@@ -407,6 +411,8 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) | |||
407 | struct dnode_of_data dn; | 411 | struct dnode_of_data dn; |
408 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 412 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
409 | 413 | ||
414 | f2fs_balance_fs(sbi); | ||
415 | |||
410 | mutex_lock_op(sbi, DATA_TRUNC); | 416 | mutex_lock_op(sbi, DATA_TRUNC); |
411 | set_new_dnode(&dn, inode, NULL, NULL, 0); | 417 | set_new_dnode(&dn, inode, NULL, NULL, 0); |
412 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); | 418 | err = get_dnode_of_data(&dn, index, RDONLY_NODE); |
@@ -534,7 +540,6 @@ static long f2fs_fallocate(struct file *file, int mode, | |||
534 | loff_t offset, loff_t len) | 540 | loff_t offset, loff_t len) |
535 | { | 541 | { |
536 | struct inode *inode = file->f_path.dentry->d_inode; | 542 | struct inode *inode = file->f_path.dentry->d_inode; |
537 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | ||
538 | long ret; | 543 | long ret; |
539 | 544 | ||
540 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) | 545 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) |
@@ -545,7 +550,10 @@ static long f2fs_fallocate(struct file *file, int mode, | |||
545 | else | 550 | else |
546 | ret = expand_inode_data(inode, offset, len, mode); | 551 | ret = expand_inode_data(inode, offset, len, mode); |
547 | 552 | ||
548 | f2fs_balance_fs(sbi); | 553 | if (!ret) { |
554 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
555 | mark_inode_dirty(inode); | ||
556 | } | ||
549 | return ret; | 557 | return ret; |
550 | } | 558 | } |
551 | 559 | ||
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index b0ec721e984a..c386910dacc5 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c | |||
@@ -78,7 +78,7 @@ static int gc_thread_func(void *data) | |||
78 | 78 | ||
79 | sbi->bg_gc++; | 79 | sbi->bg_gc++; |
80 | 80 | ||
81 | if (f2fs_gc(sbi, 1) == GC_NONE) | 81 | if (f2fs_gc(sbi) == GC_NONE) |
82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; | 82 | wait_ms = GC_THREAD_NOGC_SLEEP_TIME; |
83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) | 83 | else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME) |
84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; | 84 | wait_ms = GC_THREAD_MAX_SLEEP_TIME; |
@@ -424,7 +424,11 @@ next_step: | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* | 426 | /* |
427 | * Calculate start block index that this node page contains | 427 | * Calculate start block index indicating the given node offset. |
428 | * Be careful, caller should give this node offset only indicating direct node | ||
429 | * blocks. If any node offsets, which point the other types of node blocks such | ||
430 | * as indirect or double indirect node blocks, are given, it must be a caller's | ||
431 | * bug. | ||
428 | */ | 432 | */ |
429 | block_t start_bidx_of_node(unsigned int node_ofs) | 433 | block_t start_bidx_of_node(unsigned int node_ofs) |
430 | { | 434 | { |
@@ -651,62 +655,44 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno, | |||
651 | return ret; | 655 | return ret; |
652 | } | 656 | } |
653 | 657 | ||
654 | int f2fs_gc(struct f2fs_sb_info *sbi, int nGC) | 658 | int f2fs_gc(struct f2fs_sb_info *sbi) |
655 | { | 659 | { |
656 | unsigned int segno; | ||
657 | int old_free_secs, cur_free_secs; | ||
658 | int gc_status, nfree; | ||
659 | struct list_head ilist; | 660 | struct list_head ilist; |
661 | unsigned int segno, i; | ||
660 | int gc_type = BG_GC; | 662 | int gc_type = BG_GC; |
663 | int gc_status = GC_NONE; | ||
661 | 664 | ||
662 | INIT_LIST_HEAD(&ilist); | 665 | INIT_LIST_HEAD(&ilist); |
663 | gc_more: | 666 | gc_more: |
664 | nfree = 0; | 667 | if (!(sbi->sb->s_flags & MS_ACTIVE)) |
665 | gc_status = GC_NONE; | 668 | goto stop; |
666 | 669 | ||
667 | if (has_not_enough_free_secs(sbi)) | 670 | if (has_not_enough_free_secs(sbi)) |
668 | old_free_secs = reserved_sections(sbi); | 671 | gc_type = FG_GC; |
669 | else | ||
670 | old_free_secs = free_sections(sbi); | ||
671 | |||
672 | while (sbi->sb->s_flags & MS_ACTIVE) { | ||
673 | int i; | ||
674 | if (has_not_enough_free_secs(sbi)) | ||
675 | gc_type = FG_GC; | ||
676 | 672 | ||
677 | cur_free_secs = free_sections(sbi) + nfree; | 673 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) |
674 | goto stop; | ||
678 | 675 | ||
679 | /* We got free space successfully. */ | 676 | for (i = 0; i < sbi->segs_per_sec; i++) { |
680 | if (nGC < cur_free_secs - old_free_secs) | 677 | /* |
681 | break; | 678 | * do_garbage_collect will give us three gc_status: |
682 | 679 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | |
683 | if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) | 680 | * If GC is finished uncleanly, we have to return |
681 | * the victim to dirty segment list. | ||
682 | */ | ||
683 | gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type); | ||
684 | if (gc_status != GC_DONE) | ||
684 | break; | 685 | break; |
685 | |||
686 | for (i = 0; i < sbi->segs_per_sec; i++) { | ||
687 | /* | ||
688 | * do_garbage_collect will give us three gc_status: | ||
689 | * GC_ERROR, GC_DONE, and GC_BLOCKED. | ||
690 | * If GC is finished uncleanly, we have to return | ||
691 | * the victim to dirty segment list. | ||
692 | */ | ||
693 | gc_status = do_garbage_collect(sbi, segno + i, | ||
694 | &ilist, gc_type); | ||
695 | if (gc_status != GC_DONE) | ||
696 | goto stop; | ||
697 | nfree++; | ||
698 | } | ||
699 | } | 686 | } |
700 | stop: | 687 | if (has_not_enough_free_secs(sbi)) { |
701 | if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) { | ||
702 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); | 688 | write_checkpoint(sbi, (gc_status == GC_BLOCKED), false); |
703 | if (nfree) | 689 | if (has_not_enough_free_secs(sbi)) |
704 | goto gc_more; | 690 | goto gc_more; |
705 | } | 691 | } |
692 | stop: | ||
706 | mutex_unlock(&sbi->gc_mutex); | 693 | mutex_unlock(&sbi->gc_mutex); |
707 | 694 | ||
708 | put_gc_inode(&ilist); | 695 | put_gc_inode(&ilist); |
709 | BUG_ON(!list_empty(&ilist)); | ||
710 | return gc_status; | 696 | return gc_status; |
711 | } | 697 | } |
712 | 698 | ||
@@ -715,7 +701,7 @@ void build_gc_manager(struct f2fs_sb_info *sbi) | |||
715 | DIRTY_I(sbi)->v_ops = &default_v_ops; | 701 | DIRTY_I(sbi)->v_ops = &default_v_ops; |
716 | } | 702 | } |
717 | 703 | ||
718 | int create_gc_caches(void) | 704 | int __init create_gc_caches(void) |
719 | { | 705 | { |
720 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", | 706 | winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", |
721 | sizeof(struct inode_entry), NULL); | 707 | sizeof(struct inode_entry), NULL); |
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index bf20b4d03214..794241777322 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c | |||
@@ -217,6 +217,9 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
217 | inode->i_ino == F2FS_META_INO(sbi)) | 217 | inode->i_ino == F2FS_META_INO(sbi)) |
218 | return 0; | 218 | return 0; |
219 | 219 | ||
220 | if (wbc) | ||
221 | f2fs_balance_fs(sbi); | ||
222 | |||
220 | node_page = get_node_page(sbi, inode->i_ino); | 223 | node_page = get_node_page(sbi, inode->i_ino); |
221 | if (IS_ERR(node_page)) | 224 | if (IS_ERR(node_page)) |
222 | return PTR_ERR(node_page); | 225 | return PTR_ERR(node_page); |
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 5066bfd256c9..9bda63c9c166 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -1124,6 +1124,12 @@ static int f2fs_write_node_page(struct page *page, | |||
1124 | return 0; | 1124 | return 0; |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | /* | ||
1128 | * It is very important to gather dirty pages and write at once, so that we can | ||
1129 | * submit a big bio without interfering other data writes. | ||
1130 | * Be default, 512 pages (2MB), a segment size, is quite reasonable. | ||
1131 | */ | ||
1132 | #define COLLECT_DIRTY_NODES 512 | ||
1127 | static int f2fs_write_node_pages(struct address_space *mapping, | 1133 | static int f2fs_write_node_pages(struct address_space *mapping, |
1128 | struct writeback_control *wbc) | 1134 | struct writeback_control *wbc) |
1129 | { | 1135 | { |
@@ -1131,17 +1137,16 @@ static int f2fs_write_node_pages(struct address_space *mapping, | |||
1131 | struct block_device *bdev = sbi->sb->s_bdev; | 1137 | struct block_device *bdev = sbi->sb->s_bdev; |
1132 | long nr_to_write = wbc->nr_to_write; | 1138 | long nr_to_write = wbc->nr_to_write; |
1133 | 1139 | ||
1134 | if (wbc->for_kupdate) | 1140 | /* First check balancing cached NAT entries */ |
1135 | return 0; | ||
1136 | |||
1137 | if (get_pages(sbi, F2FS_DIRTY_NODES) == 0) | ||
1138 | return 0; | ||
1139 | |||
1140 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { | 1141 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { |
1141 | write_checkpoint(sbi, false, false); | 1142 | write_checkpoint(sbi, false, false); |
1142 | return 0; | 1143 | return 0; |
1143 | } | 1144 | } |
1144 | 1145 | ||
1146 | /* collect a number of dirty node pages and write together */ | ||
1147 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) | ||
1148 | return 0; | ||
1149 | |||
1145 | /* if mounting is failed, skip writing node pages */ | 1150 | /* if mounting is failed, skip writing node pages */ |
1146 | wbc->nr_to_write = bio_get_nr_vecs(bdev); | 1151 | wbc->nr_to_write = bio_get_nr_vecs(bdev); |
1147 | sync_node_pages(sbi, 0, wbc); | 1152 | sync_node_pages(sbi, 0, wbc); |
@@ -1732,7 +1737,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi) | |||
1732 | kfree(nm_i); | 1737 | kfree(nm_i); |
1733 | } | 1738 | } |
1734 | 1739 | ||
1735 | int create_node_manager_caches(void) | 1740 | int __init create_node_manager_caches(void) |
1736 | { | 1741 | { |
1737 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", | 1742 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", |
1738 | sizeof(struct nat_entry), NULL); | 1743 | sizeof(struct nat_entry), NULL); |
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index b571fee677d5..f42e4060b399 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c | |||
@@ -67,7 +67,7 @@ static int recover_dentry(struct page *ipage, struct inode *inode) | |||
67 | kunmap(page); | 67 | kunmap(page); |
68 | f2fs_put_page(page, 0); | 68 | f2fs_put_page(page, 0); |
69 | } else { | 69 | } else { |
70 | f2fs_add_link(&dent, inode); | 70 | err = f2fs_add_link(&dent, inode); |
71 | } | 71 | } |
72 | iput(dir); | 72 | iput(dir); |
73 | out: | 73 | out: |
@@ -151,7 +151,6 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) | |||
151 | goto out; | 151 | goto out; |
152 | } | 152 | } |
153 | 153 | ||
154 | INIT_LIST_HEAD(&entry->list); | ||
155 | list_add_tail(&entry->list, head); | 154 | list_add_tail(&entry->list, head); |
156 | entry->blkaddr = blkaddr; | 155 | entry->blkaddr = blkaddr; |
157 | } | 156 | } |
@@ -174,10 +173,9 @@ out: | |||
174 | static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, | 173 | static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi, |
175 | struct list_head *head) | 174 | struct list_head *head) |
176 | { | 175 | { |
177 | struct list_head *this; | 176 | struct fsync_inode_entry *entry, *tmp; |
178 | struct fsync_inode_entry *entry; | 177 | |
179 | list_for_each(this, head) { | 178 | list_for_each_entry_safe(entry, tmp, head, list) { |
180 | entry = list_entry(this, struct fsync_inode_entry, list); | ||
181 | iput(entry->inode); | 179 | iput(entry->inode); |
182 | list_del(&entry->list); | 180 | list_del(&entry->list); |
183 | kmem_cache_free(fsync_entry_slab, entry); | 181 | kmem_cache_free(fsync_entry_slab, entry); |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index de6240922b0a..4b0099066582 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -31,7 +31,7 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi) | |||
31 | */ | 31 | */ |
32 | if (has_not_enough_free_secs(sbi)) { | 32 | if (has_not_enough_free_secs(sbi)) { |
33 | mutex_lock(&sbi->gc_mutex); | 33 | mutex_lock(&sbi->gc_mutex); |
34 | f2fs_gc(sbi, 1); | 34 | f2fs_gc(sbi); |
35 | } | 35 | } |
36 | } | 36 | } |
37 | 37 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 08a94c814bdc..37fad04c8669 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -53,6 +53,18 @@ static match_table_t f2fs_tokens = { | |||
53 | {Opt_err, NULL}, | 53 | {Opt_err, NULL}, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) | ||
57 | { | ||
58 | struct va_format vaf; | ||
59 | va_list args; | ||
60 | |||
61 | va_start(args, fmt); | ||
62 | vaf.fmt = fmt; | ||
63 | vaf.va = &args; | ||
64 | printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); | ||
65 | va_end(args); | ||
66 | } | ||
67 | |||
56 | static void init_once(void *foo) | 68 | static void init_once(void *foo) |
57 | { | 69 | { |
58 | struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; | 70 | struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; |
@@ -125,6 +137,8 @@ int f2fs_sync_fs(struct super_block *sb, int sync) | |||
125 | 137 | ||
126 | if (sync) | 138 | if (sync) |
127 | write_checkpoint(sbi, false, false); | 139 | write_checkpoint(sbi, false, false); |
140 | else | ||
141 | f2fs_balance_fs(sbi); | ||
128 | 142 | ||
129 | return 0; | 143 | return 0; |
130 | } | 144 | } |
@@ -247,7 +261,8 @@ static const struct export_operations f2fs_export_ops = { | |||
247 | .get_parent = f2fs_get_parent, | 261 | .get_parent = f2fs_get_parent, |
248 | }; | 262 | }; |
249 | 263 | ||
250 | static int parse_options(struct f2fs_sb_info *sbi, char *options) | 264 | static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi, |
265 | char *options) | ||
251 | { | 266 | { |
252 | substring_t args[MAX_OPT_ARGS]; | 267 | substring_t args[MAX_OPT_ARGS]; |
253 | char *p; | 268 | char *p; |
@@ -286,7 +301,8 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
286 | break; | 301 | break; |
287 | #else | 302 | #else |
288 | case Opt_nouser_xattr: | 303 | case Opt_nouser_xattr: |
289 | pr_info("nouser_xattr options not supported\n"); | 304 | f2fs_msg(sb, KERN_INFO, |
305 | "nouser_xattr options not supported"); | ||
290 | break; | 306 | break; |
291 | #endif | 307 | #endif |
292 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 308 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
@@ -295,7 +311,7 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
295 | break; | 311 | break; |
296 | #else | 312 | #else |
297 | case Opt_noacl: | 313 | case Opt_noacl: |
298 | pr_info("noacl options not supported\n"); | 314 | f2fs_msg(sb, KERN_INFO, "noacl options not supported"); |
299 | break; | 315 | break; |
300 | #endif | 316 | #endif |
301 | case Opt_active_logs: | 317 | case Opt_active_logs: |
@@ -309,8 +325,9 @@ static int parse_options(struct f2fs_sb_info *sbi, char *options) | |||
309 | set_opt(sbi, DISABLE_EXT_IDENTIFY); | 325 | set_opt(sbi, DISABLE_EXT_IDENTIFY); |
310 | break; | 326 | break; |
311 | default: | 327 | default: |
312 | pr_err("Unrecognized mount option \"%s\" or missing value\n", | 328 | f2fs_msg(sb, KERN_ERR, |
313 | p); | 329 | "Unrecognized mount option \"%s\" or missing value", |
330 | p); | ||
314 | return -EINVAL; | 331 | return -EINVAL; |
315 | } | 332 | } |
316 | } | 333 | } |
@@ -337,23 +354,36 @@ static loff_t max_file_size(unsigned bits) | |||
337 | return result; | 354 | return result; |
338 | } | 355 | } |
339 | 356 | ||
340 | static int sanity_check_raw_super(struct f2fs_super_block *raw_super) | 357 | static int sanity_check_raw_super(struct super_block *sb, |
358 | struct f2fs_super_block *raw_super) | ||
341 | { | 359 | { |
342 | unsigned int blocksize; | 360 | unsigned int blocksize; |
343 | 361 | ||
344 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) | 362 | if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { |
363 | f2fs_msg(sb, KERN_INFO, | ||
364 | "Magic Mismatch, valid(0x%x) - read(0x%x)", | ||
365 | F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); | ||
345 | return 1; | 366 | return 1; |
367 | } | ||
346 | 368 | ||
347 | /* Currently, support only 4KB block size */ | 369 | /* Currently, support only 4KB block size */ |
348 | blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); | 370 | blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); |
349 | if (blocksize != PAGE_CACHE_SIZE) | 371 | if (blocksize != PAGE_CACHE_SIZE) { |
372 | f2fs_msg(sb, KERN_INFO, | ||
373 | "Invalid blocksize (%u), supports only 4KB\n", | ||
374 | blocksize); | ||
350 | return 1; | 375 | return 1; |
376 | } | ||
351 | if (le32_to_cpu(raw_super->log_sectorsize) != | 377 | if (le32_to_cpu(raw_super->log_sectorsize) != |
352 | F2FS_LOG_SECTOR_SIZE) | 378 | F2FS_LOG_SECTOR_SIZE) { |
379 | f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize"); | ||
353 | return 1; | 380 | return 1; |
381 | } | ||
354 | if (le32_to_cpu(raw_super->log_sectors_per_block) != | 382 | if (le32_to_cpu(raw_super->log_sectors_per_block) != |
355 | F2FS_LOG_SECTORS_PER_BLOCK) | 383 | F2FS_LOG_SECTORS_PER_BLOCK) { |
384 | f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block"); | ||
356 | return 1; | 385 | return 1; |
386 | } | ||
357 | return 0; | 387 | return 0; |
358 | } | 388 | } |
359 | 389 | ||
@@ -413,14 +443,17 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
413 | if (!sbi) | 443 | if (!sbi) |
414 | return -ENOMEM; | 444 | return -ENOMEM; |
415 | 445 | ||
416 | /* set a temporary block size */ | 446 | /* set a block size */ |
417 | if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) | 447 | if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) { |
448 | f2fs_msg(sb, KERN_ERR, "unable to set blocksize"); | ||
418 | goto free_sbi; | 449 | goto free_sbi; |
450 | } | ||
419 | 451 | ||
420 | /* read f2fs raw super block */ | 452 | /* read f2fs raw super block */ |
421 | raw_super_buf = sb_bread(sb, 0); | 453 | raw_super_buf = sb_bread(sb, 0); |
422 | if (!raw_super_buf) { | 454 | if (!raw_super_buf) { |
423 | err = -EIO; | 455 | err = -EIO; |
456 | f2fs_msg(sb, KERN_ERR, "unable to read superblock"); | ||
424 | goto free_sbi; | 457 | goto free_sbi; |
425 | } | 458 | } |
426 | raw_super = (struct f2fs_super_block *) | 459 | raw_super = (struct f2fs_super_block *) |
@@ -438,12 +471,14 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
438 | set_opt(sbi, POSIX_ACL); | 471 | set_opt(sbi, POSIX_ACL); |
439 | #endif | 472 | #endif |
440 | /* parse mount options */ | 473 | /* parse mount options */ |
441 | if (parse_options(sbi, (char *)data)) | 474 | if (parse_options(sb, sbi, (char *)data)) |
442 | goto free_sb_buf; | 475 | goto free_sb_buf; |
443 | 476 | ||
444 | /* sanity checking of raw super */ | 477 | /* sanity checking of raw super */ |
445 | if (sanity_check_raw_super(raw_super)) | 478 | if (sanity_check_raw_super(sb, raw_super)) { |
479 | f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem"); | ||
446 | goto free_sb_buf; | 480 | goto free_sb_buf; |
481 | } | ||
447 | 482 | ||
448 | sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); | 483 | sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); |
449 | sb->s_max_links = F2FS_LINK_MAX; | 484 | sb->s_max_links = F2FS_LINK_MAX; |
@@ -477,18 +512,23 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
477 | /* get an inode for meta space */ | 512 | /* get an inode for meta space */ |
478 | sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); | 513 | sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); |
479 | if (IS_ERR(sbi->meta_inode)) { | 514 | if (IS_ERR(sbi->meta_inode)) { |
515 | f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode"); | ||
480 | err = PTR_ERR(sbi->meta_inode); | 516 | err = PTR_ERR(sbi->meta_inode); |
481 | goto free_sb_buf; | 517 | goto free_sb_buf; |
482 | } | 518 | } |
483 | 519 | ||
484 | err = get_valid_checkpoint(sbi); | 520 | err = get_valid_checkpoint(sbi); |
485 | if (err) | 521 | if (err) { |
522 | f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint"); | ||
486 | goto free_meta_inode; | 523 | goto free_meta_inode; |
524 | } | ||
487 | 525 | ||
488 | /* sanity checking of checkpoint */ | 526 | /* sanity checking of checkpoint */ |
489 | err = -EINVAL; | 527 | err = -EINVAL; |
490 | if (sanity_check_ckpt(raw_super, sbi->ckpt)) | 528 | if (sanity_check_ckpt(raw_super, sbi->ckpt)) { |
529 | f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); | ||
491 | goto free_cp; | 530 | goto free_cp; |
531 | } | ||
492 | 532 | ||
493 | sbi->total_valid_node_count = | 533 | sbi->total_valid_node_count = |
494 | le32_to_cpu(sbi->ckpt->valid_node_count); | 534 | le32_to_cpu(sbi->ckpt->valid_node_count); |
@@ -502,25 +542,28 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
502 | INIT_LIST_HEAD(&sbi->dir_inode_list); | 542 | INIT_LIST_HEAD(&sbi->dir_inode_list); |
503 | spin_lock_init(&sbi->dir_inode_lock); | 543 | spin_lock_init(&sbi->dir_inode_lock); |
504 | 544 | ||
505 | /* init super block */ | ||
506 | if (!sb_set_blocksize(sb, sbi->blocksize)) | ||
507 | goto free_cp; | ||
508 | |||
509 | init_orphan_info(sbi); | 545 | init_orphan_info(sbi); |
510 | 546 | ||
511 | /* setup f2fs internal modules */ | 547 | /* setup f2fs internal modules */ |
512 | err = build_segment_manager(sbi); | 548 | err = build_segment_manager(sbi); |
513 | if (err) | 549 | if (err) { |
550 | f2fs_msg(sb, KERN_ERR, | ||
551 | "Failed to initialize F2FS segment manager"); | ||
514 | goto free_sm; | 552 | goto free_sm; |
553 | } | ||
515 | err = build_node_manager(sbi); | 554 | err = build_node_manager(sbi); |
516 | if (err) | 555 | if (err) { |
556 | f2fs_msg(sb, KERN_ERR, | ||
557 | "Failed to initialize F2FS node manager"); | ||
517 | goto free_nm; | 558 | goto free_nm; |
559 | } | ||
518 | 560 | ||
519 | build_gc_manager(sbi); | 561 | build_gc_manager(sbi); |
520 | 562 | ||
521 | /* get an inode for node space */ | 563 | /* get an inode for node space */ |
522 | sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); | 564 | sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); |
523 | if (IS_ERR(sbi->node_inode)) { | 565 | if (IS_ERR(sbi->node_inode)) { |
566 | f2fs_msg(sb, KERN_ERR, "Failed to read node inode"); | ||
524 | err = PTR_ERR(sbi->node_inode); | 567 | err = PTR_ERR(sbi->node_inode); |
525 | goto free_nm; | 568 | goto free_nm; |
526 | } | 569 | } |
@@ -533,6 +576,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
533 | /* read root inode and dentry */ | 576 | /* read root inode and dentry */ |
534 | root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); | 577 | root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); |
535 | if (IS_ERR(root)) { | 578 | if (IS_ERR(root)) { |
579 | f2fs_msg(sb, KERN_ERR, "Failed to read root inode"); | ||
536 | err = PTR_ERR(root); | 580 | err = PTR_ERR(root); |
537 | goto free_node_inode; | 581 | goto free_node_inode; |
538 | } | 582 | } |
@@ -596,7 +640,7 @@ static struct file_system_type f2fs_fs_type = { | |||
596 | .fs_flags = FS_REQUIRES_DEV, | 640 | .fs_flags = FS_REQUIRES_DEV, |
597 | }; | 641 | }; |
598 | 642 | ||
599 | static int init_inodecache(void) | 643 | static int __init init_inodecache(void) |
600 | { | 644 | { |
601 | f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", | 645 | f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", |
602 | sizeof(struct f2fs_inode_info), NULL); | 646 | sizeof(struct f2fs_inode_info), NULL); |
@@ -631,14 +675,17 @@ static int __init init_f2fs_fs(void) | |||
631 | err = create_checkpoint_caches(); | 675 | err = create_checkpoint_caches(); |
632 | if (err) | 676 | if (err) |
633 | goto fail; | 677 | goto fail; |
634 | return register_filesystem(&f2fs_fs_type); | 678 | err = register_filesystem(&f2fs_fs_type); |
679 | if (err) | ||
680 | goto fail; | ||
681 | f2fs_create_root_stats(); | ||
635 | fail: | 682 | fail: |
636 | return err; | 683 | return err; |
637 | } | 684 | } |
638 | 685 | ||
639 | static void __exit exit_f2fs_fs(void) | 686 | static void __exit exit_f2fs_fs(void) |
640 | { | 687 | { |
641 | destroy_root_stats(); | 688 | f2fs_destroy_root_stats(); |
642 | unregister_filesystem(&f2fs_fs_type); | 689 | unregister_filesystem(&f2fs_fs_type); |
643 | destroy_checkpoint_caches(); | 690 | destroy_checkpoint_caches(); |
644 | destroy_gc_caches(); | 691 | destroy_gc_caches(); |
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 940136a3d3a6..8038c0496504 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -318,6 +318,8 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
318 | if (name_len > 255 || value_len > MAX_VALUE_LEN) | 318 | if (name_len > 255 || value_len > MAX_VALUE_LEN) |
319 | return -ERANGE; | 319 | return -ERANGE; |
320 | 320 | ||
321 | f2fs_balance_fs(sbi); | ||
322 | |||
321 | mutex_lock_op(sbi, NODE_NEW); | 323 | mutex_lock_op(sbi, NODE_NEW); |
322 | if (!fi->i_xattr_nid) { | 324 | if (!fi->i_xattr_nid) { |
323 | /* Allocate new attribute block */ | 325 | /* Allocate new attribute block */ |
diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig index 0cf160a94eda..1b2f6c2c3aaf 100644 --- a/fs/fuse/Kconfig +++ b/fs/fuse/Kconfig | |||
@@ -4,12 +4,24 @@ config FUSE_FS | |||
4 | With FUSE it is possible to implement a fully functional filesystem | 4 | With FUSE it is possible to implement a fully functional filesystem |
5 | in a userspace program. | 5 | in a userspace program. |
6 | 6 | ||
7 | There's also companion library: libfuse. This library along with | 7 | There's also a companion library: libfuse2. This library is available |
8 | utilities is available from the FUSE homepage: | 8 | from the FUSE homepage: |
9 | <http://fuse.sourceforge.net/> | 9 | <http://fuse.sourceforge.net/> |
10 | although chances are your distribution already has that library | ||
11 | installed if you've installed the "fuse" package itself. | ||
10 | 12 | ||
11 | See <file:Documentation/filesystems/fuse.txt> for more information. | 13 | See <file:Documentation/filesystems/fuse.txt> for more information. |
12 | See <file:Documentation/Changes> for needed library/utility version. | 14 | See <file:Documentation/Changes> for needed library/utility version. |
13 | 15 | ||
14 | If you want to develop a userspace FS, or if you want to use | 16 | If you want to develop a userspace FS, or if you want to use |
15 | a filesystem based on FUSE, answer Y or M. | 17 | a filesystem based on FUSE, answer Y or M. |
18 | |||
19 | config CUSE | ||
20 | tristate "Character device in Userspace support" | ||
21 | depends on FUSE_FS | ||
22 | help | ||
23 | This FUSE extension allows character devices to be | ||
24 | implemented in userspace. | ||
25 | |||
26 | If you want to develop or use a userspace character device | ||
27 | based on CUSE, answer Y or M. | ||
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index ee8d55042298..e397b675b029 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <linux/miscdevice.h> | 45 | #include <linux/miscdevice.h> |
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/stat.h> | 48 | #include <linux/stat.h> |
50 | #include <linux/module.h> | 49 | #include <linux/module.h> |
51 | 50 | ||
@@ -63,7 +62,7 @@ struct cuse_conn { | |||
63 | bool unrestricted_ioctl; | 62 | bool unrestricted_ioctl; |
64 | }; | 63 | }; |
65 | 64 | ||
66 | static DEFINE_SPINLOCK(cuse_lock); /* protects cuse_conntbl */ | 65 | static DEFINE_MUTEX(cuse_lock); /* protects registration */ |
67 | static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; | 66 | static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN]; |
68 | static struct class *cuse_class; | 67 | static struct class *cuse_class; |
69 | 68 | ||
@@ -114,14 +113,14 @@ static int cuse_open(struct inode *inode, struct file *file) | |||
114 | int rc; | 113 | int rc; |
115 | 114 | ||
116 | /* look up and get the connection */ | 115 | /* look up and get the connection */ |
117 | spin_lock(&cuse_lock); | 116 | mutex_lock(&cuse_lock); |
118 | list_for_each_entry(pos, cuse_conntbl_head(devt), list) | 117 | list_for_each_entry(pos, cuse_conntbl_head(devt), list) |
119 | if (pos->dev->devt == devt) { | 118 | if (pos->dev->devt == devt) { |
120 | fuse_conn_get(&pos->fc); | 119 | fuse_conn_get(&pos->fc); |
121 | cc = pos; | 120 | cc = pos; |
122 | break; | 121 | break; |
123 | } | 122 | } |
124 | spin_unlock(&cuse_lock); | 123 | mutex_unlock(&cuse_lock); |
125 | 124 | ||
126 | /* dead? */ | 125 | /* dead? */ |
127 | if (!cc) | 126 | if (!cc) |
@@ -267,7 +266,7 @@ static int cuse_parse_one(char **pp, char *end, char **keyp, char **valp) | |||
267 | static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) | 266 | static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo) |
268 | { | 267 | { |
269 | char *end = p + len; | 268 | char *end = p + len; |
270 | char *key, *val; | 269 | char *uninitialized_var(key), *uninitialized_var(val); |
271 | int rc; | 270 | int rc; |
272 | 271 | ||
273 | while (true) { | 272 | while (true) { |
@@ -305,14 +304,14 @@ static void cuse_gendev_release(struct device *dev) | |||
305 | */ | 304 | */ |
306 | static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | 305 | static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) |
307 | { | 306 | { |
308 | struct cuse_conn *cc = fc_to_cc(fc); | 307 | struct cuse_conn *cc = fc_to_cc(fc), *pos; |
309 | struct cuse_init_out *arg = req->out.args[0].value; | 308 | struct cuse_init_out *arg = req->out.args[0].value; |
310 | struct page *page = req->pages[0]; | 309 | struct page *page = req->pages[0]; |
311 | struct cuse_devinfo devinfo = { }; | 310 | struct cuse_devinfo devinfo = { }; |
312 | struct device *dev; | 311 | struct device *dev; |
313 | struct cdev *cdev; | 312 | struct cdev *cdev; |
314 | dev_t devt; | 313 | dev_t devt; |
315 | int rc; | 314 | int rc, i; |
316 | 315 | ||
317 | if (req->out.h.error || | 316 | if (req->out.h.error || |
318 | arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { | 317 | arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) { |
@@ -356,15 +355,24 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
356 | dev_set_drvdata(dev, cc); | 355 | dev_set_drvdata(dev, cc); |
357 | dev_set_name(dev, "%s", devinfo.name); | 356 | dev_set_name(dev, "%s", devinfo.name); |
358 | 357 | ||
358 | mutex_lock(&cuse_lock); | ||
359 | |||
360 | /* make sure the device-name is unique */ | ||
361 | for (i = 0; i < CUSE_CONNTBL_LEN; ++i) { | ||
362 | list_for_each_entry(pos, &cuse_conntbl[i], list) | ||
363 | if (!strcmp(dev_name(pos->dev), dev_name(dev))) | ||
364 | goto err_unlock; | ||
365 | } | ||
366 | |||
359 | rc = device_add(dev); | 367 | rc = device_add(dev); |
360 | if (rc) | 368 | if (rc) |
361 | goto err_device; | 369 | goto err_unlock; |
362 | 370 | ||
363 | /* register cdev */ | 371 | /* register cdev */ |
364 | rc = -ENOMEM; | 372 | rc = -ENOMEM; |
365 | cdev = cdev_alloc(); | 373 | cdev = cdev_alloc(); |
366 | if (!cdev) | 374 | if (!cdev) |
367 | goto err_device; | 375 | goto err_unlock; |
368 | 376 | ||
369 | cdev->owner = THIS_MODULE; | 377 | cdev->owner = THIS_MODULE; |
370 | cdev->ops = &cuse_frontend_fops; | 378 | cdev->ops = &cuse_frontend_fops; |
@@ -377,9 +385,8 @@ static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
377 | cc->cdev = cdev; | 385 | cc->cdev = cdev; |
378 | 386 | ||
379 | /* make the device available */ | 387 | /* make the device available */ |
380 | spin_lock(&cuse_lock); | ||
381 | list_add(&cc->list, cuse_conntbl_head(devt)); | 388 | list_add(&cc->list, cuse_conntbl_head(devt)); |
382 | spin_unlock(&cuse_lock); | 389 | mutex_unlock(&cuse_lock); |
383 | 390 | ||
384 | /* announce device availability */ | 391 | /* announce device availability */ |
385 | dev_set_uevent_suppress(dev, 0); | 392 | dev_set_uevent_suppress(dev, 0); |
@@ -391,7 +398,8 @@ out: | |||
391 | 398 | ||
392 | err_cdev: | 399 | err_cdev: |
393 | cdev_del(cdev); | 400 | cdev_del(cdev); |
394 | err_device: | 401 | err_unlock: |
402 | mutex_unlock(&cuse_lock); | ||
395 | put_device(dev); | 403 | put_device(dev); |
396 | err_region: | 404 | err_region: |
397 | unregister_chrdev_region(devt, 1); | 405 | unregister_chrdev_region(devt, 1); |
@@ -520,9 +528,9 @@ static int cuse_channel_release(struct inode *inode, struct file *file) | |||
520 | int rc; | 528 | int rc; |
521 | 529 | ||
522 | /* remove from the conntbl, no more access from this point on */ | 530 | /* remove from the conntbl, no more access from this point on */ |
523 | spin_lock(&cuse_lock); | 531 | mutex_lock(&cuse_lock); |
524 | list_del_init(&cc->list); | 532 | list_del_init(&cc->list); |
525 | spin_unlock(&cuse_lock); | 533 | mutex_unlock(&cuse_lock); |
526 | 534 | ||
527 | /* remove device */ | 535 | /* remove device */ |
528 | if (cc->dev) | 536 | if (cc->dev) |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c16335315e5d..e83351aa5bad 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -692,8 +692,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
692 | struct page *oldpage = *pagep; | 692 | struct page *oldpage = *pagep; |
693 | struct page *newpage; | 693 | struct page *newpage; |
694 | struct pipe_buffer *buf = cs->pipebufs; | 694 | struct pipe_buffer *buf = cs->pipebufs; |
695 | struct address_space *mapping; | ||
696 | pgoff_t index; | ||
697 | 695 | ||
698 | unlock_request(cs->fc, cs->req); | 696 | unlock_request(cs->fc, cs->req); |
699 | fuse_copy_finish(cs); | 697 | fuse_copy_finish(cs); |
@@ -724,9 +722,6 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) | |||
724 | if (fuse_check_page(newpage) != 0) | 722 | if (fuse_check_page(newpage) != 0) |
725 | goto out_fallback_unlock; | 723 | goto out_fallback_unlock; |
726 | 724 | ||
727 | mapping = oldpage->mapping; | ||
728 | index = oldpage->index; | ||
729 | |||
730 | /* | 725 | /* |
731 | * This is a new and locked page, it shouldn't be mapped or | 726 | * This is a new and locked page, it shouldn't be mapped or |
732 | * have any special flags on it | 727 | * have any special flags on it |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index e21d4d8f87e3..f3ab824fa302 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -2177,8 +2177,8 @@ fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | |||
2177 | return ret; | 2177 | return ret; |
2178 | } | 2178 | } |
2179 | 2179 | ||
2180 | long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | 2180 | static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, |
2181 | loff_t length) | 2181 | loff_t length) |
2182 | { | 2182 | { |
2183 | struct fuse_file *ff = file->private_data; | 2183 | struct fuse_file *ff = file->private_data; |
2184 | struct fuse_conn *fc = ff->fc; | 2184 | struct fuse_conn *fc = ff->fc; |
@@ -2213,7 +2213,6 @@ long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2213 | 2213 | ||
2214 | return err; | 2214 | return err; |
2215 | } | 2215 | } |
2216 | EXPORT_SYMBOL_GPL(fuse_file_fallocate); | ||
2217 | 2216 | ||
2218 | static const struct file_operations fuse_file_operations = { | 2217 | static const struct file_operations fuse_file_operations = { |
2219 | .llseek = fuse_file_llseek, | 2218 | .llseek = fuse_file_llseek, |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index a2862339323b..81cc7eaff863 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -446,7 +446,8 @@ int __log_start_commit(journal_t *journal, tid_t target) | |||
446 | * currently running transaction (if it exists). Otherwise, | 446 | * currently running transaction (if it exists). Otherwise, |
447 | * the target tid must be an old one. | 447 | * the target tid must be an old one. |
448 | */ | 448 | */ |
449 | if (journal->j_running_transaction && | 449 | if (journal->j_commit_request != target && |
450 | journal->j_running_transaction && | ||
450 | journal->j_running_transaction->t_tid == target) { | 451 | journal->j_running_transaction->t_tid == target) { |
451 | /* | 452 | /* |
452 | * We want a new commit: OK, mark the request and wakeup the | 453 | * We want a new commit: OK, mark the request and wakeup the |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 9d863fb501f9..f2bc3dfd0b88 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -296,7 +296,7 @@ EXPORT_SYMBOL(seq_read); | |||
296 | * seq_lseek - ->llseek() method for sequential files. | 296 | * seq_lseek - ->llseek() method for sequential files. |
297 | * @file: the file in question | 297 | * @file: the file in question |
298 | * @offset: new position | 298 | * @offset: new position |
299 | * @origin: 0 for absolute, 1 for relative position | 299 | * @whence: 0 for absolute, 1 for relative position |
300 | * | 300 | * |
301 | * Ready-made ->f_op->llseek() | 301 | * Ready-made ->f_op->llseek() |
302 | */ | 302 | */ |
diff --git a/fs/udf/super.c b/fs/udf/super.c index d44fb568abe1..e9be396a558d 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -307,7 +307,8 @@ static void udf_sb_free_partitions(struct super_block *sb) | |||
307 | { | 307 | { |
308 | struct udf_sb_info *sbi = UDF_SB(sb); | 308 | struct udf_sb_info *sbi = UDF_SB(sb); |
309 | int i; | 309 | int i; |
310 | 310 | if (sbi->s_partmaps == NULL) | |
311 | return; | ||
311 | for (i = 0; i < sbi->s_partitions; i++) | 312 | for (i = 0; i < sbi->s_partitions; i++) |
312 | udf_free_partition(&sbi->s_partmaps[i]); | 313 | udf_free_partition(&sbi->s_partmaps[i]); |
313 | kfree(sbi->s_partmaps); | 314 | kfree(sbi->s_partmaps); |
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 26673a0b20e7..56d1614760cf 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c | |||
@@ -175,7 +175,7 @@ xfs_buf_get_maps( | |||
175 | bp->b_map_count = map_count; | 175 | bp->b_map_count = map_count; |
176 | 176 | ||
177 | if (map_count == 1) { | 177 | if (map_count == 1) { |
178 | bp->b_maps = &bp->b_map; | 178 | bp->b_maps = &bp->__b_map; |
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
@@ -193,7 +193,7 @@ static void | |||
193 | xfs_buf_free_maps( | 193 | xfs_buf_free_maps( |
194 | struct xfs_buf *bp) | 194 | struct xfs_buf *bp) |
195 | { | 195 | { |
196 | if (bp->b_maps != &bp->b_map) { | 196 | if (bp->b_maps != &bp->__b_map) { |
197 | kmem_free(bp->b_maps); | 197 | kmem_free(bp->b_maps); |
198 | bp->b_maps = NULL; | 198 | bp->b_maps = NULL; |
199 | } | 199 | } |
@@ -377,8 +377,8 @@ xfs_buf_allocate_memory( | |||
377 | } | 377 | } |
378 | 378 | ||
379 | use_alloc_page: | 379 | use_alloc_page: |
380 | start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT; | 380 | start = BBTOB(bp->b_maps[0].bm_bn) >> PAGE_SHIFT; |
381 | end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1) | 381 | end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1) |
382 | >> PAGE_SHIFT; | 382 | >> PAGE_SHIFT; |
383 | page_count = end - start; | 383 | page_count = end - start; |
384 | error = _xfs_buf_get_pages(bp, page_count, flags); | 384 | error = _xfs_buf_get_pages(bp, page_count, flags); |
@@ -640,7 +640,7 @@ _xfs_buf_read( | |||
640 | xfs_buf_flags_t flags) | 640 | xfs_buf_flags_t flags) |
641 | { | 641 | { |
642 | ASSERT(!(flags & XBF_WRITE)); | 642 | ASSERT(!(flags & XBF_WRITE)); |
643 | ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL); | 643 | ASSERT(bp->b_maps[0].bm_bn != XFS_BUF_DADDR_NULL); |
644 | 644 | ||
645 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); | 645 | bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD); |
646 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); | 646 | bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD); |
@@ -1709,7 +1709,7 @@ xfs_buf_cmp( | |||
1709 | struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list); | 1709 | struct xfs_buf *bp = container_of(b, struct xfs_buf, b_list); |
1710 | xfs_daddr_t diff; | 1710 | xfs_daddr_t diff; |
1711 | 1711 | ||
1712 | diff = ap->b_map.bm_bn - bp->b_map.bm_bn; | 1712 | diff = ap->b_maps[0].bm_bn - bp->b_maps[0].bm_bn; |
1713 | if (diff < 0) | 1713 | if (diff < 0) |
1714 | return -1; | 1714 | return -1; |
1715 | if (diff > 0) | 1715 | if (diff > 0) |
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h index 23f5642480bb..433a12ed7b17 100644 --- a/fs/xfs/xfs_buf.h +++ b/fs/xfs/xfs_buf.h | |||
@@ -151,7 +151,7 @@ typedef struct xfs_buf { | |||
151 | struct page **b_pages; /* array of page pointers */ | 151 | struct page **b_pages; /* array of page pointers */ |
152 | struct page *b_page_array[XB_PAGES]; /* inline pages */ | 152 | struct page *b_page_array[XB_PAGES]; /* inline pages */ |
153 | struct xfs_buf_map *b_maps; /* compound buffer map */ | 153 | struct xfs_buf_map *b_maps; /* compound buffer map */ |
154 | struct xfs_buf_map b_map; /* inline compound buffer map */ | 154 | struct xfs_buf_map __b_map; /* inline compound buffer map */ |
155 | int b_map_count; | 155 | int b_map_count; |
156 | int b_io_length; /* IO size in BBs */ | 156 | int b_io_length; /* IO size in BBs */ |
157 | atomic_t b_pin_count; /* pin count */ | 157 | atomic_t b_pin_count; /* pin count */ |
@@ -330,8 +330,8 @@ void xfs_buf_stale(struct xfs_buf *bp); | |||
330 | * In future, uncached buffers will pass the block number directly to the io | 330 | * In future, uncached buffers will pass the block number directly to the io |
331 | * request function and hence these macros will go away at that point. | 331 | * request function and hence these macros will go away at that point. |
332 | */ | 332 | */ |
333 | #define XFS_BUF_ADDR(bp) ((bp)->b_map.bm_bn) | 333 | #define XFS_BUF_ADDR(bp) ((bp)->b_maps[0].bm_bn) |
334 | #define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_map.bm_bn = (xfs_daddr_t)(bno)) | 334 | #define XFS_BUF_SET_ADDR(bp, bno) ((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno)) |
335 | 335 | ||
336 | static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) | 336 | static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref) |
337 | { | 337 | { |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index becf4a97efc6..77b09750e92c 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -71,7 +71,7 @@ xfs_buf_item_log_debug( | |||
71 | chunk_num = byte >> XFS_BLF_SHIFT; | 71 | chunk_num = byte >> XFS_BLF_SHIFT; |
72 | word_num = chunk_num >> BIT_TO_WORD_SHIFT; | 72 | word_num = chunk_num >> BIT_TO_WORD_SHIFT; |
73 | bit_num = chunk_num & (NBWORD - 1); | 73 | bit_num = chunk_num & (NBWORD - 1); |
74 | wordp = &(bip->bli_format.blf_data_map[word_num]); | 74 | wordp = &(bip->__bli_format.blf_data_map[word_num]); |
75 | bit_set = *wordp & (1 << bit_num); | 75 | bit_set = *wordp & (1 << bit_num); |
76 | ASSERT(bit_set); | 76 | ASSERT(bit_set); |
77 | byte++; | 77 | byte++; |
@@ -237,7 +237,7 @@ xfs_buf_item_size( | |||
237 | * cancel flag in it. | 237 | * cancel flag in it. |
238 | */ | 238 | */ |
239 | trace_xfs_buf_item_size_stale(bip); | 239 | trace_xfs_buf_item_size_stale(bip); |
240 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 240 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
241 | return bip->bli_format_count; | 241 | return bip->bli_format_count; |
242 | } | 242 | } |
243 | 243 | ||
@@ -278,7 +278,7 @@ xfs_buf_item_format_segment( | |||
278 | uint buffer_offset; | 278 | uint buffer_offset; |
279 | 279 | ||
280 | /* copy the flags across from the base format item */ | 280 | /* copy the flags across from the base format item */ |
281 | blfp->blf_flags = bip->bli_format.blf_flags; | 281 | blfp->blf_flags = bip->__bli_format.blf_flags; |
282 | 282 | ||
283 | /* | 283 | /* |
284 | * Base size is the actual size of the ondisk structure - it reflects | 284 | * Base size is the actual size of the ondisk structure - it reflects |
@@ -287,6 +287,17 @@ xfs_buf_item_format_segment( | |||
287 | */ | 287 | */ |
288 | base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + | 288 | base_size = offsetof(struct xfs_buf_log_format, blf_data_map) + |
289 | (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); | 289 | (blfp->blf_map_size * sizeof(blfp->blf_data_map[0])); |
290 | |||
291 | nvecs = 0; | ||
292 | first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); | ||
293 | if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) { | ||
294 | /* | ||
295 | * If the map is not be dirty in the transaction, mark | ||
296 | * the size as zero and do not advance the vector pointer. | ||
297 | */ | ||
298 | goto out; | ||
299 | } | ||
300 | |||
290 | vecp->i_addr = blfp; | 301 | vecp->i_addr = blfp; |
291 | vecp->i_len = base_size; | 302 | vecp->i_len = base_size; |
292 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; | 303 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; |
@@ -301,15 +312,13 @@ xfs_buf_item_format_segment( | |||
301 | */ | 312 | */ |
302 | trace_xfs_buf_item_format_stale(bip); | 313 | trace_xfs_buf_item_format_stale(bip); |
303 | ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); | 314 | ASSERT(blfp->blf_flags & XFS_BLF_CANCEL); |
304 | blfp->blf_size = nvecs; | 315 | goto out; |
305 | return vecp; | ||
306 | } | 316 | } |
307 | 317 | ||
308 | /* | 318 | /* |
309 | * Fill in an iovec for each set of contiguous chunks. | 319 | * Fill in an iovec for each set of contiguous chunks. |
310 | */ | 320 | */ |
311 | first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0); | 321 | |
312 | ASSERT(first_bit != -1); | ||
313 | last_bit = first_bit; | 322 | last_bit = first_bit; |
314 | nbits = 1; | 323 | nbits = 1; |
315 | for (;;) { | 324 | for (;;) { |
@@ -371,7 +380,8 @@ xfs_buf_item_format_segment( | |||
371 | nbits++; | 380 | nbits++; |
372 | } | 381 | } |
373 | } | 382 | } |
374 | bip->bli_format.blf_size = nvecs; | 383 | out: |
384 | blfp->blf_size = nvecs; | ||
375 | return vecp; | 385 | return vecp; |
376 | } | 386 | } |
377 | 387 | ||
@@ -405,7 +415,7 @@ xfs_buf_item_format( | |||
405 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { | 415 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { |
406 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 416 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && |
407 | xfs_log_item_in_current_chkpt(lip))) | 417 | xfs_log_item_in_current_chkpt(lip))) |
408 | bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; | 418 | bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF; |
409 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 419 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
410 | } | 420 | } |
411 | 421 | ||
@@ -485,7 +495,7 @@ xfs_buf_item_unpin( | |||
485 | ASSERT(bip->bli_flags & XFS_BLI_STALE); | 495 | ASSERT(bip->bli_flags & XFS_BLI_STALE); |
486 | ASSERT(xfs_buf_islocked(bp)); | 496 | ASSERT(xfs_buf_islocked(bp)); |
487 | ASSERT(XFS_BUF_ISSTALE(bp)); | 497 | ASSERT(XFS_BUF_ISSTALE(bp)); |
488 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 498 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
489 | 499 | ||
490 | trace_xfs_buf_item_unpin_stale(bip); | 500 | trace_xfs_buf_item_unpin_stale(bip); |
491 | 501 | ||
@@ -601,7 +611,7 @@ xfs_buf_item_unlock( | |||
601 | { | 611 | { |
602 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | 612 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
603 | struct xfs_buf *bp = bip->bli_buf; | 613 | struct xfs_buf *bp = bip->bli_buf; |
604 | int aborted; | 614 | int aborted, clean, i; |
605 | uint hold; | 615 | uint hold; |
606 | 616 | ||
607 | /* Clear the buffer's association with this transaction. */ | 617 | /* Clear the buffer's association with this transaction. */ |
@@ -631,7 +641,7 @@ xfs_buf_item_unlock( | |||
631 | */ | 641 | */ |
632 | if (bip->bli_flags & XFS_BLI_STALE) { | 642 | if (bip->bli_flags & XFS_BLI_STALE) { |
633 | trace_xfs_buf_item_unlock_stale(bip); | 643 | trace_xfs_buf_item_unlock_stale(bip); |
634 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 644 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
635 | if (!aborted) { | 645 | if (!aborted) { |
636 | atomic_dec(&bip->bli_refcount); | 646 | atomic_dec(&bip->bli_refcount); |
637 | return; | 647 | return; |
@@ -644,8 +654,15 @@ xfs_buf_item_unlock( | |||
644 | * If the buf item isn't tracking any data, free it, otherwise drop the | 654 | * If the buf item isn't tracking any data, free it, otherwise drop the |
645 | * reference we hold to it. | 655 | * reference we hold to it. |
646 | */ | 656 | */ |
647 | if (xfs_bitmap_empty(bip->bli_format.blf_data_map, | 657 | clean = 1; |
648 | bip->bli_format.blf_map_size)) | 658 | for (i = 0; i < bip->bli_format_count; i++) { |
659 | if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map, | ||
660 | bip->bli_formats[i].blf_map_size)) { | ||
661 | clean = 0; | ||
662 | break; | ||
663 | } | ||
664 | } | ||
665 | if (clean) | ||
649 | xfs_buf_item_relse(bp); | 666 | xfs_buf_item_relse(bp); |
650 | else | 667 | else |
651 | atomic_dec(&bip->bli_refcount); | 668 | atomic_dec(&bip->bli_refcount); |
@@ -716,7 +733,7 @@ xfs_buf_item_get_format( | |||
716 | bip->bli_format_count = count; | 733 | bip->bli_format_count = count; |
717 | 734 | ||
718 | if (count == 1) { | 735 | if (count == 1) { |
719 | bip->bli_formats = &bip->bli_format; | 736 | bip->bli_formats = &bip->__bli_format; |
720 | return 0; | 737 | return 0; |
721 | } | 738 | } |
722 | 739 | ||
@@ -731,7 +748,7 @@ STATIC void | |||
731 | xfs_buf_item_free_format( | 748 | xfs_buf_item_free_format( |
732 | struct xfs_buf_log_item *bip) | 749 | struct xfs_buf_log_item *bip) |
733 | { | 750 | { |
734 | if (bip->bli_formats != &bip->bli_format) { | 751 | if (bip->bli_formats != &bip->__bli_format) { |
735 | kmem_free(bip->bli_formats); | 752 | kmem_free(bip->bli_formats); |
736 | bip->bli_formats = NULL; | 753 | bip->bli_formats = NULL; |
737 | } | 754 | } |
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 6850f49f4af3..16def435944a 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -104,7 +104,7 @@ typedef struct xfs_buf_log_item { | |||
104 | #endif | 104 | #endif |
105 | int bli_format_count; /* count of headers */ | 105 | int bli_format_count; /* count of headers */ |
106 | struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */ | 106 | struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */ |
107 | struct xfs_buf_log_format bli_format; /* embedded in-log header */ | 107 | struct xfs_buf_log_format __bli_format; /* embedded in-log header */ |
108 | } xfs_buf_log_item_t; | 108 | } xfs_buf_log_item_t; |
109 | 109 | ||
110 | void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); | 110 | void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 7536faaa61e7..12afe07a91d7 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -355,10 +355,12 @@ xfs_dir2_block_addname( | |||
355 | /* | 355 | /* |
356 | * If need to compact the leaf entries, do it now. | 356 | * If need to compact the leaf entries, do it now. |
357 | */ | 357 | */ |
358 | if (compact) | 358 | if (compact) { |
359 | xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog, | 359 | xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog, |
360 | &lfloghigh, &lfloglow); | 360 | &lfloghigh, &lfloglow); |
361 | else if (btp->stale) { | 361 | /* recalculate blp post-compaction */ |
362 | blp = xfs_dir2_block_leaf_p(btp); | ||
363 | } else if (btp->stale) { | ||
362 | /* | 364 | /* |
363 | * Set leaf logging boundaries to impossible state. | 365 | * Set leaf logging boundaries to impossible state. |
364 | * For the no-stale case they're set explicitly. | 366 | * For the no-stale case they're set explicitly. |
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index 5f53e75409b8..8a59f8546552 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c | |||
@@ -784,11 +784,11 @@ xfs_qm_scall_getquota( | |||
784 | (XFS_IS_OQUOTA_ENFORCED(mp) && | 784 | (XFS_IS_OQUOTA_ENFORCED(mp) && |
785 | (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) && | 785 | (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) && |
786 | dst->d_id != 0) { | 786 | dst->d_id != 0) { |
787 | if (((int) dst->d_bcount > (int) dst->d_blk_softlimit) && | 787 | if ((dst->d_bcount > dst->d_blk_softlimit) && |
788 | (dst->d_blk_softlimit > 0)) { | 788 | (dst->d_blk_softlimit > 0)) { |
789 | ASSERT(dst->d_btimer != 0); | 789 | ASSERT(dst->d_btimer != 0); |
790 | } | 790 | } |
791 | if (((int) dst->d_icount > (int) dst->d_ino_softlimit) && | 791 | if ((dst->d_icount > dst->d_ino_softlimit) && |
792 | (dst->d_ino_softlimit > 0)) { | 792 | (dst->d_ino_softlimit > 0)) { |
793 | ASSERT(dst->d_itimer != 0); | 793 | ASSERT(dst->d_itimer != 0); |
794 | } | 794 | } |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 4fc17d479d42..3edf5dbee001 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -93,7 +93,7 @@ _xfs_trans_bjoin( | |||
93 | xfs_buf_item_init(bp, tp->t_mountp); | 93 | xfs_buf_item_init(bp, tp->t_mountp); |
94 | bip = bp->b_fspriv; | 94 | bip = bp->b_fspriv; |
95 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 95 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
96 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); | 96 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); |
97 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); | 97 | ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); |
98 | if (reset_recur) | 98 | if (reset_recur) |
99 | bip->bli_recur = 0; | 99 | bip->bli_recur = 0; |
@@ -432,7 +432,7 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
432 | bip = bp->b_fspriv; | 432 | bip = bp->b_fspriv; |
433 | ASSERT(bip->bli_item.li_type == XFS_LI_BUF); | 433 | ASSERT(bip->bli_item.li_type == XFS_LI_BUF); |
434 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 434 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
435 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); | 435 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); |
436 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 436 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
437 | 437 | ||
438 | trace_xfs_trans_brelse(bip); | 438 | trace_xfs_trans_brelse(bip); |
@@ -519,7 +519,7 @@ xfs_trans_bhold(xfs_trans_t *tp, | |||
519 | ASSERT(bp->b_transp == tp); | 519 | ASSERT(bp->b_transp == tp); |
520 | ASSERT(bip != NULL); | 520 | ASSERT(bip != NULL); |
521 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 521 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
522 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); | 522 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); |
523 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 523 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
524 | 524 | ||
525 | bip->bli_flags |= XFS_BLI_HOLD; | 525 | bip->bli_flags |= XFS_BLI_HOLD; |
@@ -539,7 +539,7 @@ xfs_trans_bhold_release(xfs_trans_t *tp, | |||
539 | ASSERT(bp->b_transp == tp); | 539 | ASSERT(bp->b_transp == tp); |
540 | ASSERT(bip != NULL); | 540 | ASSERT(bip != NULL); |
541 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 541 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
542 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); | 542 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); |
543 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 543 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
544 | ASSERT(bip->bli_flags & XFS_BLI_HOLD); | 544 | ASSERT(bip->bli_flags & XFS_BLI_HOLD); |
545 | 545 | ||
@@ -598,7 +598,7 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
598 | bip->bli_flags &= ~XFS_BLI_STALE; | 598 | bip->bli_flags &= ~XFS_BLI_STALE; |
599 | ASSERT(XFS_BUF_ISSTALE(bp)); | 599 | ASSERT(XFS_BUF_ISSTALE(bp)); |
600 | XFS_BUF_UNSTALE(bp); | 600 | XFS_BUF_UNSTALE(bp); |
601 | bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL; | 601 | bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL; |
602 | } | 602 | } |
603 | 603 | ||
604 | tp->t_flags |= XFS_TRANS_DIRTY; | 604 | tp->t_flags |= XFS_TRANS_DIRTY; |
@@ -643,6 +643,7 @@ xfs_trans_binval( | |||
643 | xfs_buf_t *bp) | 643 | xfs_buf_t *bp) |
644 | { | 644 | { |
645 | xfs_buf_log_item_t *bip = bp->b_fspriv; | 645 | xfs_buf_log_item_t *bip = bp->b_fspriv; |
646 | int i; | ||
646 | 647 | ||
647 | ASSERT(bp->b_transp == tp); | 648 | ASSERT(bp->b_transp == tp); |
648 | ASSERT(bip != NULL); | 649 | ASSERT(bip != NULL); |
@@ -657,8 +658,8 @@ xfs_trans_binval( | |||
657 | */ | 658 | */ |
658 | ASSERT(XFS_BUF_ISSTALE(bp)); | 659 | ASSERT(XFS_BUF_ISSTALE(bp)); |
659 | ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); | 660 | ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); |
660 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF)); | 661 | ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF)); |
661 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 662 | ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); |
662 | ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); | 663 | ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); |
663 | ASSERT(tp->t_flags & XFS_TRANS_DIRTY); | 664 | ASSERT(tp->t_flags & XFS_TRANS_DIRTY); |
664 | return; | 665 | return; |
@@ -668,10 +669,12 @@ xfs_trans_binval( | |||
668 | 669 | ||
669 | bip->bli_flags |= XFS_BLI_STALE; | 670 | bip->bli_flags |= XFS_BLI_STALE; |
670 | bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); | 671 | bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); |
671 | bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; | 672 | bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; |
672 | bip->bli_format.blf_flags |= XFS_BLF_CANCEL; | 673 | bip->__bli_format.blf_flags |= XFS_BLF_CANCEL; |
673 | memset((char *)(bip->bli_format.blf_data_map), 0, | 674 | for (i = 0; i < bip->bli_format_count; i++) { |
674 | (bip->bli_format.blf_map_size * sizeof(uint))); | 675 | memset(bip->bli_formats[i].blf_data_map, 0, |
676 | (bip->bli_formats[i].blf_map_size * sizeof(uint))); | ||
677 | } | ||
675 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; | 678 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
676 | tp->t_flags |= XFS_TRANS_DIRTY; | 679 | tp->t_flags |= XFS_TRANS_DIRTY; |
677 | } | 680 | } |
@@ -775,5 +778,5 @@ xfs_trans_dquot_buf( | |||
775 | type == XFS_BLF_GDQUOT_BUF); | 778 | type == XFS_BLF_GDQUOT_BUF); |
776 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 779 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
777 | 780 | ||
778 | bip->bli_format.blf_flags |= type; | 781 | bip->__bli_format.blf_flags |= type; |
779 | } | 782 | } |
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h index ccf7b4f34a3c..6c32af918c2f 100644 --- a/include/asm-generic/dma-mapping-broken.h +++ b/include/asm-generic/dma-mapping-broken.h | |||
@@ -16,6 +16,22 @@ extern void | |||
16 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, | 16 | dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, |
17 | dma_addr_t dma_handle); | 17 | dma_addr_t dma_handle); |
18 | 18 | ||
19 | static inline void *dma_alloc_attrs(struct device *dev, size_t size, | ||
20 | dma_addr_t *dma_handle, gfp_t flag, | ||
21 | struct dma_attrs *attrs) | ||
22 | { | ||
23 | /* attrs is not supported and ignored */ | ||
24 | return dma_alloc_coherent(dev, size, dma_handle, flag); | ||
25 | } | ||
26 | |||
27 | static inline void dma_free_attrs(struct device *dev, size_t size, | ||
28 | void *cpu_addr, dma_addr_t dma_handle, | ||
29 | struct dma_attrs *attrs) | ||
30 | { | ||
31 | /* attrs is not supported and ignored */ | ||
32 | dma_free_coherent(dev, size, cpu_addr, dma_handle); | ||
33 | } | ||
34 | |||
19 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) | 35 | #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) |
20 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) | 36 | #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) |
21 | 37 | ||
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 701beab27aab..5cf680a98f9b 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h | |||
@@ -461,10 +461,8 @@ static inline int is_zero_pfn(unsigned long pfn) | |||
461 | return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); | 461 | return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); |
462 | } | 462 | } |
463 | 463 | ||
464 | static inline unsigned long my_zero_pfn(unsigned long addr) | 464 | #define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) |
465 | { | 465 | |
466 | return page_to_pfn(ZERO_PAGE(addr)); | ||
467 | } | ||
468 | #else | 466 | #else |
469 | static inline int is_zero_pfn(unsigned long pfn) | 467 | static inline int is_zero_pfn(unsigned long pfn) |
470 | { | 468 | { |
diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h index 58f466ff00d3..1db51b8524e9 100644 --- a/include/asm-generic/syscalls.h +++ b/include/asm-generic/syscalls.h | |||
@@ -21,10 +21,12 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len, | |||
21 | unsigned long fd, off_t pgoff); | 21 | unsigned long fd, off_t pgoff); |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #ifndef CONFIG_GENERIC_SIGALTSTACK | ||
24 | #ifndef sys_sigaltstack | 25 | #ifndef sys_sigaltstack |
25 | asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, | 26 | asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *, |
26 | struct pt_regs *); | 27 | struct pt_regs *); |
27 | #endif | 28 | #endif |
29 | #endif | ||
28 | 30 | ||
29 | #ifndef sys_rt_sigreturn | 31 | #ifndef sys_rt_sigreturn |
30 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); | 32 | asmlinkage long sys_rt_sigreturn(struct pt_regs *regs); |
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h index 0f4a366f6fa6..3527fb3f75bb 100644 --- a/include/drm/drm_mm.h +++ b/include/drm/drm_mm.h | |||
@@ -70,7 +70,7 @@ struct drm_mm { | |||
70 | unsigned long scan_color; | 70 | unsigned long scan_color; |
71 | unsigned long scan_size; | 71 | unsigned long scan_size; |
72 | unsigned long scan_hit_start; | 72 | unsigned long scan_hit_start; |
73 | unsigned scan_hit_size; | 73 | unsigned long scan_hit_end; |
74 | unsigned scanned_blocks; | 74 | unsigned scanned_blocks; |
75 | unsigned long scan_start; | 75 | unsigned long scan_start; |
76 | unsigned long scan_end; | 76 | unsigned long scan_end; |
diff --git a/include/linux/ata.h b/include/linux/ata.h index 408da9502177..8f7a3d68371a 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -297,10 +297,12 @@ enum { | |||
297 | ATA_LOG_SATA_NCQ = 0x10, | 297 | ATA_LOG_SATA_NCQ = 0x10, |
298 | ATA_LOG_SATA_ID_DEV_DATA = 0x30, | 298 | ATA_LOG_SATA_ID_DEV_DATA = 0x30, |
299 | ATA_LOG_SATA_SETTINGS = 0x08, | 299 | ATA_LOG_SATA_SETTINGS = 0x08, |
300 | ATA_LOG_DEVSLP_MDAT = 0x30, | 300 | ATA_LOG_DEVSLP_OFFSET = 0x30, |
301 | ATA_LOG_DEVSLP_SIZE = 0x08, | ||
302 | ATA_LOG_DEVSLP_MDAT = 0x00, | ||
301 | ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, | 303 | ATA_LOG_DEVSLP_MDAT_MASK = 0x1F, |
302 | ATA_LOG_DEVSLP_DETO = 0x31, | 304 | ATA_LOG_DEVSLP_DETO = 0x01, |
303 | ATA_LOG_DEVSLP_VALID = 0x37, | 305 | ATA_LOG_DEVSLP_VALID = 0x07, |
304 | ATA_LOG_DEVSLP_VALID_MASK = 0x80, | 306 | ATA_LOG_DEVSLP_VALID_MASK = 0x80, |
305 | 307 | ||
306 | /* READ/WRITE LONG (obsolete) */ | 308 | /* READ/WRITE LONG (obsolete) */ |
diff --git a/include/linux/audit.h b/include/linux/audit.h index bce729afbcf9..5a6d718adf34 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #define _LINUX_AUDIT_H_ | 24 | #define _LINUX_AUDIT_H_ |
25 | 25 | ||
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | #include <linux/ptrace.h> | ||
27 | #include <uapi/linux/audit.h> | 28 | #include <uapi/linux/audit.h> |
28 | 29 | ||
29 | struct audit_sig_info { | 30 | struct audit_sig_info { |
@@ -157,7 +158,8 @@ void audit_core_dumps(long signr); | |||
157 | 158 | ||
158 | static inline void audit_seccomp(unsigned long syscall, long signr, int code) | 159 | static inline void audit_seccomp(unsigned long syscall, long signr, int code) |
159 | { | 160 | { |
160 | if (unlikely(!audit_dummy_context())) | 161 | /* Force a record to be reported if a signal was delivered. */ |
162 | if (signr || unlikely(!audit_dummy_context())) | ||
161 | __audit_seccomp(syscall, signr, code); | 163 | __audit_seccomp(syscall, signr, code); |
162 | } | 164 | } |
163 | 165 | ||
diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 6ecb6dc2f303..cc7bddeaf553 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h | |||
@@ -22,7 +22,7 @@ extern int sysctl_extfrag_handler(struct ctl_table *table, int write, | |||
22 | extern int fragmentation_index(struct zone *zone, unsigned int order); | 22 | extern int fragmentation_index(struct zone *zone, unsigned int order); |
23 | extern unsigned long try_to_compact_pages(struct zonelist *zonelist, | 23 | extern unsigned long try_to_compact_pages(struct zonelist *zonelist, |
24 | int order, gfp_t gfp_mask, nodemask_t *mask, | 24 | int order, gfp_t gfp_mask, nodemask_t *mask, |
25 | bool sync, bool *contended, struct page **page); | 25 | bool sync, bool *contended); |
26 | extern int compact_pgdat(pg_data_t *pgdat, int order); | 26 | extern int compact_pgdat(pg_data_t *pgdat, int order); |
27 | extern void reset_isolation_suitable(pg_data_t *pgdat); | 27 | extern void reset_isolation_suitable(pg_data_t *pgdat); |
28 | extern unsigned long compaction_suitable(struct zone *zone, int order); | 28 | extern unsigned long compaction_suitable(struct zone *zone, int order); |
@@ -75,7 +75,7 @@ static inline bool compaction_restarting(struct zone *zone, int order) | |||
75 | #else | 75 | #else |
76 | static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, | 76 | static inline unsigned long try_to_compact_pages(struct zonelist *zonelist, |
77 | int order, gfp_t gfp_mask, nodemask_t *nodemask, | 77 | int order, gfp_t gfp_mask, nodemask_t *nodemask, |
78 | bool sync, bool *contended, struct page **page) | 78 | bool sync, bool *contended) |
79 | { | 79 | { |
80 | return COMPACT_CONTINUE; | 80 | return COMPACT_CONTINUE; |
81 | } | 81 | } |
diff --git a/include/linux/cpu_rmap.h b/include/linux/cpu_rmap.h index ac3bbb5b9502..1739510d8994 100644 --- a/include/linux/cpu_rmap.h +++ b/include/linux/cpu_rmap.h | |||
@@ -13,9 +13,11 @@ | |||
13 | #include <linux/cpumask.h> | 13 | #include <linux/cpumask.h> |
14 | #include <linux/gfp.h> | 14 | #include <linux/gfp.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/kref.h> | ||
16 | 17 | ||
17 | /** | 18 | /** |
18 | * struct cpu_rmap - CPU affinity reverse-map | 19 | * struct cpu_rmap - CPU affinity reverse-map |
20 | * @refcount: kref for object | ||
19 | * @size: Number of objects to be reverse-mapped | 21 | * @size: Number of objects to be reverse-mapped |
20 | * @used: Number of objects added | 22 | * @used: Number of objects added |
21 | * @obj: Pointer to array of object pointers | 23 | * @obj: Pointer to array of object pointers |
@@ -23,6 +25,7 @@ | |||
23 | * based on affinity masks | 25 | * based on affinity masks |
24 | */ | 26 | */ |
25 | struct cpu_rmap { | 27 | struct cpu_rmap { |
28 | struct kref refcount; | ||
26 | u16 size, used; | 29 | u16 size, used; |
27 | void **obj; | 30 | void **obj; |
28 | struct { | 31 | struct { |
@@ -33,15 +36,7 @@ struct cpu_rmap { | |||
33 | #define CPU_RMAP_DIST_INF 0xffff | 36 | #define CPU_RMAP_DIST_INF 0xffff |
34 | 37 | ||
35 | extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags); | 38 | extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags); |
36 | 39 | extern int cpu_rmap_put(struct cpu_rmap *rmap); | |
37 | /** | ||
38 | * free_cpu_rmap - free CPU affinity reverse-map | ||
39 | * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL | ||
40 | */ | ||
41 | static inline void free_cpu_rmap(struct cpu_rmap *rmap) | ||
42 | { | ||
43 | kfree(rmap); | ||
44 | } | ||
45 | 40 | ||
46 | extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj); | 41 | extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj); |
47 | extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index, | 42 | extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index, |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 3711b34dc4f9..24cd1037b6d6 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -126,9 +126,9 @@ struct cpuidle_driver { | |||
126 | struct module *owner; | 126 | struct module *owner; |
127 | int refcnt; | 127 | int refcnt; |
128 | 128 | ||
129 | unsigned int power_specified:1; | ||
130 | /* set to 1 to use the core cpuidle time keeping (for all states). */ | 129 | /* set to 1 to use the core cpuidle time keeping (for all states). */ |
131 | unsigned int en_core_tk_irqen:1; | 130 | unsigned int en_core_tk_irqen:1; |
131 | /* states array must be ordered in decreasing power consumption */ | ||
132 | struct cpuidle_state states[CPUIDLE_STATE_MAX]; | 132 | struct cpuidle_state states[CPUIDLE_STATE_MAX]; |
133 | int state_count; | 133 | int state_count; |
134 | int safe_state_index; | 134 | int safe_state_index; |
diff --git a/include/linux/init.h b/include/linux/init.h index a799273714ac..10ed4f436458 100644 --- a/include/linux/init.h +++ b/include/linux/init.h | |||
@@ -93,14 +93,6 @@ | |||
93 | 93 | ||
94 | #define __exit __section(.exit.text) __exitused __cold notrace | 94 | #define __exit __section(.exit.text) __exitused __cold notrace |
95 | 95 | ||
96 | /* Used for HOTPLUG, but that is always enabled now, so just make them noops */ | ||
97 | #define __devinit | ||
98 | #define __devinitdata | ||
99 | #define __devinitconst | ||
100 | #define __devexit | ||
101 | #define __devexitdata | ||
102 | #define __devexitconst | ||
103 | |||
104 | /* Used for HOTPLUG_CPU */ | 96 | /* Used for HOTPLUG_CPU */ |
105 | #define __cpuinit __section(.cpuinit.text) __cold notrace | 97 | #define __cpuinit __section(.cpuinit.text) __cold notrace |
106 | #define __cpuinitdata __section(.cpuinit.data) | 98 | #define __cpuinitdata __section(.cpuinit.data) |
@@ -337,18 +329,6 @@ void __init parse_early_options(char *cmdline); | |||
337 | #define __INITRODATA_OR_MODULE __INITRODATA | 329 | #define __INITRODATA_OR_MODULE __INITRODATA |
338 | #endif /*CONFIG_MODULES*/ | 330 | #endif /*CONFIG_MODULES*/ |
339 | 331 | ||
340 | /* Functions marked as __devexit may be discarded at kernel link time, depending | ||
341 | on config options. Newer versions of binutils detect references from | ||
342 | retained sections to discarded sections and flag an error. Pointers to | ||
343 | __devexit functions must use __devexit_p(function_name), the wrapper will | ||
344 | insert either the function_name or NULL, depending on the config options. | ||
345 | */ | ||
346 | #if defined(MODULE) || defined(CONFIG_HOTPLUG) | ||
347 | #define __devexit_p(x) x | ||
348 | #else | ||
349 | #define __devexit_p(x) NULL | ||
350 | #endif | ||
351 | |||
352 | #ifdef MODULE | 332 | #ifdef MODULE |
353 | #define __exit_p(x) x | 333 | #define __exit_p(x) x |
354 | #else | 334 | #else |
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 5e4e6170f43a..5fa5afeeb759 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -268,11 +268,6 @@ struct irq_affinity_notify { | |||
268 | extern int | 268 | extern int |
269 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); | 269 | irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify); |
270 | 270 | ||
271 | static inline void irq_run_affinity_notifiers(void) | ||
272 | { | ||
273 | flush_scheduled_work(); | ||
274 | } | ||
275 | |||
276 | #else /* CONFIG_SMP */ | 271 | #else /* CONFIG_SMP */ |
277 | 272 | ||
278 | static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) | 273 | static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m) |
diff --git a/include/linux/libata.h b/include/linux/libata.h index 83ba0ab2c915..649e5f86b5f0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -652,8 +652,8 @@ struct ata_device { | |||
652 | u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ | 652 | u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ |
653 | }; | 653 | }; |
654 | 654 | ||
655 | /* Identify Device Data Log (30h), SATA Settings (page 08h) */ | 655 | /* DEVSLP Timing Variables from Identify Device Data Log */ |
656 | u8 sata_settings[ATA_SECT_SIZE]; | 656 | u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; |
657 | 657 | ||
658 | /* error history */ | 658 | /* error history */ |
659 | int spdn_cnt; | 659 | int spdn_cnt; |
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 00e46376e28f..2bca44b0893c 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
@@ -524,14 +524,17 @@ static inline void print_irqtrace_events(struct task_struct *curr) | |||
524 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 524 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
525 | # ifdef CONFIG_PROVE_LOCKING | 525 | # ifdef CONFIG_PROVE_LOCKING |
526 | # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) | 526 | # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, NULL, i) |
527 | # define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 2, n, i) | ||
527 | # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, NULL, i) | 528 | # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, NULL, i) |
528 | # else | 529 | # else |
529 | # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) | 530 | # define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, NULL, i) |
531 | # define rwsem_acquire_nest(l, s, t, n, i) lock_acquire(l, s, t, 0, 1, n, i) | ||
530 | # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, NULL, i) | 532 | # define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, NULL, i) |
531 | # endif | 533 | # endif |
532 | # define rwsem_release(l, n, i) lock_release(l, n, i) | 534 | # define rwsem_release(l, n, i) lock_release(l, n, i) |
533 | #else | 535 | #else |
534 | # define rwsem_acquire(l, s, t, i) do { } while (0) | 536 | # define rwsem_acquire(l, s, t, i) do { } while (0) |
537 | # define rwsem_acquire_nest(l, s, t, n, i) do { } while (0) | ||
535 | # define rwsem_acquire_read(l, s, t, i) do { } while (0) | 538 | # define rwsem_acquire_read(l, s, t, i) do { } while (0) |
536 | # define rwsem_release(l, n, i) do { } while (0) | 539 | # define rwsem_release(l, n, i) do { } while (0) |
537 | #endif | 540 | #endif |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 63204078f72b..66e2f7c61e5c 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -455,7 +455,6 @@ void put_pages_list(struct list_head *pages); | |||
455 | 455 | ||
456 | void split_page(struct page *page, unsigned int order); | 456 | void split_page(struct page *page, unsigned int order); |
457 | int split_free_page(struct page *page); | 457 | int split_free_page(struct page *page); |
458 | int capture_free_page(struct page *page, int alloc_order, int migratetype); | ||
459 | 458 | ||
460 | /* | 459 | /* |
461 | * Compound pages have a destructor function. Provide a | 460 | * Compound pages have a destructor function. Provide a |
diff --git a/include/linux/module.h b/include/linux/module.h index 7760c6d344a3..1375ee3f03aa 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -199,11 +199,11 @@ struct module_use { | |||
199 | struct module *source, *target; | 199 | struct module *source, *target; |
200 | }; | 200 | }; |
201 | 201 | ||
202 | enum module_state | 202 | enum module_state { |
203 | { | 203 | MODULE_STATE_LIVE, /* Normal state. */ |
204 | MODULE_STATE_LIVE, | 204 | MODULE_STATE_COMING, /* Full formed, running module_init. */ |
205 | MODULE_STATE_COMING, | 205 | MODULE_STATE_GOING, /* Going away. */ |
206 | MODULE_STATE_GOING, | 206 | MODULE_STATE_UNFORMED, /* Still setting it up. */ |
207 | }; | 207 | }; |
208 | 208 | ||
209 | /** | 209 | /** |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c599e4782d45..9ef07d0868b6 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -60,6 +60,9 @@ struct wireless_dev; | |||
60 | #define SET_ETHTOOL_OPS(netdev,ops) \ | 60 | #define SET_ETHTOOL_OPS(netdev,ops) \ |
61 | ( (netdev)->ethtool_ops = (ops) ) | 61 | ( (netdev)->ethtool_ops = (ops) ) |
62 | 62 | ||
63 | extern void netdev_set_default_ethtool_ops(struct net_device *dev, | ||
64 | const struct ethtool_ops *ops); | ||
65 | |||
63 | /* hardware address assignment types */ | 66 | /* hardware address assignment types */ |
64 | #define NET_ADDR_PERM 0 /* address is permanent (default) */ | 67 | #define NET_ADDR_PERM 0 /* address is permanent (default) */ |
65 | #define NET_ADDR_RANDOM 1 /* address is generated randomly */ | 68 | #define NET_ADDR_RANDOM 1 /* address is generated randomly */ |
diff --git a/arch/arm/mach-imx/iram.h b/include/linux/platform_data/imx-iram.h index 022690c33702..022690c33702 100644 --- a/arch/arm/mach-imx/iram.h +++ b/include/linux/platform_data/imx-iram.h | |||
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 1693775ecfe8..89573a33ab3c 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -45,7 +45,6 @@ extern long arch_ptrace(struct task_struct *child, long request, | |||
45 | extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); | 45 | extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); |
46 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); | 46 | extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); |
47 | extern void ptrace_disable(struct task_struct *); | 47 | extern void ptrace_disable(struct task_struct *); |
48 | extern int ptrace_check_attach(struct task_struct *task, bool ignore_state); | ||
49 | extern int ptrace_request(struct task_struct *child, long request, | 48 | extern int ptrace_request(struct task_struct *child, long request, |
50 | unsigned long addr, unsigned long data); | 49 | unsigned long addr, unsigned long data); |
51 | extern void ptrace_notify(int exit_code); | 50 | extern void ptrace_notify(int exit_code); |
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h index 2ac60c9cf644..fea49b5da12a 100644 --- a/include/linux/rbtree_augmented.h +++ b/include/linux/rbtree_augmented.h | |||
@@ -123,9 +123,9 @@ __rb_change_child(struct rb_node *old, struct rb_node *new, | |||
123 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | 123 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, |
124 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); | 124 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); |
125 | 125 | ||
126 | static __always_inline void | 126 | static __always_inline struct rb_node * |
127 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, | 127 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root, |
128 | const struct rb_augment_callbacks *augment) | 128 | const struct rb_augment_callbacks *augment) |
129 | { | 129 | { |
130 | struct rb_node *child = node->rb_right, *tmp = node->rb_left; | 130 | struct rb_node *child = node->rb_right, *tmp = node->rb_left; |
131 | struct rb_node *parent, *rebalance; | 131 | struct rb_node *parent, *rebalance; |
@@ -217,6 +217,14 @@ rb_erase_augmented(struct rb_node *node, struct rb_root *root, | |||
217 | } | 217 | } |
218 | 218 | ||
219 | augment->propagate(tmp, NULL); | 219 | augment->propagate(tmp, NULL); |
220 | return rebalance; | ||
221 | } | ||
222 | |||
223 | static __always_inline void | ||
224 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, | ||
225 | const struct rb_augment_callbacks *augment) | ||
226 | { | ||
227 | struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); | ||
220 | if (rebalance) | 228 | if (rebalance) |
221 | __rb_erase_color(rebalance, root, augment->rotate); | 229 | __rb_erase_color(rebalance, root, augment->rotate); |
222 | } | 230 | } |
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 54bd7cd7ecbd..8da67d625e13 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h | |||
@@ -125,8 +125,17 @@ extern void downgrade_write(struct rw_semaphore *sem); | |||
125 | */ | 125 | */ |
126 | extern void down_read_nested(struct rw_semaphore *sem, int subclass); | 126 | extern void down_read_nested(struct rw_semaphore *sem, int subclass); |
127 | extern void down_write_nested(struct rw_semaphore *sem, int subclass); | 127 | extern void down_write_nested(struct rw_semaphore *sem, int subclass); |
128 | extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock); | ||
129 | |||
130 | # define down_write_nest_lock(sem, nest_lock) \ | ||
131 | do { \ | ||
132 | typecheck(struct lockdep_map *, &(nest_lock)->dep_map); \ | ||
133 | _down_write_nest_lock(sem, &(nest_lock)->dep_map); \ | ||
134 | } while (0); | ||
135 | |||
128 | #else | 136 | #else |
129 | # define down_read_nested(sem, subclass) down_read(sem) | 137 | # define down_read_nested(sem, subclass) down_read(sem) |
138 | # define down_write_nest_lock(sem, nest_lock) down_write(sem) | ||
130 | # define down_write_nested(sem, subclass) down_write(sem) | 139 | # define down_write_nested(sem, subclass) down_write(sem) |
131 | #endif | 140 | #endif |
132 | 141 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 206bb089c06b..d2112477ff5e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1810,6 +1810,7 @@ extern void thread_group_cputime_adjusted(struct task_struct *p, cputime_t *ut, | |||
1810 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ | 1810 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ |
1811 | #define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */ | 1811 | #define PF_NPROC_EXCEEDED 0x00001000 /* set_user noticed that RLIMIT_NPROC was exceeded */ |
1812 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ | 1812 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ |
1813 | #define PF_USED_ASYNC 0x00004000 /* used async_schedule*(), used by module init */ | ||
1813 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ | 1814 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ |
1814 | #define PF_FROZEN 0x00010000 /* frozen for system suspend */ | 1815 | #define PF_FROZEN 0x00010000 /* frozen for system suspend */ |
1815 | #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ | 1816 | #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ |
@@ -2713,7 +2714,16 @@ static inline void thread_group_cputime_init(struct signal_struct *sig) | |||
2713 | extern void recalc_sigpending_and_wake(struct task_struct *t); | 2714 | extern void recalc_sigpending_and_wake(struct task_struct *t); |
2714 | extern void recalc_sigpending(void); | 2715 | extern void recalc_sigpending(void); |
2715 | 2716 | ||
2716 | extern void signal_wake_up(struct task_struct *t, int resume_stopped); | 2717 | extern void signal_wake_up_state(struct task_struct *t, unsigned int state); |
2718 | |||
2719 | static inline void signal_wake_up(struct task_struct *t, bool resume) | ||
2720 | { | ||
2721 | signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0); | ||
2722 | } | ||
2723 | static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) | ||
2724 | { | ||
2725 | signal_wake_up_state(t, resume ? __TASK_TRACED : 0); | ||
2726 | } | ||
2717 | 2727 | ||
2718 | /* | 2728 | /* |
2719 | * Wrappers for p->thread_info->cpu access. No-op on UP. | 2729 | * Wrappers for p->thread_info->cpu access. No-op on UP. |
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 7cae2360221e..663e34a5383f 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -174,6 +174,7 @@ typedef unsigned __bitwise__ sense_reason_t; | |||
174 | 174 | ||
175 | enum tcm_sense_reason_table { | 175 | enum tcm_sense_reason_table { |
176 | #define R(x) (__force sense_reason_t )(x) | 176 | #define R(x) (__force sense_reason_t )(x) |
177 | TCM_NO_SENSE = R(0x00), | ||
177 | TCM_NON_EXISTENT_LUN = R(0x01), | 178 | TCM_NON_EXISTENT_LUN = R(0x01), |
178 | TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), | 179 | TCM_UNSUPPORTED_SCSI_OPCODE = R(0x02), |
179 | TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), | 180 | TCM_INCORRECT_AMOUNT_OF_DATA = R(0x03), |
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 76352ac45f24..9f096f1c0907 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h | |||
@@ -26,7 +26,6 @@ | |||
26 | 26 | ||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/elf-em.h> | 28 | #include <linux/elf-em.h> |
29 | #include <linux/ptrace.h> | ||
30 | 29 | ||
31 | /* The netlink messages for the audit system is divided into blocks: | 30 | /* The netlink messages for the audit system is divided into blocks: |
32 | * 1000 - 1099 are for commanding the audit system | 31 | * 1000 - 1099 are for commanding the audit system |
@@ -106,6 +105,7 @@ | |||
106 | #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ | 105 | #define AUDIT_MMAP 1323 /* Record showing descriptor and flags in mmap */ |
107 | #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ | 106 | #define AUDIT_NETFILTER_PKT 1324 /* Packets traversing netfilter chains */ |
108 | #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ | 107 | #define AUDIT_NETFILTER_CFG 1325 /* Netfilter chain modifications */ |
108 | #define AUDIT_SECCOMP 1326 /* Secure Computing event */ | ||
109 | 109 | ||
110 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 110 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
111 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 111 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 78f99d97475b..2c6c85f18ea0 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h | |||
@@ -50,7 +50,8 @@ | |||
50 | #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ | 50 | #define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ |
51 | #define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ | 51 | #define PORT_8250_CIR 23 /* CIR infrared port, has its own driver */ |
52 | #define PORT_XR17V35X 24 /* Exar XR17V35x UARTs */ | 52 | #define PORT_XR17V35X 24 /* Exar XR17V35x UARTs */ |
53 | #define PORT_MAX_8250 24 /* max port ID */ | 53 | #define PORT_BRCM_TRUMANAGE 24 |
54 | #define PORT_MAX_8250 25 /* max port ID */ | ||
54 | 55 | ||
55 | /* | 56 | /* |
56 | * ARM specific type numbers. These are not currently guaranteed | 57 | * ARM specific type numbers. These are not currently guaranteed |
diff --git a/init/Kconfig b/init/Kconfig index 7d30240e5bfe..be8b7f55312d 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
@@ -1182,7 +1182,7 @@ config CC_OPTIMIZE_FOR_SIZE | |||
1182 | Enabling this option will pass "-Os" instead of "-O2" to gcc | 1182 | Enabling this option will pass "-Os" instead of "-O2" to gcc |
1183 | resulting in a smaller kernel. | 1183 | resulting in a smaller kernel. |
1184 | 1184 | ||
1185 | If unsure, say Y. | 1185 | If unsure, say N. |
1186 | 1186 | ||
1187 | config SYSCTL | 1187 | config SYSCTL |
1188 | bool | 1188 | bool |
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c index 5e4ded51788e..f9acf71b9810 100644 --- a/init/do_mounts_initrd.c +++ b/init/do_mounts_initrd.c | |||
@@ -36,6 +36,10 @@ __setup("noinitrd", no_initrd); | |||
36 | static int init_linuxrc(struct subprocess_info *info, struct cred *new) | 36 | static int init_linuxrc(struct subprocess_info *info, struct cred *new) |
37 | { | 37 | { |
38 | sys_unshare(CLONE_FS | CLONE_FILES); | 38 | sys_unshare(CLONE_FS | CLONE_FILES); |
39 | /* stdin/stdout/stderr for /linuxrc */ | ||
40 | sys_open("/dev/console", O_RDWR, 0); | ||
41 | sys_dup(0); | ||
42 | sys_dup(0); | ||
39 | /* move initrd over / and chdir/chroot in initrd root */ | 43 | /* move initrd over / and chdir/chroot in initrd root */ |
40 | sys_chdir("/root"); | 44 | sys_chdir("/root"); |
41 | sys_mount(".", "/", NULL, MS_MOVE, NULL); | 45 | sys_mount(".", "/", NULL, MS_MOVE, NULL); |
diff --git a/init/main.c b/init/main.c index 85d69dffe864..92d728a32d51 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -802,7 +802,7 @@ static int run_init_process(const char *init_filename) | |||
802 | (const char __user *const __user *)envp_init); | 802 | (const char __user *const __user *)envp_init); |
803 | } | 803 | } |
804 | 804 | ||
805 | static void __init kernel_init_freeable(void); | 805 | static noinline void __init kernel_init_freeable(void); |
806 | 806 | ||
807 | static int __ref kernel_init(void *unused) | 807 | static int __ref kernel_init(void *unused) |
808 | { | 808 | { |
@@ -845,7 +845,7 @@ static int __ref kernel_init(void *unused) | |||
845 | "See Linux Documentation/init.txt for guidance."); | 845 | "See Linux Documentation/init.txt for guidance."); |
846 | } | 846 | } |
847 | 847 | ||
848 | static void __init kernel_init_freeable(void) | 848 | static noinline void __init kernel_init_freeable(void) |
849 | { | 849 | { |
850 | /* | 850 | /* |
851 | * Wait until kthreadd is all set-up. | 851 | * Wait until kthreadd is all set-up. |
diff --git a/kernel/async.c b/kernel/async.c index 9d3118384858..6f34904a0b53 100644 --- a/kernel/async.c +++ b/kernel/async.c | |||
@@ -86,18 +86,27 @@ static atomic_t entry_count; | |||
86 | */ | 86 | */ |
87 | static async_cookie_t __lowest_in_progress(struct async_domain *running) | 87 | static async_cookie_t __lowest_in_progress(struct async_domain *running) |
88 | { | 88 | { |
89 | async_cookie_t first_running = next_cookie; /* infinity value */ | ||
90 | async_cookie_t first_pending = next_cookie; /* ditto */ | ||
89 | struct async_entry *entry; | 91 | struct async_entry *entry; |
90 | 92 | ||
93 | /* | ||
94 | * Both running and pending lists are sorted but not disjoint. | ||
95 | * Take the first cookies from both and return the min. | ||
96 | */ | ||
91 | if (!list_empty(&running->domain)) { | 97 | if (!list_empty(&running->domain)) { |
92 | entry = list_first_entry(&running->domain, typeof(*entry), list); | 98 | entry = list_first_entry(&running->domain, typeof(*entry), list); |
93 | return entry->cookie; | 99 | first_running = entry->cookie; |
94 | } | 100 | } |
95 | 101 | ||
96 | list_for_each_entry(entry, &async_pending, list) | 102 | list_for_each_entry(entry, &async_pending, list) { |
97 | if (entry->running == running) | 103 | if (entry->running == running) { |
98 | return entry->cookie; | 104 | first_pending = entry->cookie; |
105 | break; | ||
106 | } | ||
107 | } | ||
99 | 108 | ||
100 | return next_cookie; /* "infinity" value */ | 109 | return min(first_running, first_pending); |
101 | } | 110 | } |
102 | 111 | ||
103 | static async_cookie_t lowest_in_progress(struct async_domain *running) | 112 | static async_cookie_t lowest_in_progress(struct async_domain *running) |
@@ -118,13 +127,17 @@ static void async_run_entry_fn(struct work_struct *work) | |||
118 | { | 127 | { |
119 | struct async_entry *entry = | 128 | struct async_entry *entry = |
120 | container_of(work, struct async_entry, work); | 129 | container_of(work, struct async_entry, work); |
130 | struct async_entry *pos; | ||
121 | unsigned long flags; | 131 | unsigned long flags; |
122 | ktime_t uninitialized_var(calltime), delta, rettime; | 132 | ktime_t uninitialized_var(calltime), delta, rettime; |
123 | struct async_domain *running = entry->running; | 133 | struct async_domain *running = entry->running; |
124 | 134 | ||
125 | /* 1) move self to the running queue */ | 135 | /* 1) move self to the running queue, make sure it stays sorted */ |
126 | spin_lock_irqsave(&async_lock, flags); | 136 | spin_lock_irqsave(&async_lock, flags); |
127 | list_move_tail(&entry->list, &running->domain); | 137 | list_for_each_entry_reverse(pos, &running->domain, list) |
138 | if (entry->cookie < pos->cookie) | ||
139 | break; | ||
140 | list_move_tail(&entry->list, &pos->list); | ||
128 | spin_unlock_irqrestore(&async_lock, flags); | 141 | spin_unlock_irqrestore(&async_lock, flags); |
129 | 142 | ||
130 | /* 2) run (and print duration) */ | 143 | /* 2) run (and print duration) */ |
@@ -196,6 +209,9 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a | |||
196 | atomic_inc(&entry_count); | 209 | atomic_inc(&entry_count); |
197 | spin_unlock_irqrestore(&async_lock, flags); | 210 | spin_unlock_irqrestore(&async_lock, flags); |
198 | 211 | ||
212 | /* mark that this task has queued an async job, used by module init */ | ||
213 | current->flags |= PF_USED_ASYNC; | ||
214 | |||
199 | /* schedule for execution */ | 215 | /* schedule for execution */ |
200 | queue_work(system_unbound_wq, &entry->work); | 216 | queue_work(system_unbound_wq, &entry->work); |
201 | 217 | ||
diff --git a/kernel/audit.c b/kernel/audit.c index 40414e9143db..d596e5355f15 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
@@ -272,6 +272,8 @@ static int audit_log_config_change(char *function_name, int new, int old, | |||
272 | int rc = 0; | 272 | int rc = 0; |
273 | 273 | ||
274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 274 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); |
275 | if (unlikely(!ab)) | ||
276 | return rc; | ||
275 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, | 277 | audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new, |
276 | old, from_kuid(&init_user_ns, loginuid), sessionid); | 278 | old, from_kuid(&init_user_ns, loginuid), sessionid); |
277 | if (sid) { | 279 | if (sid) { |
@@ -619,6 +621,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, | |||
619 | } | 621 | } |
620 | 622 | ||
621 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); | 623 | *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); |
624 | if (unlikely(!*ab)) | ||
625 | return rc; | ||
622 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", | 626 | audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u", |
623 | task_tgid_vnr(current), | 627 | task_tgid_vnr(current), |
624 | from_kuid(&init_user_ns, current_uid()), | 628 | from_kuid(&init_user_ns, current_uid()), |
@@ -1097,6 +1101,23 @@ static inline void audit_get_stamp(struct audit_context *ctx, | |||
1097 | } | 1101 | } |
1098 | } | 1102 | } |
1099 | 1103 | ||
1104 | /* | ||
1105 | * Wait for auditd to drain the queue a little | ||
1106 | */ | ||
1107 | static void wait_for_auditd(unsigned long sleep_time) | ||
1108 | { | ||
1109 | DECLARE_WAITQUEUE(wait, current); | ||
1110 | set_current_state(TASK_INTERRUPTIBLE); | ||
1111 | add_wait_queue(&audit_backlog_wait, &wait); | ||
1112 | |||
1113 | if (audit_backlog_limit && | ||
1114 | skb_queue_len(&audit_skb_queue) > audit_backlog_limit) | ||
1115 | schedule_timeout(sleep_time); | ||
1116 | |||
1117 | __set_current_state(TASK_RUNNING); | ||
1118 | remove_wait_queue(&audit_backlog_wait, &wait); | ||
1119 | } | ||
1120 | |||
1100 | /* Obtain an audit buffer. This routine does locking to obtain the | 1121 | /* Obtain an audit buffer. This routine does locking to obtain the |
1101 | * audit buffer, but then no locking is required for calls to | 1122 | * audit buffer, but then no locking is required for calls to |
1102 | * audit_log_*format. If the tsk is a task that is currently in a | 1123 | * audit_log_*format. If the tsk is a task that is currently in a |
@@ -1142,20 +1163,13 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, | |||
1142 | 1163 | ||
1143 | while (audit_backlog_limit | 1164 | while (audit_backlog_limit |
1144 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { | 1165 | && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { |
1145 | if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time | 1166 | if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) { |
1146 | && time_before(jiffies, timeout_start + audit_backlog_wait_time)) { | 1167 | unsigned long sleep_time; |
1147 | 1168 | ||
1148 | /* Wait for auditd to drain the queue a little */ | 1169 | sleep_time = timeout_start + audit_backlog_wait_time - |
1149 | DECLARE_WAITQUEUE(wait, current); | 1170 | jiffies; |
1150 | set_current_state(TASK_INTERRUPTIBLE); | 1171 | if ((long)sleep_time > 0) |
1151 | add_wait_queue(&audit_backlog_wait, &wait); | 1172 | wait_for_auditd(sleep_time); |
1152 | |||
1153 | if (audit_backlog_limit && | ||
1154 | skb_queue_len(&audit_skb_queue) > audit_backlog_limit) | ||
1155 | schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies); | ||
1156 | |||
1157 | __set_current_state(TASK_RUNNING); | ||
1158 | remove_wait_queue(&audit_backlog_wait, &wait); | ||
1159 | continue; | 1173 | continue; |
1160 | } | 1174 | } |
1161 | if (audit_rate_check() && printk_ratelimit()) | 1175 | if (audit_rate_check() && printk_ratelimit()) |
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index e81175ef25f8..642a89c4f3d6 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c | |||
@@ -449,11 +449,26 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) | |||
449 | return 0; | 449 | return 0; |
450 | } | 450 | } |
451 | 451 | ||
452 | static void audit_log_remove_rule(struct audit_krule *rule) | ||
453 | { | ||
454 | struct audit_buffer *ab; | ||
455 | |||
456 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | ||
457 | if (unlikely(!ab)) | ||
458 | return; | ||
459 | audit_log_format(ab, "op="); | ||
460 | audit_log_string(ab, "remove rule"); | ||
461 | audit_log_format(ab, " dir="); | ||
462 | audit_log_untrustedstring(ab, rule->tree->pathname); | ||
463 | audit_log_key(ab, rule->filterkey); | ||
464 | audit_log_format(ab, " list=%d res=1", rule->listnr); | ||
465 | audit_log_end(ab); | ||
466 | } | ||
467 | |||
452 | static void kill_rules(struct audit_tree *tree) | 468 | static void kill_rules(struct audit_tree *tree) |
453 | { | 469 | { |
454 | struct audit_krule *rule, *next; | 470 | struct audit_krule *rule, *next; |
455 | struct audit_entry *entry; | 471 | struct audit_entry *entry; |
456 | struct audit_buffer *ab; | ||
457 | 472 | ||
458 | list_for_each_entry_safe(rule, next, &tree->rules, rlist) { | 473 | list_for_each_entry_safe(rule, next, &tree->rules, rlist) { |
459 | entry = container_of(rule, struct audit_entry, rule); | 474 | entry = container_of(rule, struct audit_entry, rule); |
@@ -461,14 +476,7 @@ static void kill_rules(struct audit_tree *tree) | |||
461 | list_del_init(&rule->rlist); | 476 | list_del_init(&rule->rlist); |
462 | if (rule->tree) { | 477 | if (rule->tree) { |
463 | /* not a half-baked one */ | 478 | /* not a half-baked one */ |
464 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); | 479 | audit_log_remove_rule(rule); |
465 | audit_log_format(ab, "op="); | ||
466 | audit_log_string(ab, "remove rule"); | ||
467 | audit_log_format(ab, " dir="); | ||
468 | audit_log_untrustedstring(ab, rule->tree->pathname); | ||
469 | audit_log_key(ab, rule->filterkey); | ||
470 | audit_log_format(ab, " list=%d res=1", rule->listnr); | ||
471 | audit_log_end(ab); | ||
472 | rule->tree = NULL; | 480 | rule->tree = NULL; |
473 | list_del_rcu(&entry->list); | 481 | list_del_rcu(&entry->list); |
474 | list_del(&entry->rule.list); | 482 | list_del(&entry->rule.list); |
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 4a599f699adc..22831c4d369c 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -240,6 +240,8 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc | |||
240 | if (audit_enabled) { | 240 | if (audit_enabled) { |
241 | struct audit_buffer *ab; | 241 | struct audit_buffer *ab; |
242 | ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); | 242 | ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE); |
243 | if (unlikely(!ab)) | ||
244 | return; | ||
243 | audit_log_format(ab, "auid=%u ses=%u op=", | 245 | audit_log_format(ab, "auid=%u ses=%u op=", |
244 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 246 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
245 | audit_get_sessionid(current)); | 247 | audit_get_sessionid(current)); |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 7f19f23d38a3..f9fc54bbe06f 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -1144,7 +1144,6 @@ static void audit_log_rule_change(kuid_t loginuid, u32 sessionid, u32 sid, | |||
1144 | * audit_receive_filter - apply all rules to the specified message type | 1144 | * audit_receive_filter - apply all rules to the specified message type |
1145 | * @type: audit message type | 1145 | * @type: audit message type |
1146 | * @pid: target pid for netlink audit messages | 1146 | * @pid: target pid for netlink audit messages |
1147 | * @uid: target uid for netlink audit messages | ||
1148 | * @seq: netlink audit message sequence (serial) number | 1147 | * @seq: netlink audit message sequence (serial) number |
1149 | * @data: payload data | 1148 | * @data: payload data |
1150 | * @datasz: size of payload data | 1149 | * @datasz: size of payload data |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e37e6a12c5e3..a371f857a0a9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -1464,14 +1464,14 @@ static void show_special(struct audit_context *context, int *call_panic) | |||
1464 | audit_log_end(ab); | 1464 | audit_log_end(ab); |
1465 | ab = audit_log_start(context, GFP_KERNEL, | 1465 | ab = audit_log_start(context, GFP_KERNEL, |
1466 | AUDIT_IPC_SET_PERM); | 1466 | AUDIT_IPC_SET_PERM); |
1467 | if (unlikely(!ab)) | ||
1468 | return; | ||
1467 | audit_log_format(ab, | 1469 | audit_log_format(ab, |
1468 | "qbytes=%lx ouid=%u ogid=%u mode=%#ho", | 1470 | "qbytes=%lx ouid=%u ogid=%u mode=%#ho", |
1469 | context->ipc.qbytes, | 1471 | context->ipc.qbytes, |
1470 | context->ipc.perm_uid, | 1472 | context->ipc.perm_uid, |
1471 | context->ipc.perm_gid, | 1473 | context->ipc.perm_gid, |
1472 | context->ipc.perm_mode); | 1474 | context->ipc.perm_mode); |
1473 | if (!ab) | ||
1474 | return; | ||
1475 | } | 1475 | } |
1476 | break; } | 1476 | break; } |
1477 | case AUDIT_MQ_OPEN: { | 1477 | case AUDIT_MQ_OPEN: { |
@@ -2675,7 +2675,7 @@ void __audit_mmap_fd(int fd, int flags) | |||
2675 | context->type = AUDIT_MMAP; | 2675 | context->type = AUDIT_MMAP; |
2676 | } | 2676 | } |
2677 | 2677 | ||
2678 | static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) | 2678 | static void audit_log_task(struct audit_buffer *ab) |
2679 | { | 2679 | { |
2680 | kuid_t auid, uid; | 2680 | kuid_t auid, uid; |
2681 | kgid_t gid; | 2681 | kgid_t gid; |
@@ -2693,6 +2693,11 @@ static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) | |||
2693 | audit_log_task_context(ab); | 2693 | audit_log_task_context(ab); |
2694 | audit_log_format(ab, " pid=%d comm=", current->pid); | 2694 | audit_log_format(ab, " pid=%d comm=", current->pid); |
2695 | audit_log_untrustedstring(ab, current->comm); | 2695 | audit_log_untrustedstring(ab, current->comm); |
2696 | } | ||
2697 | |||
2698 | static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) | ||
2699 | { | ||
2700 | audit_log_task(ab); | ||
2696 | audit_log_format(ab, " reason="); | 2701 | audit_log_format(ab, " reason="); |
2697 | audit_log_string(ab, reason); | 2702 | audit_log_string(ab, reason); |
2698 | audit_log_format(ab, " sig=%ld", signr); | 2703 | audit_log_format(ab, " sig=%ld", signr); |
@@ -2715,6 +2720,8 @@ void audit_core_dumps(long signr) | |||
2715 | return; | 2720 | return; |
2716 | 2721 | ||
2717 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); | 2722 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); |
2723 | if (unlikely(!ab)) | ||
2724 | return; | ||
2718 | audit_log_abend(ab, "memory violation", signr); | 2725 | audit_log_abend(ab, "memory violation", signr); |
2719 | audit_log_end(ab); | 2726 | audit_log_end(ab); |
2720 | } | 2727 | } |
@@ -2723,8 +2730,11 @@ void __audit_seccomp(unsigned long syscall, long signr, int code) | |||
2723 | { | 2730 | { |
2724 | struct audit_buffer *ab; | 2731 | struct audit_buffer *ab; |
2725 | 2732 | ||
2726 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); | 2733 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP); |
2727 | audit_log_abend(ab, "seccomp", signr); | 2734 | if (unlikely(!ab)) |
2735 | return; | ||
2736 | audit_log_task(ab); | ||
2737 | audit_log_format(ab, " sig=%ld", signr); | ||
2728 | audit_log_format(ab, " syscall=%ld", syscall); | 2738 | audit_log_format(ab, " syscall=%ld", syscall); |
2729 | audit_log_format(ab, " compat=%d", is_compat_task()); | 2739 | audit_log_format(ab, " compat=%d", is_compat_task()); |
2730 | audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); | 2740 | audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current)); |
diff --git a/kernel/compat.c b/kernel/compat.c index f6150e92dfc9..36700e9e2be9 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -535,9 +535,11 @@ asmlinkage long compat_sys_getrusage(int who, struct compat_rusage __user *ru) | |||
535 | return 0; | 535 | return 0; |
536 | } | 536 | } |
537 | 537 | ||
538 | asmlinkage long | 538 | COMPAT_SYSCALL_DEFINE4(wait4, |
539 | compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, | 539 | compat_pid_t, pid, |
540 | struct compat_rusage __user *ru) | 540 | compat_uint_t __user *, stat_addr, |
541 | int, options, | ||
542 | struct compat_rusage __user *, ru) | ||
541 | { | 543 | { |
542 | if (!ru) { | 544 | if (!ru) { |
543 | return sys_wait4(pid, stat_addr, options, NULL); | 545 | return sys_wait4(pid, stat_addr, options, NULL); |
@@ -564,9 +566,10 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, | |||
564 | } | 566 | } |
565 | } | 567 | } |
566 | 568 | ||
567 | asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, | 569 | COMPAT_SYSCALL_DEFINE5(waitid, |
568 | struct compat_siginfo __user *uinfo, int options, | 570 | int, which, compat_pid_t, pid, |
569 | struct compat_rusage __user *uru) | 571 | struct compat_siginfo __user *, uinfo, int, options, |
572 | struct compat_rusage __user *, uru) | ||
570 | { | 573 | { |
571 | siginfo_t info; | 574 | siginfo_t info; |
572 | struct rusage ru; | 575 | struct rusage ru; |
@@ -584,7 +587,11 @@ asmlinkage long compat_sys_waitid(int which, compat_pid_t pid, | |||
584 | return ret; | 587 | return ret; |
585 | 588 | ||
586 | if (uru) { | 589 | if (uru) { |
587 | ret = put_compat_rusage(&ru, uru); | 590 | /* sys_waitid() overwrites everything in ru */ |
591 | if (COMPAT_USE_64BIT_TIME) | ||
592 | ret = copy_to_user(uru, &ru, sizeof(ru)); | ||
593 | else | ||
594 | ret = put_compat_rusage(&ru, uru); | ||
588 | if (ret) | 595 | if (ret) |
589 | return ret; | 596 | return ret; |
590 | } | 597 | } |
@@ -994,7 +1001,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
994 | sigset_from_compat(&s, &s32); | 1001 | sigset_from_compat(&s, &s32); |
995 | 1002 | ||
996 | if (uts) { | 1003 | if (uts) { |
997 | if (get_compat_timespec(&t, uts)) | 1004 | if (compat_get_timespec(&t, uts)) |
998 | return -EFAULT; | 1005 | return -EFAULT; |
999 | } | 1006 | } |
1000 | 1007 | ||
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c index 4d5f8d5612f3..8875254120b6 100644 --- a/kernel/debug/kdb/kdb_main.c +++ b/kernel/debug/kdb/kdb_main.c | |||
@@ -1970,6 +1970,8 @@ static int kdb_lsmod(int argc, const char **argv) | |||
1970 | 1970 | ||
1971 | kdb_printf("Module Size modstruct Used by\n"); | 1971 | kdb_printf("Module Size modstruct Used by\n"); |
1972 | list_for_each_entry(mod, kdb_modules, list) { | 1972 | list_for_each_entry(mod, kdb_modules, list) { |
1973 | if (mod->state == MODULE_STATE_UNFORMED) | ||
1974 | continue; | ||
1973 | 1975 | ||
1974 | kdb_printf("%-20s%8u 0x%p ", mod->name, | 1976 | kdb_printf("%-20s%8u 0x%p ", mod->name, |
1975 | mod->core_size, (void *)mod); | 1977 | mod->core_size, (void *)mod); |
diff --git a/kernel/fork.c b/kernel/fork.c index 65ca6d27f24e..c535f33bbb9c 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1668,8 +1668,10 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, | |||
1668 | int, tls_val) | 1668 | int, tls_val) |
1669 | #endif | 1669 | #endif |
1670 | { | 1670 | { |
1671 | return do_fork(clone_flags, newsp, 0, | 1671 | long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr); |
1672 | parent_tidptr, child_tidptr); | 1672 | asmlinkage_protect(5, ret, clone_flags, newsp, |
1673 | parent_tidptr, child_tidptr, tls_val); | ||
1674 | return ret; | ||
1673 | } | 1675 | } |
1674 | #endif | 1676 | #endif |
1675 | 1677 | ||
diff --git a/kernel/module.c b/kernel/module.c index 250092c1d57d..eab08274ec9b 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -188,6 +188,7 @@ struct load_info { | |||
188 | ongoing or failed initialization etc. */ | 188 | ongoing or failed initialization etc. */ |
189 | static inline int strong_try_module_get(struct module *mod) | 189 | static inline int strong_try_module_get(struct module *mod) |
190 | { | 190 | { |
191 | BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED); | ||
191 | if (mod && mod->state == MODULE_STATE_COMING) | 192 | if (mod && mod->state == MODULE_STATE_COMING) |
192 | return -EBUSY; | 193 | return -EBUSY; |
193 | if (try_module_get(mod)) | 194 | if (try_module_get(mod)) |
@@ -343,6 +344,9 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr, | |||
343 | #endif | 344 | #endif |
344 | }; | 345 | }; |
345 | 346 | ||
347 | if (mod->state == MODULE_STATE_UNFORMED) | ||
348 | continue; | ||
349 | |||
346 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data)) | 350 | if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data)) |
347 | return true; | 351 | return true; |
348 | } | 352 | } |
@@ -450,16 +454,24 @@ const struct kernel_symbol *find_symbol(const char *name, | |||
450 | EXPORT_SYMBOL_GPL(find_symbol); | 454 | EXPORT_SYMBOL_GPL(find_symbol); |
451 | 455 | ||
452 | /* Search for module by name: must hold module_mutex. */ | 456 | /* Search for module by name: must hold module_mutex. */ |
453 | struct module *find_module(const char *name) | 457 | static struct module *find_module_all(const char *name, |
458 | bool even_unformed) | ||
454 | { | 459 | { |
455 | struct module *mod; | 460 | struct module *mod; |
456 | 461 | ||
457 | list_for_each_entry(mod, &modules, list) { | 462 | list_for_each_entry(mod, &modules, list) { |
463 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | ||
464 | continue; | ||
458 | if (strcmp(mod->name, name) == 0) | 465 | if (strcmp(mod->name, name) == 0) |
459 | return mod; | 466 | return mod; |
460 | } | 467 | } |
461 | return NULL; | 468 | return NULL; |
462 | } | 469 | } |
470 | |||
471 | struct module *find_module(const char *name) | ||
472 | { | ||
473 | return find_module_all(name, false); | ||
474 | } | ||
463 | EXPORT_SYMBOL_GPL(find_module); | 475 | EXPORT_SYMBOL_GPL(find_module); |
464 | 476 | ||
465 | #ifdef CONFIG_SMP | 477 | #ifdef CONFIG_SMP |
@@ -525,6 +537,8 @@ bool is_module_percpu_address(unsigned long addr) | |||
525 | preempt_disable(); | 537 | preempt_disable(); |
526 | 538 | ||
527 | list_for_each_entry_rcu(mod, &modules, list) { | 539 | list_for_each_entry_rcu(mod, &modules, list) { |
540 | if (mod->state == MODULE_STATE_UNFORMED) | ||
541 | continue; | ||
528 | if (!mod->percpu_size) | 542 | if (!mod->percpu_size) |
529 | continue; | 543 | continue; |
530 | for_each_possible_cpu(cpu) { | 544 | for_each_possible_cpu(cpu) { |
@@ -1048,6 +1062,8 @@ static ssize_t show_initstate(struct module_attribute *mattr, | |||
1048 | case MODULE_STATE_GOING: | 1062 | case MODULE_STATE_GOING: |
1049 | state = "going"; | 1063 | state = "going"; |
1050 | break; | 1064 | break; |
1065 | default: | ||
1066 | BUG(); | ||
1051 | } | 1067 | } |
1052 | return sprintf(buffer, "%s\n", state); | 1068 | return sprintf(buffer, "%s\n", state); |
1053 | } | 1069 | } |
@@ -1786,6 +1802,8 @@ void set_all_modules_text_rw(void) | |||
1786 | 1802 | ||
1787 | mutex_lock(&module_mutex); | 1803 | mutex_lock(&module_mutex); |
1788 | list_for_each_entry_rcu(mod, &modules, list) { | 1804 | list_for_each_entry_rcu(mod, &modules, list) { |
1805 | if (mod->state == MODULE_STATE_UNFORMED) | ||
1806 | continue; | ||
1789 | if ((mod->module_core) && (mod->core_text_size)) { | 1807 | if ((mod->module_core) && (mod->core_text_size)) { |
1790 | set_page_attributes(mod->module_core, | 1808 | set_page_attributes(mod->module_core, |
1791 | mod->module_core + mod->core_text_size, | 1809 | mod->module_core + mod->core_text_size, |
@@ -1807,6 +1825,8 @@ void set_all_modules_text_ro(void) | |||
1807 | 1825 | ||
1808 | mutex_lock(&module_mutex); | 1826 | mutex_lock(&module_mutex); |
1809 | list_for_each_entry_rcu(mod, &modules, list) { | 1827 | list_for_each_entry_rcu(mod, &modules, list) { |
1828 | if (mod->state == MODULE_STATE_UNFORMED) | ||
1829 | continue; | ||
1810 | if ((mod->module_core) && (mod->core_text_size)) { | 1830 | if ((mod->module_core) && (mod->core_text_size)) { |
1811 | set_page_attributes(mod->module_core, | 1831 | set_page_attributes(mod->module_core, |
1812 | mod->module_core + mod->core_text_size, | 1832 | mod->module_core + mod->core_text_size, |
@@ -2527,6 +2547,13 @@ static int copy_module_from_fd(int fd, struct load_info *info) | |||
2527 | err = -EFBIG; | 2547 | err = -EFBIG; |
2528 | goto out; | 2548 | goto out; |
2529 | } | 2549 | } |
2550 | |||
2551 | /* Don't hand 0 to vmalloc, it whines. */ | ||
2552 | if (stat.size == 0) { | ||
2553 | err = -EINVAL; | ||
2554 | goto out; | ||
2555 | } | ||
2556 | |||
2530 | info->hdr = vmalloc(stat.size); | 2557 | info->hdr = vmalloc(stat.size); |
2531 | if (!info->hdr) { | 2558 | if (!info->hdr) { |
2532 | err = -ENOMEM; | 2559 | err = -ENOMEM; |
@@ -2990,8 +3017,9 @@ static bool finished_loading(const char *name) | |||
2990 | bool ret; | 3017 | bool ret; |
2991 | 3018 | ||
2992 | mutex_lock(&module_mutex); | 3019 | mutex_lock(&module_mutex); |
2993 | mod = find_module(name); | 3020 | mod = find_module_all(name, true); |
2994 | ret = !mod || mod->state != MODULE_STATE_COMING; | 3021 | ret = !mod || mod->state == MODULE_STATE_LIVE |
3022 | || mod->state == MODULE_STATE_GOING; | ||
2995 | mutex_unlock(&module_mutex); | 3023 | mutex_unlock(&module_mutex); |
2996 | 3024 | ||
2997 | return ret; | 3025 | return ret; |
@@ -3013,6 +3041,12 @@ static int do_init_module(struct module *mod) | |||
3013 | { | 3041 | { |
3014 | int ret = 0; | 3042 | int ret = 0; |
3015 | 3043 | ||
3044 | /* | ||
3045 | * We want to find out whether @mod uses async during init. Clear | ||
3046 | * PF_USED_ASYNC. async_schedule*() will set it. | ||
3047 | */ | ||
3048 | current->flags &= ~PF_USED_ASYNC; | ||
3049 | |||
3016 | blocking_notifier_call_chain(&module_notify_list, | 3050 | blocking_notifier_call_chain(&module_notify_list, |
3017 | MODULE_STATE_COMING, mod); | 3051 | MODULE_STATE_COMING, mod); |
3018 | 3052 | ||
@@ -3058,8 +3092,25 @@ static int do_init_module(struct module *mod) | |||
3058 | blocking_notifier_call_chain(&module_notify_list, | 3092 | blocking_notifier_call_chain(&module_notify_list, |
3059 | MODULE_STATE_LIVE, mod); | 3093 | MODULE_STATE_LIVE, mod); |
3060 | 3094 | ||
3061 | /* We need to finish all async code before the module init sequence is done */ | 3095 | /* |
3062 | async_synchronize_full(); | 3096 | * We need to finish all async code before the module init sequence |
3097 | * is done. This has potential to deadlock. For example, a newly | ||
3098 | * detected block device can trigger request_module() of the | ||
3099 | * default iosched from async probing task. Once userland helper | ||
3100 | * reaches here, async_synchronize_full() will wait on the async | ||
3101 | * task waiting on request_module() and deadlock. | ||
3102 | * | ||
3103 | * This deadlock is avoided by perfomring async_synchronize_full() | ||
3104 | * iff module init queued any async jobs. This isn't a full | ||
3105 | * solution as it will deadlock the same if module loading from | ||
3106 | * async jobs nests more than once; however, due to the various | ||
3107 | * constraints, this hack seems to be the best option for now. | ||
3108 | * Please refer to the following thread for details. | ||
3109 | * | ||
3110 | * http://thread.gmane.org/gmane.linux.kernel/1420814 | ||
3111 | */ | ||
3112 | if (current->flags & PF_USED_ASYNC) | ||
3113 | async_synchronize_full(); | ||
3063 | 3114 | ||
3064 | mutex_lock(&module_mutex); | 3115 | mutex_lock(&module_mutex); |
3065 | /* Drop initial reference. */ | 3116 | /* Drop initial reference. */ |
@@ -3113,6 +3164,32 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3113 | goto free_copy; | 3164 | goto free_copy; |
3114 | } | 3165 | } |
3115 | 3166 | ||
3167 | /* | ||
3168 | * We try to place it in the list now to make sure it's unique | ||
3169 | * before we dedicate too many resources. In particular, | ||
3170 | * temporary percpu memory exhaustion. | ||
3171 | */ | ||
3172 | mod->state = MODULE_STATE_UNFORMED; | ||
3173 | again: | ||
3174 | mutex_lock(&module_mutex); | ||
3175 | if ((old = find_module_all(mod->name, true)) != NULL) { | ||
3176 | if (old->state == MODULE_STATE_COMING | ||
3177 | || old->state == MODULE_STATE_UNFORMED) { | ||
3178 | /* Wait in case it fails to load. */ | ||
3179 | mutex_unlock(&module_mutex); | ||
3180 | err = wait_event_interruptible(module_wq, | ||
3181 | finished_loading(mod->name)); | ||
3182 | if (err) | ||
3183 | goto free_module; | ||
3184 | goto again; | ||
3185 | } | ||
3186 | err = -EEXIST; | ||
3187 | mutex_unlock(&module_mutex); | ||
3188 | goto free_module; | ||
3189 | } | ||
3190 | list_add_rcu(&mod->list, &modules); | ||
3191 | mutex_unlock(&module_mutex); | ||
3192 | |||
3116 | #ifdef CONFIG_MODULE_SIG | 3193 | #ifdef CONFIG_MODULE_SIG |
3117 | mod->sig_ok = info->sig_ok; | 3194 | mod->sig_ok = info->sig_ok; |
3118 | if (!mod->sig_ok) | 3195 | if (!mod->sig_ok) |
@@ -3122,7 +3199,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3122 | /* Now module is in final location, initialize linked lists, etc. */ | 3199 | /* Now module is in final location, initialize linked lists, etc. */ |
3123 | err = module_unload_init(mod); | 3200 | err = module_unload_init(mod); |
3124 | if (err) | 3201 | if (err) |
3125 | goto free_module; | 3202 | goto unlink_mod; |
3126 | 3203 | ||
3127 | /* Now we've got everything in the final locations, we can | 3204 | /* Now we've got everything in the final locations, we can |
3128 | * find optional sections. */ | 3205 | * find optional sections. */ |
@@ -3157,54 +3234,33 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3157 | goto free_arch_cleanup; | 3234 | goto free_arch_cleanup; |
3158 | } | 3235 | } |
3159 | 3236 | ||
3160 | /* Mark state as coming so strong_try_module_get() ignores us. */ | ||
3161 | mod->state = MODULE_STATE_COMING; | ||
3162 | |||
3163 | /* Now sew it into the lists so we can get lockdep and oops | ||
3164 | * info during argument parsing. No one should access us, since | ||
3165 | * strong_try_module_get() will fail. | ||
3166 | * lockdep/oops can run asynchronous, so use the RCU list insertion | ||
3167 | * function to insert in a way safe to concurrent readers. | ||
3168 | * The mutex protects against concurrent writers. | ||
3169 | */ | ||
3170 | again: | ||
3171 | mutex_lock(&module_mutex); | ||
3172 | if ((old = find_module(mod->name)) != NULL) { | ||
3173 | if (old->state == MODULE_STATE_COMING) { | ||
3174 | /* Wait in case it fails to load. */ | ||
3175 | mutex_unlock(&module_mutex); | ||
3176 | err = wait_event_interruptible(module_wq, | ||
3177 | finished_loading(mod->name)); | ||
3178 | if (err) | ||
3179 | goto free_arch_cleanup; | ||
3180 | goto again; | ||
3181 | } | ||
3182 | err = -EEXIST; | ||
3183 | goto unlock; | ||
3184 | } | ||
3185 | |||
3186 | /* This has to be done once we're sure module name is unique. */ | ||
3187 | dynamic_debug_setup(info->debug, info->num_debug); | 3237 | dynamic_debug_setup(info->debug, info->num_debug); |
3188 | 3238 | ||
3189 | /* Find duplicate symbols */ | 3239 | mutex_lock(&module_mutex); |
3240 | /* Find duplicate symbols (must be called under lock). */ | ||
3190 | err = verify_export_symbols(mod); | 3241 | err = verify_export_symbols(mod); |
3191 | if (err < 0) | 3242 | if (err < 0) |
3192 | goto ddebug; | 3243 | goto ddebug_cleanup; |
3193 | 3244 | ||
3245 | /* This relies on module_mutex for list integrity. */ | ||
3194 | module_bug_finalize(info->hdr, info->sechdrs, mod); | 3246 | module_bug_finalize(info->hdr, info->sechdrs, mod); |
3195 | list_add_rcu(&mod->list, &modules); | 3247 | |
3248 | /* Mark state as coming so strong_try_module_get() ignores us, | ||
3249 | * but kallsyms etc. can see us. */ | ||
3250 | mod->state = MODULE_STATE_COMING; | ||
3251 | |||
3196 | mutex_unlock(&module_mutex); | 3252 | mutex_unlock(&module_mutex); |
3197 | 3253 | ||
3198 | /* Module is ready to execute: parsing args may do that. */ | 3254 | /* Module is ready to execute: parsing args may do that. */ |
3199 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 3255 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
3200 | -32768, 32767, &ddebug_dyndbg_module_param_cb); | 3256 | -32768, 32767, &ddebug_dyndbg_module_param_cb); |
3201 | if (err < 0) | 3257 | if (err < 0) |
3202 | goto unlink; | 3258 | goto bug_cleanup; |
3203 | 3259 | ||
3204 | /* Link in to syfs. */ | 3260 | /* Link in to syfs. */ |
3205 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); | 3261 | err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp); |
3206 | if (err < 0) | 3262 | if (err < 0) |
3207 | goto unlink; | 3263 | goto bug_cleanup; |
3208 | 3264 | ||
3209 | /* Get rid of temporary copy. */ | 3265 | /* Get rid of temporary copy. */ |
3210 | free_copy(info); | 3266 | free_copy(info); |
@@ -3214,16 +3270,13 @@ again: | |||
3214 | 3270 | ||
3215 | return do_init_module(mod); | 3271 | return do_init_module(mod); |
3216 | 3272 | ||
3217 | unlink: | 3273 | bug_cleanup: |
3274 | /* module_bug_cleanup needs module_mutex protection */ | ||
3218 | mutex_lock(&module_mutex); | 3275 | mutex_lock(&module_mutex); |
3219 | /* Unlink carefully: kallsyms could be walking list. */ | ||
3220 | list_del_rcu(&mod->list); | ||
3221 | module_bug_cleanup(mod); | 3276 | module_bug_cleanup(mod); |
3222 | wake_up_all(&module_wq); | 3277 | ddebug_cleanup: |
3223 | ddebug: | ||
3224 | dynamic_debug_remove(info->debug); | ||
3225 | unlock: | ||
3226 | mutex_unlock(&module_mutex); | 3278 | mutex_unlock(&module_mutex); |
3279 | dynamic_debug_remove(info->debug); | ||
3227 | synchronize_sched(); | 3280 | synchronize_sched(); |
3228 | kfree(mod->args); | 3281 | kfree(mod->args); |
3229 | free_arch_cleanup: | 3282 | free_arch_cleanup: |
@@ -3232,6 +3285,12 @@ again: | |||
3232 | free_modinfo(mod); | 3285 | free_modinfo(mod); |
3233 | free_unload: | 3286 | free_unload: |
3234 | module_unload_free(mod); | 3287 | module_unload_free(mod); |
3288 | unlink_mod: | ||
3289 | mutex_lock(&module_mutex); | ||
3290 | /* Unlink carefully: kallsyms could be walking list. */ | ||
3291 | list_del_rcu(&mod->list); | ||
3292 | wake_up_all(&module_wq); | ||
3293 | mutex_unlock(&module_mutex); | ||
3235 | free_module: | 3294 | free_module: |
3236 | module_deallocate(mod, info); | 3295 | module_deallocate(mod, info); |
3237 | free_copy: | 3296 | free_copy: |
@@ -3354,6 +3413,8 @@ const char *module_address_lookup(unsigned long addr, | |||
3354 | 3413 | ||
3355 | preempt_disable(); | 3414 | preempt_disable(); |
3356 | list_for_each_entry_rcu(mod, &modules, list) { | 3415 | list_for_each_entry_rcu(mod, &modules, list) { |
3416 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3417 | continue; | ||
3357 | if (within_module_init(addr, mod) || | 3418 | if (within_module_init(addr, mod) || |
3358 | within_module_core(addr, mod)) { | 3419 | within_module_core(addr, mod)) { |
3359 | if (modname) | 3420 | if (modname) |
@@ -3377,6 +3438,8 @@ int lookup_module_symbol_name(unsigned long addr, char *symname) | |||
3377 | 3438 | ||
3378 | preempt_disable(); | 3439 | preempt_disable(); |
3379 | list_for_each_entry_rcu(mod, &modules, list) { | 3440 | list_for_each_entry_rcu(mod, &modules, list) { |
3441 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3442 | continue; | ||
3380 | if (within_module_init(addr, mod) || | 3443 | if (within_module_init(addr, mod) || |
3381 | within_module_core(addr, mod)) { | 3444 | within_module_core(addr, mod)) { |
3382 | const char *sym; | 3445 | const char *sym; |
@@ -3401,6 +3464,8 @@ int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |||
3401 | 3464 | ||
3402 | preempt_disable(); | 3465 | preempt_disable(); |
3403 | list_for_each_entry_rcu(mod, &modules, list) { | 3466 | list_for_each_entry_rcu(mod, &modules, list) { |
3467 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3468 | continue; | ||
3404 | if (within_module_init(addr, mod) || | 3469 | if (within_module_init(addr, mod) || |
3405 | within_module_core(addr, mod)) { | 3470 | within_module_core(addr, mod)) { |
3406 | const char *sym; | 3471 | const char *sym; |
@@ -3428,6 +3493,8 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, | |||
3428 | 3493 | ||
3429 | preempt_disable(); | 3494 | preempt_disable(); |
3430 | list_for_each_entry_rcu(mod, &modules, list) { | 3495 | list_for_each_entry_rcu(mod, &modules, list) { |
3496 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3497 | continue; | ||
3431 | if (symnum < mod->num_symtab) { | 3498 | if (symnum < mod->num_symtab) { |
3432 | *value = mod->symtab[symnum].st_value; | 3499 | *value = mod->symtab[symnum].st_value; |
3433 | *type = mod->symtab[symnum].st_info; | 3500 | *type = mod->symtab[symnum].st_info; |
@@ -3470,9 +3537,12 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
3470 | ret = mod_find_symname(mod, colon+1); | 3537 | ret = mod_find_symname(mod, colon+1); |
3471 | *colon = ':'; | 3538 | *colon = ':'; |
3472 | } else { | 3539 | } else { |
3473 | list_for_each_entry_rcu(mod, &modules, list) | 3540 | list_for_each_entry_rcu(mod, &modules, list) { |
3541 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3542 | continue; | ||
3474 | if ((ret = mod_find_symname(mod, name)) != 0) | 3543 | if ((ret = mod_find_symname(mod, name)) != 0) |
3475 | break; | 3544 | break; |
3545 | } | ||
3476 | } | 3546 | } |
3477 | preempt_enable(); | 3547 | preempt_enable(); |
3478 | return ret; | 3548 | return ret; |
@@ -3487,6 +3557,8 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *, | |||
3487 | int ret; | 3557 | int ret; |
3488 | 3558 | ||
3489 | list_for_each_entry(mod, &modules, list) { | 3559 | list_for_each_entry(mod, &modules, list) { |
3560 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3561 | continue; | ||
3490 | for (i = 0; i < mod->num_symtab; i++) { | 3562 | for (i = 0; i < mod->num_symtab; i++) { |
3491 | ret = fn(data, mod->strtab + mod->symtab[i].st_name, | 3563 | ret = fn(data, mod->strtab + mod->symtab[i].st_name, |
3492 | mod, mod->symtab[i].st_value); | 3564 | mod, mod->symtab[i].st_value); |
@@ -3502,6 +3574,7 @@ static char *module_flags(struct module *mod, char *buf) | |||
3502 | { | 3574 | { |
3503 | int bx = 0; | 3575 | int bx = 0; |
3504 | 3576 | ||
3577 | BUG_ON(mod->state == MODULE_STATE_UNFORMED); | ||
3505 | if (mod->taints || | 3578 | if (mod->taints || |
3506 | mod->state == MODULE_STATE_GOING || | 3579 | mod->state == MODULE_STATE_GOING || |
3507 | mod->state == MODULE_STATE_COMING) { | 3580 | mod->state == MODULE_STATE_COMING) { |
@@ -3543,6 +3616,10 @@ static int m_show(struct seq_file *m, void *p) | |||
3543 | struct module *mod = list_entry(p, struct module, list); | 3616 | struct module *mod = list_entry(p, struct module, list); |
3544 | char buf[8]; | 3617 | char buf[8]; |
3545 | 3618 | ||
3619 | /* We always ignore unformed modules. */ | ||
3620 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3621 | return 0; | ||
3622 | |||
3546 | seq_printf(m, "%s %u", | 3623 | seq_printf(m, "%s %u", |
3547 | mod->name, mod->init_size + mod->core_size); | 3624 | mod->name, mod->init_size + mod->core_size); |
3548 | print_unload_info(m, mod); | 3625 | print_unload_info(m, mod); |
@@ -3603,6 +3680,8 @@ const struct exception_table_entry *search_module_extables(unsigned long addr) | |||
3603 | 3680 | ||
3604 | preempt_disable(); | 3681 | preempt_disable(); |
3605 | list_for_each_entry_rcu(mod, &modules, list) { | 3682 | list_for_each_entry_rcu(mod, &modules, list) { |
3683 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3684 | continue; | ||
3606 | if (mod->num_exentries == 0) | 3685 | if (mod->num_exentries == 0) |
3607 | continue; | 3686 | continue; |
3608 | 3687 | ||
@@ -3651,10 +3730,13 @@ struct module *__module_address(unsigned long addr) | |||
3651 | if (addr < module_addr_min || addr > module_addr_max) | 3730 | if (addr < module_addr_min || addr > module_addr_max) |
3652 | return NULL; | 3731 | return NULL; |
3653 | 3732 | ||
3654 | list_for_each_entry_rcu(mod, &modules, list) | 3733 | list_for_each_entry_rcu(mod, &modules, list) { |
3734 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3735 | continue; | ||
3655 | if (within_module_core(addr, mod) | 3736 | if (within_module_core(addr, mod) |
3656 | || within_module_init(addr, mod)) | 3737 | || within_module_init(addr, mod)) |
3657 | return mod; | 3738 | return mod; |
3739 | } | ||
3658 | return NULL; | 3740 | return NULL; |
3659 | } | 3741 | } |
3660 | EXPORT_SYMBOL_GPL(__module_address); | 3742 | EXPORT_SYMBOL_GPL(__module_address); |
@@ -3707,8 +3789,11 @@ void print_modules(void) | |||
3707 | printk(KERN_DEFAULT "Modules linked in:"); | 3789 | printk(KERN_DEFAULT "Modules linked in:"); |
3708 | /* Most callers should already have preempt disabled, but make sure */ | 3790 | /* Most callers should already have preempt disabled, but make sure */ |
3709 | preempt_disable(); | 3791 | preempt_disable(); |
3710 | list_for_each_entry_rcu(mod, &modules, list) | 3792 | list_for_each_entry_rcu(mod, &modules, list) { |
3793 | if (mod->state == MODULE_STATE_UNFORMED) | ||
3794 | continue; | ||
3711 | printk(" %s%s", mod->name, module_flags(mod, buf)); | 3795 | printk(" %s%s", mod->name, module_flags(mod, buf)); |
3796 | } | ||
3712 | preempt_enable(); | 3797 | preempt_enable(); |
3713 | if (last_unloaded_module[0]) | 3798 | if (last_unloaded_module[0]) |
3714 | printk(" [last unloaded: %s]", last_unloaded_module); | 3799 | printk(" [last unloaded: %s]", last_unloaded_module); |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 1599157336a6..6cbeaae4406d 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -117,11 +117,45 @@ void __ptrace_unlink(struct task_struct *child) | |||
117 | * TASK_KILLABLE sleeps. | 117 | * TASK_KILLABLE sleeps. |
118 | */ | 118 | */ |
119 | if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) | 119 | if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) |
120 | signal_wake_up(child, task_is_traced(child)); | 120 | ptrace_signal_wake_up(child, true); |
121 | 121 | ||
122 | spin_unlock(&child->sighand->siglock); | 122 | spin_unlock(&child->sighand->siglock); |
123 | } | 123 | } |
124 | 124 | ||
125 | /* Ensure that nothing can wake it up, even SIGKILL */ | ||
126 | static bool ptrace_freeze_traced(struct task_struct *task) | ||
127 | { | ||
128 | bool ret = false; | ||
129 | |||
130 | /* Lockless, nobody but us can set this flag */ | ||
131 | if (task->jobctl & JOBCTL_LISTENING) | ||
132 | return ret; | ||
133 | |||
134 | spin_lock_irq(&task->sighand->siglock); | ||
135 | if (task_is_traced(task) && !__fatal_signal_pending(task)) { | ||
136 | task->state = __TASK_TRACED; | ||
137 | ret = true; | ||
138 | } | ||
139 | spin_unlock_irq(&task->sighand->siglock); | ||
140 | |||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | static void ptrace_unfreeze_traced(struct task_struct *task) | ||
145 | { | ||
146 | if (task->state != __TASK_TRACED) | ||
147 | return; | ||
148 | |||
149 | WARN_ON(!task->ptrace || task->parent != current); | ||
150 | |||
151 | spin_lock_irq(&task->sighand->siglock); | ||
152 | if (__fatal_signal_pending(task)) | ||
153 | wake_up_state(task, __TASK_TRACED); | ||
154 | else | ||
155 | task->state = TASK_TRACED; | ||
156 | spin_unlock_irq(&task->sighand->siglock); | ||
157 | } | ||
158 | |||
125 | /** | 159 | /** |
126 | * ptrace_check_attach - check whether ptracee is ready for ptrace operation | 160 | * ptrace_check_attach - check whether ptracee is ready for ptrace operation |
127 | * @child: ptracee to check for | 161 | * @child: ptracee to check for |
@@ -139,7 +173,7 @@ void __ptrace_unlink(struct task_struct *child) | |||
139 | * RETURNS: | 173 | * RETURNS: |
140 | * 0 on success, -ESRCH if %child is not ready. | 174 | * 0 on success, -ESRCH if %child is not ready. |
141 | */ | 175 | */ |
142 | int ptrace_check_attach(struct task_struct *child, bool ignore_state) | 176 | static int ptrace_check_attach(struct task_struct *child, bool ignore_state) |
143 | { | 177 | { |
144 | int ret = -ESRCH; | 178 | int ret = -ESRCH; |
145 | 179 | ||
@@ -151,24 +185,29 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state) | |||
151 | * be changed by us so it's not changing right after this. | 185 | * be changed by us so it's not changing right after this. |
152 | */ | 186 | */ |
153 | read_lock(&tasklist_lock); | 187 | read_lock(&tasklist_lock); |
154 | if ((child->ptrace & PT_PTRACED) && child->parent == current) { | 188 | if (child->ptrace && child->parent == current) { |
189 | WARN_ON(child->state == __TASK_TRACED); | ||
155 | /* | 190 | /* |
156 | * child->sighand can't be NULL, release_task() | 191 | * child->sighand can't be NULL, release_task() |
157 | * does ptrace_unlink() before __exit_signal(). | 192 | * does ptrace_unlink() before __exit_signal(). |
158 | */ | 193 | */ |
159 | spin_lock_irq(&child->sighand->siglock); | 194 | if (ignore_state || ptrace_freeze_traced(child)) |
160 | WARN_ON_ONCE(task_is_stopped(child)); | ||
161 | if (ignore_state || (task_is_traced(child) && | ||
162 | !(child->jobctl & JOBCTL_LISTENING))) | ||
163 | ret = 0; | 195 | ret = 0; |
164 | spin_unlock_irq(&child->sighand->siglock); | ||
165 | } | 196 | } |
166 | read_unlock(&tasklist_lock); | 197 | read_unlock(&tasklist_lock); |
167 | 198 | ||
168 | if (!ret && !ignore_state) | 199 | if (!ret && !ignore_state) { |
169 | ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; | 200 | if (!wait_task_inactive(child, __TASK_TRACED)) { |
201 | /* | ||
202 | * This can only happen if may_ptrace_stop() fails and | ||
203 | * ptrace_stop() changes ->state back to TASK_RUNNING, | ||
204 | * so we should not worry about leaking __TASK_TRACED. | ||
205 | */ | ||
206 | WARN_ON(child->state == __TASK_TRACED); | ||
207 | ret = -ESRCH; | ||
208 | } | ||
209 | } | ||
170 | 210 | ||
171 | /* All systems go.. */ | ||
172 | return ret; | 211 | return ret; |
173 | } | 212 | } |
174 | 213 | ||
@@ -317,7 +356,7 @@ static int ptrace_attach(struct task_struct *task, long request, | |||
317 | */ | 356 | */ |
318 | if (task_is_stopped(task) && | 357 | if (task_is_stopped(task) && |
319 | task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) | 358 | task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) |
320 | signal_wake_up(task, 1); | 359 | signal_wake_up_state(task, __TASK_STOPPED); |
321 | 360 | ||
322 | spin_unlock(&task->sighand->siglock); | 361 | spin_unlock(&task->sighand->siglock); |
323 | 362 | ||
@@ -737,7 +776,7 @@ int ptrace_request(struct task_struct *child, long request, | |||
737 | * tracee into STOP. | 776 | * tracee into STOP. |
738 | */ | 777 | */ |
739 | if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) | 778 | if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) |
740 | signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); | 779 | ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); |
741 | 780 | ||
742 | unlock_task_sighand(child, &flags); | 781 | unlock_task_sighand(child, &flags); |
743 | ret = 0; | 782 | ret = 0; |
@@ -763,7 +802,7 @@ int ptrace_request(struct task_struct *child, long request, | |||
763 | * start of this trap and now. Trigger re-trap. | 802 | * start of this trap and now. Trigger re-trap. |
764 | */ | 803 | */ |
765 | if (child->jobctl & JOBCTL_TRAP_NOTIFY) | 804 | if (child->jobctl & JOBCTL_TRAP_NOTIFY) |
766 | signal_wake_up(child, true); | 805 | ptrace_signal_wake_up(child, true); |
767 | ret = 0; | 806 | ret = 0; |
768 | } | 807 | } |
769 | unlock_task_sighand(child, &flags); | 808 | unlock_task_sighand(child, &flags); |
@@ -900,6 +939,8 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr, | |||
900 | goto out_put_task_struct; | 939 | goto out_put_task_struct; |
901 | 940 | ||
902 | ret = arch_ptrace(child, request, addr, data); | 941 | ret = arch_ptrace(child, request, addr, data); |
942 | if (ret || request != PTRACE_DETACH) | ||
943 | ptrace_unfreeze_traced(child); | ||
903 | 944 | ||
904 | out_put_task_struct: | 945 | out_put_task_struct: |
905 | put_task_struct(child); | 946 | put_task_struct(child); |
@@ -1039,8 +1080,11 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, | |||
1039 | 1080 | ||
1040 | ret = ptrace_check_attach(child, request == PTRACE_KILL || | 1081 | ret = ptrace_check_attach(child, request == PTRACE_KILL || |
1041 | request == PTRACE_INTERRUPT); | 1082 | request == PTRACE_INTERRUPT); |
1042 | if (!ret) | 1083 | if (!ret) { |
1043 | ret = compat_arch_ptrace(child, request, addr, data); | 1084 | ret = compat_arch_ptrace(child, request, addr, data); |
1085 | if (ret || request != PTRACE_DETACH) | ||
1086 | ptrace_unfreeze_traced(child); | ||
1087 | } | ||
1044 | 1088 | ||
1045 | out_put_task_struct: | 1089 | out_put_task_struct: |
1046 | put_task_struct(child); | 1090 | put_task_struct(child); |
diff --git a/kernel/rwsem.c b/kernel/rwsem.c index 6850f53e02d8..b3c6c3fcd847 100644 --- a/kernel/rwsem.c +++ b/kernel/rwsem.c | |||
@@ -116,6 +116,16 @@ void down_read_nested(struct rw_semaphore *sem, int subclass) | |||
116 | 116 | ||
117 | EXPORT_SYMBOL(down_read_nested); | 117 | EXPORT_SYMBOL(down_read_nested); |
118 | 118 | ||
119 | void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest) | ||
120 | { | ||
121 | might_sleep(); | ||
122 | rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_); | ||
123 | |||
124 | LOCK_CONTENDED(sem, __down_write_trylock, __down_write); | ||
125 | } | ||
126 | |||
127 | EXPORT_SYMBOL(_down_write_nest_lock); | ||
128 | |||
119 | void down_write_nested(struct rw_semaphore *sem, int subclass) | 129 | void down_write_nested(struct rw_semaphore *sem, int subclass) |
120 | { | 130 | { |
121 | might_sleep(); | 131 | might_sleep(); |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 257002c13bb0..26058d0bebba 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -1523,7 +1523,8 @@ out: | |||
1523 | */ | 1523 | */ |
1524 | int wake_up_process(struct task_struct *p) | 1524 | int wake_up_process(struct task_struct *p) |
1525 | { | 1525 | { |
1526 | return try_to_wake_up(p, TASK_ALL, 0); | 1526 | WARN_ON(task_is_stopped_or_traced(p)); |
1527 | return try_to_wake_up(p, TASK_NORMAL, 0); | ||
1527 | } | 1528 | } |
1528 | EXPORT_SYMBOL(wake_up_process); | 1529 | EXPORT_SYMBOL(wake_up_process); |
1529 | 1530 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 372771e948c2..3d09cf6cde75 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -680,23 +680,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) | |||
680 | * No need to set need_resched since signal event passing | 680 | * No need to set need_resched since signal event passing |
681 | * goes through ->blocked | 681 | * goes through ->blocked |
682 | */ | 682 | */ |
683 | void signal_wake_up(struct task_struct *t, int resume) | 683 | void signal_wake_up_state(struct task_struct *t, unsigned int state) |
684 | { | 684 | { |
685 | unsigned int mask; | ||
686 | |||
687 | set_tsk_thread_flag(t, TIF_SIGPENDING); | 685 | set_tsk_thread_flag(t, TIF_SIGPENDING); |
688 | |||
689 | /* | 686 | /* |
690 | * For SIGKILL, we want to wake it up in the stopped/traced/killable | 687 | * TASK_WAKEKILL also means wake it up in the stopped/traced/killable |
691 | * case. We don't check t->state here because there is a race with it | 688 | * case. We don't check t->state here because there is a race with it |
692 | * executing another processor and just now entering stopped state. | 689 | * executing another processor and just now entering stopped state. |
693 | * By using wake_up_state, we ensure the process will wake up and | 690 | * By using wake_up_state, we ensure the process will wake up and |
694 | * handle its death signal. | 691 | * handle its death signal. |
695 | */ | 692 | */ |
696 | mask = TASK_INTERRUPTIBLE; | 693 | if (!wake_up_state(t, state | TASK_INTERRUPTIBLE)) |
697 | if (resume) | ||
698 | mask |= TASK_WAKEKILL; | ||
699 | if (!wake_up_state(t, mask)) | ||
700 | kick_process(t); | 694 | kick_process(t); |
701 | } | 695 | } |
702 | 696 | ||
@@ -844,7 +838,7 @@ static void ptrace_trap_notify(struct task_struct *t) | |||
844 | assert_spin_locked(&t->sighand->siglock); | 838 | assert_spin_locked(&t->sighand->siglock); |
845 | 839 | ||
846 | task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); | 840 | task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); |
847 | signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); | 841 | ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); |
848 | } | 842 | } |
849 | 843 | ||
850 | /* | 844 | /* |
@@ -1800,6 +1794,10 @@ static inline int may_ptrace_stop(void) | |||
1800 | * If SIGKILL was already sent before the caller unlocked | 1794 | * If SIGKILL was already sent before the caller unlocked |
1801 | * ->siglock we must see ->core_state != NULL. Otherwise it | 1795 | * ->siglock we must see ->core_state != NULL. Otherwise it |
1802 | * is safe to enter schedule(). | 1796 | * is safe to enter schedule(). |
1797 | * | ||
1798 | * This is almost outdated, a task with the pending SIGKILL can't | ||
1799 | * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported | ||
1800 | * after SIGKILL was already dequeued. | ||
1803 | */ | 1801 | */ |
1804 | if (unlikely(current->mm->core_state) && | 1802 | if (unlikely(current->mm->core_state) && |
1805 | unlikely(current->mm == current->parent->mm)) | 1803 | unlikely(current->mm == current->parent->mm)) |
@@ -1925,6 +1923,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) | |||
1925 | if (gstop_done) | 1923 | if (gstop_done) |
1926 | do_notify_parent_cldstop(current, false, why); | 1924 | do_notify_parent_cldstop(current, false, why); |
1927 | 1925 | ||
1926 | /* tasklist protects us from ptrace_freeze_traced() */ | ||
1928 | __set_current_state(TASK_RUNNING); | 1927 | __set_current_state(TASK_RUNNING); |
1929 | if (clear_code) | 1928 | if (clear_code) |
1930 | current->exit_code = 0; | 1929 | current->exit_code = 0; |
@@ -3116,8 +3115,9 @@ int __save_altstack(stack_t __user *uss, unsigned long sp) | |||
3116 | 3115 | ||
3117 | #ifdef CONFIG_COMPAT | 3116 | #ifdef CONFIG_COMPAT |
3118 | #ifdef CONFIG_GENERIC_SIGALTSTACK | 3117 | #ifdef CONFIG_GENERIC_SIGALTSTACK |
3119 | asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, | 3118 | COMPAT_SYSCALL_DEFINE2(sigaltstack, |
3120 | compat_stack_t __user *uoss_ptr) | 3119 | const compat_stack_t __user *, uss_ptr, |
3120 | compat_stack_t __user *, uoss_ptr) | ||
3121 | { | 3121 | { |
3122 | stack_t uss, uoss; | 3122 | stack_t uss, uoss; |
3123 | int ret; | 3123 | int ret; |
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3ffe4c5ad3f3..41473b4ad7a4 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -3998,7 +3998,7 @@ static int ftrace_module_notify(struct notifier_block *self, | |||
3998 | 3998 | ||
3999 | struct notifier_block ftrace_module_nb = { | 3999 | struct notifier_block ftrace_module_nb = { |
4000 | .notifier_call = ftrace_module_notify, | 4000 | .notifier_call = ftrace_module_notify, |
4001 | .priority = 0, | 4001 | .priority = INT_MAX, /* Run before anything that can use kprobes */ |
4002 | }; | 4002 | }; |
4003 | 4003 | ||
4004 | extern unsigned long __start_mcount_loc[]; | 4004 | extern unsigned long __start_mcount_loc[]; |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e5125677efa0..3c13e46d7d24 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2899,6 +2899,8 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, | |||
2899 | if (copy_from_user(&buf, ubuf, cnt)) | 2899 | if (copy_from_user(&buf, ubuf, cnt)) |
2900 | return -EFAULT; | 2900 | return -EFAULT; |
2901 | 2901 | ||
2902 | buf[cnt] = 0; | ||
2903 | |||
2902 | trace_set_options(buf); | 2904 | trace_set_options(buf); |
2903 | 2905 | ||
2904 | *ppos += cnt; | 2906 | *ppos += cnt; |
@@ -3452,7 +3454,7 @@ static int tracing_wait_pipe(struct file *filp) | |||
3452 | return -EINTR; | 3454 | return -EINTR; |
3453 | 3455 | ||
3454 | /* | 3456 | /* |
3455 | * We block until we read something and tracing is enabled. | 3457 | * We block until we read something and tracing is disabled. |
3456 | * We still block if tracing is disabled, but we have never | 3458 | * We still block if tracing is disabled, but we have never |
3457 | * read anything. This allows a user to cat this file, and | 3459 | * read anything. This allows a user to cat this file, and |
3458 | * then enable tracing. But after we have read something, | 3460 | * then enable tracing. But after we have read something, |
@@ -3460,7 +3462,7 @@ static int tracing_wait_pipe(struct file *filp) | |||
3460 | * | 3462 | * |
3461 | * iter->pos will be 0 if we haven't read anything. | 3463 | * iter->pos will be 0 if we haven't read anything. |
3462 | */ | 3464 | */ |
3463 | if (tracing_is_enabled() && iter->pos) | 3465 | if (!tracing_is_enabled() && iter->pos) |
3464 | break; | 3466 | break; |
3465 | } | 3467 | } |
3466 | 3468 | ||
@@ -4815,10 +4817,17 @@ rb_simple_write(struct file *filp, const char __user *ubuf, | |||
4815 | return ret; | 4817 | return ret; |
4816 | 4818 | ||
4817 | if (buffer) { | 4819 | if (buffer) { |
4818 | if (val) | 4820 | mutex_lock(&trace_types_lock); |
4821 | if (val) { | ||
4819 | ring_buffer_record_on(buffer); | 4822 | ring_buffer_record_on(buffer); |
4820 | else | 4823 | if (current_trace->start) |
4824 | current_trace->start(tr); | ||
4825 | } else { | ||
4821 | ring_buffer_record_off(buffer); | 4826 | ring_buffer_record_off(buffer); |
4827 | if (current_trace->stop) | ||
4828 | current_trace->stop(tr); | ||
4829 | } | ||
4830 | mutex_unlock(&trace_types_lock); | ||
4822 | } | 4831 | } |
4823 | 4832 | ||
4824 | (*ppos)++; | 4833 | (*ppos)++; |
@@ -55,6 +55,7 @@ static inline unsigned long bug_addr(const struct bug_entry *bug) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | #ifdef CONFIG_MODULES | 57 | #ifdef CONFIG_MODULES |
58 | /* Updates are protected by module mutex */ | ||
58 | static LIST_HEAD(module_bug_list); | 59 | static LIST_HEAD(module_bug_list); |
59 | 60 | ||
60 | static const struct bug_entry *module_find_bug(unsigned long bugaddr) | 61 | static const struct bug_entry *module_find_bug(unsigned long bugaddr) |
diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c index 145dec5267c9..5fbed5caba6e 100644 --- a/lib/cpu_rmap.c +++ b/lib/cpu_rmap.c | |||
@@ -45,6 +45,7 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags) | |||
45 | if (!rmap) | 45 | if (!rmap) |
46 | return NULL; | 46 | return NULL; |
47 | 47 | ||
48 | kref_init(&rmap->refcount); | ||
48 | rmap->obj = (void **)((char *)rmap + obj_offset); | 49 | rmap->obj = (void **)((char *)rmap + obj_offset); |
49 | 50 | ||
50 | /* Initially assign CPUs to objects on a rota, since we have | 51 | /* Initially assign CPUs to objects on a rota, since we have |
@@ -63,6 +64,35 @@ struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags) | |||
63 | } | 64 | } |
64 | EXPORT_SYMBOL(alloc_cpu_rmap); | 65 | EXPORT_SYMBOL(alloc_cpu_rmap); |
65 | 66 | ||
67 | /** | ||
68 | * cpu_rmap_release - internal reclaiming helper called from kref_put | ||
69 | * @ref: kref to struct cpu_rmap | ||
70 | */ | ||
71 | static void cpu_rmap_release(struct kref *ref) | ||
72 | { | ||
73 | struct cpu_rmap *rmap = container_of(ref, struct cpu_rmap, refcount); | ||
74 | kfree(rmap); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * cpu_rmap_get - internal helper to get new ref on a cpu_rmap | ||
79 | * @rmap: reverse-map allocated with alloc_cpu_rmap() | ||
80 | */ | ||
81 | static inline void cpu_rmap_get(struct cpu_rmap *rmap) | ||
82 | { | ||
83 | kref_get(&rmap->refcount); | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * cpu_rmap_put - release ref on a cpu_rmap | ||
88 | * @rmap: reverse-map allocated with alloc_cpu_rmap() | ||
89 | */ | ||
90 | int cpu_rmap_put(struct cpu_rmap *rmap) | ||
91 | { | ||
92 | return kref_put(&rmap->refcount, cpu_rmap_release); | ||
93 | } | ||
94 | EXPORT_SYMBOL(cpu_rmap_put); | ||
95 | |||
66 | /* Reevaluate nearest object for given CPU, comparing with the given | 96 | /* Reevaluate nearest object for given CPU, comparing with the given |
67 | * neighbours at the given distance. | 97 | * neighbours at the given distance. |
68 | */ | 98 | */ |
@@ -197,8 +227,7 @@ struct irq_glue { | |||
197 | * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs | 227 | * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs |
198 | * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL | 228 | * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL |
199 | * | 229 | * |
200 | * Must be called in process context, before freeing the IRQs, and | 230 | * Must be called in process context, before freeing the IRQs. |
201 | * without holding any locks required by global workqueue items. | ||
202 | */ | 231 | */ |
203 | void free_irq_cpu_rmap(struct cpu_rmap *rmap) | 232 | void free_irq_cpu_rmap(struct cpu_rmap *rmap) |
204 | { | 233 | { |
@@ -212,12 +241,18 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap) | |||
212 | glue = rmap->obj[index]; | 241 | glue = rmap->obj[index]; |
213 | irq_set_affinity_notifier(glue->notify.irq, NULL); | 242 | irq_set_affinity_notifier(glue->notify.irq, NULL); |
214 | } | 243 | } |
215 | irq_run_affinity_notifiers(); | ||
216 | 244 | ||
217 | kfree(rmap); | 245 | cpu_rmap_put(rmap); |
218 | } | 246 | } |
219 | EXPORT_SYMBOL(free_irq_cpu_rmap); | 247 | EXPORT_SYMBOL(free_irq_cpu_rmap); |
220 | 248 | ||
249 | /** | ||
250 | * irq_cpu_rmap_notify - callback for IRQ subsystem when IRQ affinity updated | ||
251 | * @notify: struct irq_affinity_notify passed by irq/manage.c | ||
252 | * @mask: cpu mask for new SMP affinity | ||
253 | * | ||
254 | * This is executed in workqueue context. | ||
255 | */ | ||
221 | static void | 256 | static void |
222 | irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask) | 257 | irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask) |
223 | { | 258 | { |
@@ -230,10 +265,16 @@ irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask) | |||
230 | pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc); | 265 | pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc); |
231 | } | 266 | } |
232 | 267 | ||
268 | /** | ||
269 | * irq_cpu_rmap_release - reclaiming callback for IRQ subsystem | ||
270 | * @ref: kref to struct irq_affinity_notify passed by irq/manage.c | ||
271 | */ | ||
233 | static void irq_cpu_rmap_release(struct kref *ref) | 272 | static void irq_cpu_rmap_release(struct kref *ref) |
234 | { | 273 | { |
235 | struct irq_glue *glue = | 274 | struct irq_glue *glue = |
236 | container_of(ref, struct irq_glue, notify.kref); | 275 | container_of(ref, struct irq_glue, notify.kref); |
276 | |||
277 | cpu_rmap_put(glue->rmap); | ||
237 | kfree(glue); | 278 | kfree(glue); |
238 | } | 279 | } |
239 | 280 | ||
@@ -258,10 +299,13 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq) | |||
258 | glue->notify.notify = irq_cpu_rmap_notify; | 299 | glue->notify.notify = irq_cpu_rmap_notify; |
259 | glue->notify.release = irq_cpu_rmap_release; | 300 | glue->notify.release = irq_cpu_rmap_release; |
260 | glue->rmap = rmap; | 301 | glue->rmap = rmap; |
302 | cpu_rmap_get(rmap); | ||
261 | glue->index = cpu_rmap_add(rmap, glue); | 303 | glue->index = cpu_rmap_add(rmap, glue); |
262 | rc = irq_set_affinity_notifier(irq, &glue->notify); | 304 | rc = irq_set_affinity_notifier(irq, &glue->notify); |
263 | if (rc) | 305 | if (rc) { |
306 | cpu_rmap_put(glue->rmap); | ||
264 | kfree(glue); | 307 | kfree(glue); |
308 | } | ||
265 | return rc; | 309 | return rc; |
266 | } | 310 | } |
267 | EXPORT_SYMBOL(irq_cpu_rmap_add); | 311 | EXPORT_SYMBOL(irq_cpu_rmap_add); |
diff --git a/lib/rbtree.c b/lib/rbtree.c index 4f56a11d67fa..c0e31fe2fabf 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c | |||
@@ -194,8 +194,12 @@ __rb_insert(struct rb_node *node, struct rb_root *root, | |||
194 | } | 194 | } |
195 | } | 195 | } |
196 | 196 | ||
197 | __always_inline void | 197 | /* |
198 | __rb_erase_color(struct rb_node *parent, struct rb_root *root, | 198 | * Inline version for rb_erase() use - we want to be able to inline |
199 | * and eliminate the dummy_rotate callback there | ||
200 | */ | ||
201 | static __always_inline void | ||
202 | ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | ||
199 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | 203 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) |
200 | { | 204 | { |
201 | struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; | 205 | struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; |
@@ -355,6 +359,13 @@ __rb_erase_color(struct rb_node *parent, struct rb_root *root, | |||
355 | } | 359 | } |
356 | } | 360 | } |
357 | } | 361 | } |
362 | |||
363 | /* Non-inline version for rb_erase_augmented() use */ | ||
364 | void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | ||
365 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | ||
366 | { | ||
367 | ____rb_erase_color(parent, root, augment_rotate); | ||
368 | } | ||
358 | EXPORT_SYMBOL(__rb_erase_color); | 369 | EXPORT_SYMBOL(__rb_erase_color); |
359 | 370 | ||
360 | /* | 371 | /* |
@@ -380,7 +391,10 @@ EXPORT_SYMBOL(rb_insert_color); | |||
380 | 391 | ||
381 | void rb_erase(struct rb_node *node, struct rb_root *root) | 392 | void rb_erase(struct rb_node *node, struct rb_root *root) |
382 | { | 393 | { |
383 | rb_erase_augmented(node, root, &dummy_callbacks); | 394 | struct rb_node *rebalance; |
395 | rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); | ||
396 | if (rebalance) | ||
397 | ____rb_erase_color(rebalance, root, dummy_rotate); | ||
384 | } | 398 | } |
385 | EXPORT_SYMBOL(rb_erase); | 399 | EXPORT_SYMBOL(rb_erase); |
386 | 400 | ||
diff --git a/mm/bootmem.c b/mm/bootmem.c index 1324cd74faec..b93376c39b61 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c | |||
@@ -185,10 +185,23 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
185 | 185 | ||
186 | while (start < end) { | 186 | while (start < end) { |
187 | unsigned long *map, idx, vec; | 187 | unsigned long *map, idx, vec; |
188 | unsigned shift; | ||
188 | 189 | ||
189 | map = bdata->node_bootmem_map; | 190 | map = bdata->node_bootmem_map; |
190 | idx = start - bdata->node_min_pfn; | 191 | idx = start - bdata->node_min_pfn; |
192 | shift = idx & (BITS_PER_LONG - 1); | ||
193 | /* | ||
194 | * vec holds at most BITS_PER_LONG map bits, | ||
195 | * bit 0 corresponds to start. | ||
196 | */ | ||
191 | vec = ~map[idx / BITS_PER_LONG]; | 197 | vec = ~map[idx / BITS_PER_LONG]; |
198 | |||
199 | if (shift) { | ||
200 | vec >>= shift; | ||
201 | if (end - start >= BITS_PER_LONG) | ||
202 | vec |= ~map[idx / BITS_PER_LONG + 1] << | ||
203 | (BITS_PER_LONG - shift); | ||
204 | } | ||
192 | /* | 205 | /* |
193 | * If we have a properly aligned and fully unreserved | 206 | * If we have a properly aligned and fully unreserved |
194 | * BITS_PER_LONG block of pages in front of us, free | 207 | * BITS_PER_LONG block of pages in front of us, free |
@@ -201,19 +214,18 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) | |||
201 | count += BITS_PER_LONG; | 214 | count += BITS_PER_LONG; |
202 | start += BITS_PER_LONG; | 215 | start += BITS_PER_LONG; |
203 | } else { | 216 | } else { |
204 | unsigned long off = 0; | 217 | unsigned long cur = start; |
205 | 218 | ||
206 | vec >>= start & (BITS_PER_LONG - 1); | 219 | start = ALIGN(start + 1, BITS_PER_LONG); |
207 | while (vec) { | 220 | while (vec && cur != start) { |
208 | if (vec & 1) { | 221 | if (vec & 1) { |
209 | page = pfn_to_page(start + off); | 222 | page = pfn_to_page(cur); |
210 | __free_pages_bootmem(page, 0); | 223 | __free_pages_bootmem(page, 0); |
211 | count++; | 224 | count++; |
212 | } | 225 | } |
213 | vec >>= 1; | 226 | vec >>= 1; |
214 | off++; | 227 | ++cur; |
215 | } | 228 | } |
216 | start = ALIGN(start + 1, BITS_PER_LONG); | ||
217 | } | 229 | } |
218 | } | 230 | } |
219 | 231 | ||
diff --git a/mm/compaction.c b/mm/compaction.c index 6b807e466497..c62bd063d766 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -816,6 +816,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone, | |||
816 | static int compact_finished(struct zone *zone, | 816 | static int compact_finished(struct zone *zone, |
817 | struct compact_control *cc) | 817 | struct compact_control *cc) |
818 | { | 818 | { |
819 | unsigned int order; | ||
819 | unsigned long watermark; | 820 | unsigned long watermark; |
820 | 821 | ||
821 | if (fatal_signal_pending(current)) | 822 | if (fatal_signal_pending(current)) |
@@ -850,22 +851,16 @@ static int compact_finished(struct zone *zone, | |||
850 | return COMPACT_CONTINUE; | 851 | return COMPACT_CONTINUE; |
851 | 852 | ||
852 | /* Direct compactor: Is a suitable page free? */ | 853 | /* Direct compactor: Is a suitable page free? */ |
853 | if (cc->page) { | 854 | for (order = cc->order; order < MAX_ORDER; order++) { |
854 | /* Was a suitable page captured? */ | 855 | struct free_area *area = &zone->free_area[order]; |
855 | if (*cc->page) | 856 | |
857 | /* Job done if page is free of the right migratetype */ | ||
858 | if (!list_empty(&area->free_list[cc->migratetype])) | ||
859 | return COMPACT_PARTIAL; | ||
860 | |||
861 | /* Job done if allocation would set block type */ | ||
862 | if (cc->order >= pageblock_order && area->nr_free) | ||
856 | return COMPACT_PARTIAL; | 863 | return COMPACT_PARTIAL; |
857 | } else { | ||
858 | unsigned int order; | ||
859 | for (order = cc->order; order < MAX_ORDER; order++) { | ||
860 | struct free_area *area = &zone->free_area[cc->order]; | ||
861 | /* Job done if page is free of the right migratetype */ | ||
862 | if (!list_empty(&area->free_list[cc->migratetype])) | ||
863 | return COMPACT_PARTIAL; | ||
864 | |||
865 | /* Job done if allocation would set block type */ | ||
866 | if (cc->order >= pageblock_order && area->nr_free) | ||
867 | return COMPACT_PARTIAL; | ||
868 | } | ||
869 | } | 864 | } |
870 | 865 | ||
871 | return COMPACT_CONTINUE; | 866 | return COMPACT_CONTINUE; |
@@ -921,60 +916,6 @@ unsigned long compaction_suitable(struct zone *zone, int order) | |||
921 | return COMPACT_CONTINUE; | 916 | return COMPACT_CONTINUE; |
922 | } | 917 | } |
923 | 918 | ||
924 | static void compact_capture_page(struct compact_control *cc) | ||
925 | { | ||
926 | unsigned long flags; | ||
927 | int mtype, mtype_low, mtype_high; | ||
928 | |||
929 | if (!cc->page || *cc->page) | ||
930 | return; | ||
931 | |||
932 | /* | ||
933 | * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP | ||
934 | * regardless of the migratetype of the freelist is is captured from. | ||
935 | * This is fine because the order for a high-order MIGRATE_MOVABLE | ||
936 | * allocation is typically at least a pageblock size and overall | ||
937 | * fragmentation is not impaired. Other allocation types must | ||
938 | * capture pages from their own migratelist because otherwise they | ||
939 | * could pollute other pageblocks like MIGRATE_MOVABLE with | ||
940 | * difficult to move pages and making fragmentation worse overall. | ||
941 | */ | ||
942 | if (cc->migratetype == MIGRATE_MOVABLE) { | ||
943 | mtype_low = 0; | ||
944 | mtype_high = MIGRATE_PCPTYPES; | ||
945 | } else { | ||
946 | mtype_low = cc->migratetype; | ||
947 | mtype_high = cc->migratetype + 1; | ||
948 | } | ||
949 | |||
950 | /* Speculatively examine the free lists without zone lock */ | ||
951 | for (mtype = mtype_low; mtype < mtype_high; mtype++) { | ||
952 | int order; | ||
953 | for (order = cc->order; order < MAX_ORDER; order++) { | ||
954 | struct page *page; | ||
955 | struct free_area *area; | ||
956 | area = &(cc->zone->free_area[order]); | ||
957 | if (list_empty(&area->free_list[mtype])) | ||
958 | continue; | ||
959 | |||
960 | /* Take the lock and attempt capture of the page */ | ||
961 | if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc)) | ||
962 | return; | ||
963 | if (!list_empty(&area->free_list[mtype])) { | ||
964 | page = list_entry(area->free_list[mtype].next, | ||
965 | struct page, lru); | ||
966 | if (capture_free_page(page, cc->order, mtype)) { | ||
967 | spin_unlock_irqrestore(&cc->zone->lock, | ||
968 | flags); | ||
969 | *cc->page = page; | ||
970 | return; | ||
971 | } | ||
972 | } | ||
973 | spin_unlock_irqrestore(&cc->zone->lock, flags); | ||
974 | } | ||
975 | } | ||
976 | } | ||
977 | |||
978 | static int compact_zone(struct zone *zone, struct compact_control *cc) | 919 | static int compact_zone(struct zone *zone, struct compact_control *cc) |
979 | { | 920 | { |
980 | int ret; | 921 | int ret; |
@@ -1054,9 +995,6 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) | |||
1054 | goto out; | 995 | goto out; |
1055 | } | 996 | } |
1056 | } | 997 | } |
1057 | |||
1058 | /* Capture a page now if it is a suitable size */ | ||
1059 | compact_capture_page(cc); | ||
1060 | } | 998 | } |
1061 | 999 | ||
1062 | out: | 1000 | out: |
@@ -1069,8 +1007,7 @@ out: | |||
1069 | 1007 | ||
1070 | static unsigned long compact_zone_order(struct zone *zone, | 1008 | static unsigned long compact_zone_order(struct zone *zone, |
1071 | int order, gfp_t gfp_mask, | 1009 | int order, gfp_t gfp_mask, |
1072 | bool sync, bool *contended, | 1010 | bool sync, bool *contended) |
1073 | struct page **page) | ||
1074 | { | 1011 | { |
1075 | unsigned long ret; | 1012 | unsigned long ret; |
1076 | struct compact_control cc = { | 1013 | struct compact_control cc = { |
@@ -1080,7 +1017,6 @@ static unsigned long compact_zone_order(struct zone *zone, | |||
1080 | .migratetype = allocflags_to_migratetype(gfp_mask), | 1017 | .migratetype = allocflags_to_migratetype(gfp_mask), |
1081 | .zone = zone, | 1018 | .zone = zone, |
1082 | .sync = sync, | 1019 | .sync = sync, |
1083 | .page = page, | ||
1084 | }; | 1020 | }; |
1085 | INIT_LIST_HEAD(&cc.freepages); | 1021 | INIT_LIST_HEAD(&cc.freepages); |
1086 | INIT_LIST_HEAD(&cc.migratepages); | 1022 | INIT_LIST_HEAD(&cc.migratepages); |
@@ -1110,7 +1046,7 @@ int sysctl_extfrag_threshold = 500; | |||
1110 | */ | 1046 | */ |
1111 | unsigned long try_to_compact_pages(struct zonelist *zonelist, | 1047 | unsigned long try_to_compact_pages(struct zonelist *zonelist, |
1112 | int order, gfp_t gfp_mask, nodemask_t *nodemask, | 1048 | int order, gfp_t gfp_mask, nodemask_t *nodemask, |
1113 | bool sync, bool *contended, struct page **page) | 1049 | bool sync, bool *contended) |
1114 | { | 1050 | { |
1115 | enum zone_type high_zoneidx = gfp_zone(gfp_mask); | 1051 | enum zone_type high_zoneidx = gfp_zone(gfp_mask); |
1116 | int may_enter_fs = gfp_mask & __GFP_FS; | 1052 | int may_enter_fs = gfp_mask & __GFP_FS; |
@@ -1136,7 +1072,7 @@ unsigned long try_to_compact_pages(struct zonelist *zonelist, | |||
1136 | int status; | 1072 | int status; |
1137 | 1073 | ||
1138 | status = compact_zone_order(zone, order, gfp_mask, sync, | 1074 | status = compact_zone_order(zone, order, gfp_mask, sync, |
1139 | contended, page); | 1075 | contended); |
1140 | rc = max(status, rc); | 1076 | rc = max(status, rc); |
1141 | 1077 | ||
1142 | /* If a normal allocation would succeed, stop compacting */ | 1078 | /* If a normal allocation would succeed, stop compacting */ |
@@ -1192,7 +1128,6 @@ int compact_pgdat(pg_data_t *pgdat, int order) | |||
1192 | struct compact_control cc = { | 1128 | struct compact_control cc = { |
1193 | .order = order, | 1129 | .order = order, |
1194 | .sync = false, | 1130 | .sync = false, |
1195 | .page = NULL, | ||
1196 | }; | 1131 | }; |
1197 | 1132 | ||
1198 | return __compact_pgdat(pgdat, &cc); | 1133 | return __compact_pgdat(pgdat, &cc); |
@@ -1203,14 +1138,13 @@ static int compact_node(int nid) | |||
1203 | struct compact_control cc = { | 1138 | struct compact_control cc = { |
1204 | .order = -1, | 1139 | .order = -1, |
1205 | .sync = true, | 1140 | .sync = true, |
1206 | .page = NULL, | ||
1207 | }; | 1141 | }; |
1208 | 1142 | ||
1209 | return __compact_pgdat(NODE_DATA(nid), &cc); | 1143 | return __compact_pgdat(NODE_DATA(nid), &cc); |
1210 | } | 1144 | } |
1211 | 1145 | ||
1212 | /* Compact all nodes in the system */ | 1146 | /* Compact all nodes in the system */ |
1213 | static int compact_nodes(void) | 1147 | static void compact_nodes(void) |
1214 | { | 1148 | { |
1215 | int nid; | 1149 | int nid; |
1216 | 1150 | ||
@@ -1219,8 +1153,6 @@ static int compact_nodes(void) | |||
1219 | 1153 | ||
1220 | for_each_online_node(nid) | 1154 | for_each_online_node(nid) |
1221 | compact_node(nid); | 1155 | compact_node(nid); |
1222 | |||
1223 | return COMPACT_COMPLETE; | ||
1224 | } | 1156 | } |
1225 | 1157 | ||
1226 | /* The written value is actually unused, all memory is compacted */ | 1158 | /* The written value is actually unused, all memory is compacted */ |
@@ -1231,7 +1163,7 @@ int sysctl_compaction_handler(struct ctl_table *table, int write, | |||
1231 | void __user *buffer, size_t *length, loff_t *ppos) | 1163 | void __user *buffer, size_t *length, loff_t *ppos) |
1232 | { | 1164 | { |
1233 | if (write) | 1165 | if (write) |
1234 | return compact_nodes(); | 1166 | compact_nodes(); |
1235 | 1167 | ||
1236 | return 0; | 1168 | return 0; |
1237 | } | 1169 | } |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 9e894edc7811..6001ee6347a9 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
@@ -1819,9 +1819,19 @@ int split_huge_page(struct page *page) | |||
1819 | 1819 | ||
1820 | BUG_ON(is_huge_zero_pfn(page_to_pfn(page))); | 1820 | BUG_ON(is_huge_zero_pfn(page_to_pfn(page))); |
1821 | BUG_ON(!PageAnon(page)); | 1821 | BUG_ON(!PageAnon(page)); |
1822 | anon_vma = page_lock_anon_vma_read(page); | 1822 | |
1823 | /* | ||
1824 | * The caller does not necessarily hold an mmap_sem that would prevent | ||
1825 | * the anon_vma disappearing so we first we take a reference to it | ||
1826 | * and then lock the anon_vma for write. This is similar to | ||
1827 | * page_lock_anon_vma_read except the write lock is taken to serialise | ||
1828 | * against parallel split or collapse operations. | ||
1829 | */ | ||
1830 | anon_vma = page_get_anon_vma(page); | ||
1823 | if (!anon_vma) | 1831 | if (!anon_vma) |
1824 | goto out; | 1832 | goto out; |
1833 | anon_vma_lock_write(anon_vma); | ||
1834 | |||
1825 | ret = 0; | 1835 | ret = 0; |
1826 | if (!PageCompound(page)) | 1836 | if (!PageCompound(page)) |
1827 | goto out_unlock; | 1837 | goto out_unlock; |
@@ -1832,7 +1842,8 @@ int split_huge_page(struct page *page) | |||
1832 | 1842 | ||
1833 | BUG_ON(PageCompound(page)); | 1843 | BUG_ON(PageCompound(page)); |
1834 | out_unlock: | 1844 | out_unlock: |
1835 | page_unlock_anon_vma_read(anon_vma); | 1845 | anon_vma_unlock(anon_vma); |
1846 | put_anon_vma(anon_vma); | ||
1836 | out: | 1847 | out: |
1837 | return ret; | 1848 | return ret; |
1838 | } | 1849 | } |
diff --git a/mm/internal.h b/mm/internal.h index d597f94cc205..9ba21100ebf3 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -135,7 +135,6 @@ struct compact_control { | |||
135 | int migratetype; /* MOVABLE, RECLAIMABLE etc */ | 135 | int migratetype; /* MOVABLE, RECLAIMABLE etc */ |
136 | struct zone *zone; | 136 | struct zone *zone; |
137 | bool contended; /* True if a lock was contended */ | 137 | bool contended; /* True if a lock was contended */ |
138 | struct page **page; /* Page captured of requested size */ | ||
139 | }; | 138 | }; |
140 | 139 | ||
141 | unsigned long | 140 | unsigned long |
diff --git a/mm/memblock.c b/mm/memblock.c index 625905523c2a..88adc8afb610 100644 --- a/mm/memblock.c +++ b/mm/memblock.c | |||
@@ -314,7 +314,8 @@ static void __init_memblock memblock_merge_regions(struct memblock_type *type) | |||
314 | } | 314 | } |
315 | 315 | ||
316 | this->size += next->size; | 316 | this->size += next->size; |
317 | memmove(next, next + 1, (type->cnt - (i + 1)) * sizeof(*next)); | 317 | /* move forward from next + 1, index of which is i + 2 */ |
318 | memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next)); | ||
318 | type->cnt--; | 319 | type->cnt--; |
319 | } | 320 | } |
320 | } | 321 | } |
diff --git a/mm/migrate.c b/mm/migrate.c index 3b676b0c5c3e..c38778610aa8 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -1679,9 +1679,21 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm, | |||
1679 | page_xchg_last_nid(new_page, page_last_nid(page)); | 1679 | page_xchg_last_nid(new_page, page_last_nid(page)); |
1680 | 1680 | ||
1681 | isolated = numamigrate_isolate_page(pgdat, page); | 1681 | isolated = numamigrate_isolate_page(pgdat, page); |
1682 | if (!isolated) { | 1682 | |
1683 | /* | ||
1684 | * Failing to isolate or a GUP pin prevents migration. The expected | ||
1685 | * page count is 2. 1 for anonymous pages without a mapping and 1 | ||
1686 | * for the callers pin. If the page was isolated, the page will | ||
1687 | * need to be put back on the LRU. | ||
1688 | */ | ||
1689 | if (!isolated || page_count(page) != 2) { | ||
1683 | count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR); | 1690 | count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR); |
1684 | put_page(new_page); | 1691 | put_page(new_page); |
1692 | if (isolated) { | ||
1693 | putback_lru_page(page); | ||
1694 | isolated = 0; | ||
1695 | goto out; | ||
1696 | } | ||
1685 | goto out_keep_locked; | 1697 | goto out_keep_locked; |
1686 | } | 1698 | } |
1687 | 1699 | ||
@@ -2886,7 +2886,7 @@ static void vm_lock_anon_vma(struct mm_struct *mm, struct anon_vma *anon_vma) | |||
2886 | * The LSB of head.next can't change from under us | 2886 | * The LSB of head.next can't change from under us |
2887 | * because we hold the mm_all_locks_mutex. | 2887 | * because we hold the mm_all_locks_mutex. |
2888 | */ | 2888 | */ |
2889 | down_write(&anon_vma->root->rwsem); | 2889 | down_write_nest_lock(&anon_vma->root->rwsem, &mm->mmap_sem); |
2890 | /* | 2890 | /* |
2891 | * We can safely modify head.next after taking the | 2891 | * We can safely modify head.next after taking the |
2892 | * anon_vma->root->rwsem. If some other vma in this mm shares | 2892 | * anon_vma->root->rwsem. If some other vma in this mm shares |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bc6cc0e913bd..df2022ff0c8a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1384,14 +1384,8 @@ void split_page(struct page *page, unsigned int order) | |||
1384 | set_page_refcounted(page + i); | 1384 | set_page_refcounted(page + i); |
1385 | } | 1385 | } |
1386 | 1386 | ||
1387 | /* | 1387 | static int __isolate_free_page(struct page *page, unsigned int order) |
1388 | * Similar to the split_page family of functions except that the page | ||
1389 | * required at the given order and being isolated now to prevent races | ||
1390 | * with parallel allocators | ||
1391 | */ | ||
1392 | int capture_free_page(struct page *page, int alloc_order, int migratetype) | ||
1393 | { | 1388 | { |
1394 | unsigned int order; | ||
1395 | unsigned long watermark; | 1389 | unsigned long watermark; |
1396 | struct zone *zone; | 1390 | struct zone *zone; |
1397 | int mt; | 1391 | int mt; |
@@ -1399,7 +1393,6 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) | |||
1399 | BUG_ON(!PageBuddy(page)); | 1393 | BUG_ON(!PageBuddy(page)); |
1400 | 1394 | ||
1401 | zone = page_zone(page); | 1395 | zone = page_zone(page); |
1402 | order = page_order(page); | ||
1403 | mt = get_pageblock_migratetype(page); | 1396 | mt = get_pageblock_migratetype(page); |
1404 | 1397 | ||
1405 | if (mt != MIGRATE_ISOLATE) { | 1398 | if (mt != MIGRATE_ISOLATE) { |
@@ -1408,7 +1401,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) | |||
1408 | if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) | 1401 | if (!zone_watermark_ok(zone, 0, watermark, 0, 0)) |
1409 | return 0; | 1402 | return 0; |
1410 | 1403 | ||
1411 | __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt); | 1404 | __mod_zone_freepage_state(zone, -(1UL << order), mt); |
1412 | } | 1405 | } |
1413 | 1406 | ||
1414 | /* Remove page from free list */ | 1407 | /* Remove page from free list */ |
@@ -1416,11 +1409,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) | |||
1416 | zone->free_area[order].nr_free--; | 1409 | zone->free_area[order].nr_free--; |
1417 | rmv_page_order(page); | 1410 | rmv_page_order(page); |
1418 | 1411 | ||
1419 | if (alloc_order != order) | 1412 | /* Set the pageblock if the isolated page is at least a pageblock */ |
1420 | expand(zone, page, alloc_order, order, | ||
1421 | &zone->free_area[order], migratetype); | ||
1422 | |||
1423 | /* Set the pageblock if the captured page is at least a pageblock */ | ||
1424 | if (order >= pageblock_order - 1) { | 1413 | if (order >= pageblock_order - 1) { |
1425 | struct page *endpage = page + (1 << order) - 1; | 1414 | struct page *endpage = page + (1 << order) - 1; |
1426 | for (; page < endpage; page += pageblock_nr_pages) { | 1415 | for (; page < endpage; page += pageblock_nr_pages) { |
@@ -1431,7 +1420,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype) | |||
1431 | } | 1420 | } |
1432 | } | 1421 | } |
1433 | 1422 | ||
1434 | return 1UL << alloc_order; | 1423 | return 1UL << order; |
1435 | } | 1424 | } |
1436 | 1425 | ||
1437 | /* | 1426 | /* |
@@ -1449,10 +1438,9 @@ int split_free_page(struct page *page) | |||
1449 | unsigned int order; | 1438 | unsigned int order; |
1450 | int nr_pages; | 1439 | int nr_pages; |
1451 | 1440 | ||
1452 | BUG_ON(!PageBuddy(page)); | ||
1453 | order = page_order(page); | 1441 | order = page_order(page); |
1454 | 1442 | ||
1455 | nr_pages = capture_free_page(page, order, 0); | 1443 | nr_pages = __isolate_free_page(page, order); |
1456 | if (!nr_pages) | 1444 | if (!nr_pages) |
1457 | return 0; | 1445 | return 0; |
1458 | 1446 | ||
@@ -2136,8 +2124,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, | |||
2136 | bool *contended_compaction, bool *deferred_compaction, | 2124 | bool *contended_compaction, bool *deferred_compaction, |
2137 | unsigned long *did_some_progress) | 2125 | unsigned long *did_some_progress) |
2138 | { | 2126 | { |
2139 | struct page *page = NULL; | ||
2140 | |||
2141 | if (!order) | 2127 | if (!order) |
2142 | return NULL; | 2128 | return NULL; |
2143 | 2129 | ||
@@ -2149,16 +2135,12 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, | |||
2149 | current->flags |= PF_MEMALLOC; | 2135 | current->flags |= PF_MEMALLOC; |
2150 | *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, | 2136 | *did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask, |
2151 | nodemask, sync_migration, | 2137 | nodemask, sync_migration, |
2152 | contended_compaction, &page); | 2138 | contended_compaction); |
2153 | current->flags &= ~PF_MEMALLOC; | 2139 | current->flags &= ~PF_MEMALLOC; |
2154 | 2140 | ||
2155 | /* If compaction captured a page, prep and use it */ | ||
2156 | if (page) { | ||
2157 | prep_new_page(page, order, gfp_mask); | ||
2158 | goto got_page; | ||
2159 | } | ||
2160 | |||
2161 | if (*did_some_progress != COMPACT_SKIPPED) { | 2141 | if (*did_some_progress != COMPACT_SKIPPED) { |
2142 | struct page *page; | ||
2143 | |||
2162 | /* Page migration frees to the PCP lists but we want merging */ | 2144 | /* Page migration frees to the PCP lists but we want merging */ |
2163 | drain_pages(get_cpu()); | 2145 | drain_pages(get_cpu()); |
2164 | put_cpu(); | 2146 | put_cpu(); |
@@ -2168,7 +2150,6 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, | |||
2168 | alloc_flags & ~ALLOC_NO_WATERMARKS, | 2150 | alloc_flags & ~ALLOC_NO_WATERMARKS, |
2169 | preferred_zone, migratetype); | 2151 | preferred_zone, migratetype); |
2170 | if (page) { | 2152 | if (page) { |
2171 | got_page: | ||
2172 | preferred_zone->compact_blockskip_flush = false; | 2153 | preferred_zone->compact_blockskip_flush = false; |
2173 | preferred_zone->compact_considered = 0; | 2154 | preferred_zone->compact_considered = 0; |
2174 | preferred_zone->compact_defer_shift = 0; | 2155 | preferred_zone->compact_defer_shift = 0; |
@@ -5604,7 +5585,7 @@ static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) | |||
5604 | pfn &= (PAGES_PER_SECTION-1); | 5585 | pfn &= (PAGES_PER_SECTION-1); |
5605 | return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; | 5586 | return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; |
5606 | #else | 5587 | #else |
5607 | pfn = pfn - zone->zone_start_pfn; | 5588 | pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages); |
5608 | return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; | 5589 | return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS; |
5609 | #endif /* CONFIG_SPARSEMEM */ | 5590 | #endif /* CONFIG_SPARSEMEM */ |
5610 | } | 5591 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index 515473ee52cb..f64e439b4a00 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -6121,6 +6121,14 @@ struct netdev_queue *dev_ingress_queue_create(struct net_device *dev) | |||
6121 | 6121 | ||
6122 | static const struct ethtool_ops default_ethtool_ops; | 6122 | static const struct ethtool_ops default_ethtool_ops; |
6123 | 6123 | ||
6124 | void netdev_set_default_ethtool_ops(struct net_device *dev, | ||
6125 | const struct ethtool_ops *ops) | ||
6126 | { | ||
6127 | if (dev->ethtool_ops == &default_ethtool_ops) | ||
6128 | dev->ethtool_ops = ops; | ||
6129 | } | ||
6130 | EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops); | ||
6131 | |||
6124 | /** | 6132 | /** |
6125 | * alloc_netdev_mqs - allocate network device | 6133 | * alloc_netdev_mqs - allocate network device |
6126 | * @sizeof_priv: size of private data to allocate space for | 6134 | * @sizeof_priv: size of private data to allocate space for |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 3c9d20880283..d9c4f113d709 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -590,7 +590,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
590 | case IP_TTL: | 590 | case IP_TTL: |
591 | if (optlen < 1) | 591 | if (optlen < 1) |
592 | goto e_inval; | 592 | goto e_inval; |
593 | if (val != -1 && (val < 0 || val > 255)) | 593 | if (val != -1 && (val < 1 || val > 255)) |
594 | goto e_inval; | 594 | goto e_inval; |
595 | inet->uc_ttl = val; | 595 | inet->uc_ttl = val; |
596 | break; | 596 | break; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 1ca253635f7a..2aa69c8ae60c 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -1428,12 +1428,12 @@ static void tcp_service_net_dma(struct sock *sk, bool wait) | |||
1428 | } | 1428 | } |
1429 | #endif | 1429 | #endif |
1430 | 1430 | ||
1431 | static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) | 1431 | static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) |
1432 | { | 1432 | { |
1433 | struct sk_buff *skb; | 1433 | struct sk_buff *skb; |
1434 | u32 offset; | 1434 | u32 offset; |
1435 | 1435 | ||
1436 | skb_queue_walk(&sk->sk_receive_queue, skb) { | 1436 | while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { |
1437 | offset = seq - TCP_SKB_CB(skb)->seq; | 1437 | offset = seq - TCP_SKB_CB(skb)->seq; |
1438 | if (tcp_hdr(skb)->syn) | 1438 | if (tcp_hdr(skb)->syn) |
1439 | offset--; | 1439 | offset--; |
@@ -1441,6 +1441,11 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off) | |||
1441 | *off = offset; | 1441 | *off = offset; |
1442 | return skb; | 1442 | return skb; |
1443 | } | 1443 | } |
1444 | /* This looks weird, but this can happen if TCP collapsing | ||
1445 | * splitted a fat GRO packet, while we released socket lock | ||
1446 | * in skb_splice_bits() | ||
1447 | */ | ||
1448 | sk_eat_skb(sk, skb, false); | ||
1444 | } | 1449 | } |
1445 | return NULL; | 1450 | return NULL; |
1446 | } | 1451 | } |
@@ -1482,7 +1487,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1482 | break; | 1487 | break; |
1483 | } | 1488 | } |
1484 | used = recv_actor(desc, skb, offset, len); | 1489 | used = recv_actor(desc, skb, offset, len); |
1485 | if (used < 0) { | 1490 | if (used <= 0) { |
1486 | if (!copied) | 1491 | if (!copied) |
1487 | copied = used; | 1492 | copied = used; |
1488 | break; | 1493 | break; |
@@ -1520,8 +1525,10 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1520 | tcp_rcv_space_adjust(sk); | 1525 | tcp_rcv_space_adjust(sk); |
1521 | 1526 | ||
1522 | /* Clean up data we have read: This will do ACK frames. */ | 1527 | /* Clean up data we have read: This will do ACK frames. */ |
1523 | if (copied > 0) | 1528 | if (copied > 0) { |
1529 | tcp_recv_skb(sk, seq, &offset); | ||
1524 | tcp_cleanup_rbuf(sk, copied); | 1530 | tcp_cleanup_rbuf(sk, copied); |
1531 | } | ||
1525 | return copied; | 1532 | return copied; |
1526 | } | 1533 | } |
1527 | EXPORT_SYMBOL(tcp_read_sock); | 1534 | EXPORT_SYMBOL(tcp_read_sock); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index a28e4db8a952..18f97ca76b00 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -5543,7 +5543,7 @@ slow_path: | |||
5543 | if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) | 5543 | if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb)) |
5544 | goto csum_error; | 5544 | goto csum_error; |
5545 | 5545 | ||
5546 | if (!th->ack) | 5546 | if (!th->ack && !th->rst) |
5547 | goto discard; | 5547 | goto discard; |
5548 | 5548 | ||
5549 | /* | 5549 | /* |
@@ -5988,7 +5988,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5988 | goto discard; | 5988 | goto discard; |
5989 | } | 5989 | } |
5990 | 5990 | ||
5991 | if (!th->ack) | 5991 | if (!th->ack && !th->rst) |
5992 | goto discard; | 5992 | goto discard; |
5993 | 5993 | ||
5994 | if (!tcp_validate_incoming(sk, skb, th, 0)) | 5994 | if (!tcp_validate_incoming(sk, skb, th, 0)) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 408cac4ae00a..420e56326384 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -154,6 +154,11 @@ static void addrconf_type_change(struct net_device *dev, | |||
154 | unsigned long event); | 154 | unsigned long event); |
155 | static int addrconf_ifdown(struct net_device *dev, int how); | 155 | static int addrconf_ifdown(struct net_device *dev, int how); |
156 | 156 | ||
157 | static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | ||
158 | int plen, | ||
159 | const struct net_device *dev, | ||
160 | u32 flags, u32 noflags); | ||
161 | |||
157 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); | 162 | static void addrconf_dad_start(struct inet6_ifaddr *ifp); |
158 | static void addrconf_dad_timer(unsigned long data); | 163 | static void addrconf_dad_timer(unsigned long data); |
159 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); | 164 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp); |
@@ -250,12 +255,6 @@ static inline bool addrconf_qdisc_ok(const struct net_device *dev) | |||
250 | return !qdisc_tx_is_noop(dev); | 255 | return !qdisc_tx_is_noop(dev); |
251 | } | 256 | } |
252 | 257 | ||
253 | /* Check if a route is valid prefix route */ | ||
254 | static inline int addrconf_is_prefix_route(const struct rt6_info *rt) | ||
255 | { | ||
256 | return (rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0; | ||
257 | } | ||
258 | |||
259 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) | 258 | static void addrconf_del_timer(struct inet6_ifaddr *ifp) |
260 | { | 259 | { |
261 | if (del_timer(&ifp->timer)) | 260 | if (del_timer(&ifp->timer)) |
@@ -941,17 +940,15 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
941 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { | 940 | if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { |
942 | struct in6_addr prefix; | 941 | struct in6_addr prefix; |
943 | struct rt6_info *rt; | 942 | struct rt6_info *rt; |
944 | struct net *net = dev_net(ifp->idev->dev); | ||
945 | struct flowi6 fl6 = {}; | ||
946 | 943 | ||
947 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); | 944 | ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); |
948 | fl6.flowi6_oif = ifp->idev->dev->ifindex; | ||
949 | fl6.daddr = prefix; | ||
950 | rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, | ||
951 | RT6_LOOKUP_F_IFACE); | ||
952 | 945 | ||
953 | if (rt != net->ipv6.ip6_null_entry && | 946 | rt = addrconf_get_prefix_route(&prefix, |
954 | addrconf_is_prefix_route(rt)) { | 947 | ifp->prefix_len, |
948 | ifp->idev->dev, | ||
949 | 0, RTF_GATEWAY | RTF_DEFAULT); | ||
950 | |||
951 | if (rt) { | ||
955 | if (onlink == 0) { | 952 | if (onlink == 0) { |
956 | ip6_del_rt(rt); | 953 | ip6_del_rt(rt); |
957 | rt = NULL; | 954 | rt = NULL; |
@@ -1877,7 +1874,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | |||
1877 | continue; | 1874 | continue; |
1878 | if ((rt->rt6i_flags & flags) != flags) | 1875 | if ((rt->rt6i_flags & flags) != flags) |
1879 | continue; | 1876 | continue; |
1880 | if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) | 1877 | if ((rt->rt6i_flags & noflags) != 0) |
1881 | continue; | 1878 | continue; |
1882 | dst_hold(&rt->dst); | 1879 | dst_hold(&rt->dst); |
1883 | break; | 1880 | break; |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 3ad1f9db5f8b..df082508362d 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -1806,7 +1806,7 @@ static void iucv_external_interrupt(struct ext_code ext_code, | |||
1806 | struct iucv_irq_data *p; | 1806 | struct iucv_irq_data *p; |
1807 | struct iucv_irq_list *work; | 1807 | struct iucv_irq_list *work; |
1808 | 1808 | ||
1809 | kstat_cpu(smp_processor_id()).irqs[EXTINT_IUC]++; | 1809 | inc_irq_stat(IRQEXT_IUC); |
1810 | p = iucv_irq_data[smp_processor_id()]; | 1810 | p = iucv_irq_data[smp_processor_id()]; |
1811 | if (p->ippathid >= iucv_max_pathid) { | 1811 | if (p->ippathid >= iucv_max_pathid) { |
1812 | WARN_ON(p->ippathid >= iucv_max_pathid); | 1812 | WARN_ON(p->ippathid >= iucv_max_pathid); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 5c61677487cf..47e0aca614b7 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1009,6 +1009,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1009 | if (old_probe_resp) | 1009 | if (old_probe_resp) |
1010 | kfree_rcu(old_probe_resp, rcu_head); | 1010 | kfree_rcu(old_probe_resp, rcu_head); |
1011 | 1011 | ||
1012 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
1013 | sta_info_flush(local, vlan); | ||
1012 | sta_info_flush(local, sdata); | 1014 | sta_info_flush(local, sdata); |
1013 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 1015 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
1014 | 1016 | ||
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 53f03120db55..80e55527504b 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | #include <linux/nl80211.h> | 5 | #include <linux/nl80211.h> |
6 | #include <linux/export.h> | 6 | #include <linux/export.h> |
7 | #include <linux/rtnetlink.h> | ||
7 | #include <net/cfg80211.h> | 8 | #include <net/cfg80211.h> |
8 | #include "ieee80211_i.h" | 9 | #include "ieee80211_i.h" |
9 | #include "driver-ops.h" | 10 | #include "driver-ops.h" |
@@ -197,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
197 | 198 | ||
198 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | 199 | ctx = container_of(conf, struct ieee80211_chanctx, conf); |
199 | 200 | ||
201 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
202 | struct ieee80211_sub_if_data *vlan; | ||
203 | |||
204 | /* for the VLAN list */ | ||
205 | ASSERT_RTNL(); | ||
206 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
207 | rcu_assign_pointer(vlan->vif.chanctx_conf, NULL); | ||
208 | } | ||
209 | |||
200 | ieee80211_unassign_vif_chanctx(sdata, ctx); | 210 | ieee80211_unassign_vif_chanctx(sdata, ctx); |
201 | if (ctx->refcount == 0) | 211 | if (ctx->refcount == 0) |
202 | ieee80211_free_chanctx(local, ctx); | 212 | ieee80211_free_chanctx(local, ctx); |
@@ -316,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
316 | goto out; | 326 | goto out; |
317 | } | 327 | } |
318 | 328 | ||
329 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
330 | struct ieee80211_sub_if_data *vlan; | ||
331 | |||
332 | /* for the VLAN list */ | ||
333 | ASSERT_RTNL(); | ||
334 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
335 | rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf); | ||
336 | } | ||
337 | |||
319 | ieee80211_recalc_smps_chanctx(local, ctx); | 338 | ieee80211_recalc_smps_chanctx(local, ctx); |
320 | out: | 339 | out: |
321 | mutex_unlock(&local->chanctx_mtx); | 340 | mutex_unlock(&local->chanctx_mtx); |
@@ -331,6 +350,25 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
331 | mutex_unlock(&sdata->local->chanctx_mtx); | 350 | mutex_unlock(&sdata->local->chanctx_mtx); |
332 | } | 351 | } |
333 | 352 | ||
353 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata) | ||
354 | { | ||
355 | struct ieee80211_local *local = sdata->local; | ||
356 | struct ieee80211_sub_if_data *ap; | ||
357 | struct ieee80211_chanctx_conf *conf; | ||
358 | |||
359 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss)) | ||
360 | return; | ||
361 | |||
362 | ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); | ||
363 | |||
364 | mutex_lock(&local->chanctx_mtx); | ||
365 | |||
366 | conf = rcu_dereference_protected(ap->vif.chanctx_conf, | ||
367 | lockdep_is_held(&local->chanctx_mtx)); | ||
368 | rcu_assign_pointer(sdata->vif.chanctx_conf, conf); | ||
369 | mutex_unlock(&local->chanctx_mtx); | ||
370 | } | ||
371 | |||
334 | void ieee80211_iter_chan_contexts_atomic( | 372 | void ieee80211_iter_chan_contexts_atomic( |
335 | struct ieee80211_hw *hw, | 373 | struct ieee80211_hw *hw, |
336 | void (*iter)(struct ieee80211_hw *hw, | 374 | void (*iter)(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 8881fc77fb13..6b7644e818d8 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
703 | sdata_info(sdata, | 703 | sdata_info(sdata, |
704 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); | 704 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); |
705 | 705 | ||
706 | ieee80211_request_internal_scan(sdata, | 706 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, |
707 | ifibss->ssid, ifibss->ssid_len, NULL); | 707 | NULL); |
708 | } | 708 | } |
709 | 709 | ||
710 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 710 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -802,9 +802,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
802 | IEEE80211_SCAN_INTERVAL)) { | 802 | IEEE80211_SCAN_INTERVAL)) { |
803 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); | 803 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); |
804 | 804 | ||
805 | ieee80211_request_internal_scan(sdata, | 805 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, |
806 | ifibss->ssid, ifibss->ssid_len, | 806 | ifibss->ssid_len, chan); |
807 | ifibss->fixed_channel ? ifibss->channel : NULL); | ||
808 | } else { | 807 | } else { |
809 | int interval = IEEE80211_SCAN_INTERVAL; | 808 | int interval = IEEE80211_SCAN_INTERVAL; |
810 | 809 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 42d0d0267730..8563b9a5cac3 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -92,8 +92,6 @@ struct ieee80211_bss { | |||
92 | 92 | ||
93 | u32 device_ts; | 93 | u32 device_ts; |
94 | 94 | ||
95 | u8 dtim_period; | ||
96 | |||
97 | bool wmm_used; | 95 | bool wmm_used; |
98 | bool uapsd_supported; | 96 | bool uapsd_supported; |
99 | 97 | ||
@@ -140,7 +138,6 @@ enum ieee80211_bss_corrupt_data_flags { | |||
140 | 138 | ||
141 | /** | 139 | /** |
142 | * enum ieee80211_valid_data_flags - BSS valid data flags | 140 | * enum ieee80211_valid_data_flags - BSS valid data flags |
143 | * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE | ||
144 | * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE | 141 | * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE |
145 | * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE | 142 | * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE |
146 | * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE | 143 | * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE |
@@ -151,7 +148,6 @@ enum ieee80211_bss_corrupt_data_flags { | |||
151 | * beacon/probe response. | 148 | * beacon/probe response. |
152 | */ | 149 | */ |
153 | enum ieee80211_bss_valid_data_flags { | 150 | enum ieee80211_bss_valid_data_flags { |
154 | IEEE80211_BSS_VALID_DTIM = BIT(0), | ||
155 | IEEE80211_BSS_VALID_WMM = BIT(1), | 151 | IEEE80211_BSS_VALID_WMM = BIT(1), |
156 | IEEE80211_BSS_VALID_RATES = BIT(2), | 152 | IEEE80211_BSS_VALID_RATES = BIT(2), |
157 | IEEE80211_BSS_VALID_ERP = BIT(3) | 153 | IEEE80211_BSS_VALID_ERP = BIT(3) |
@@ -440,6 +436,7 @@ struct ieee80211_if_managed { | |||
440 | unsigned long timers_running; /* used for quiesce/restart */ | 436 | unsigned long timers_running; /* used for quiesce/restart */ |
441 | bool powersave; /* powersave requested for this iface */ | 437 | bool powersave; /* powersave requested for this iface */ |
442 | bool broken_ap; /* AP is broken -- turn off powersave */ | 438 | bool broken_ap; /* AP is broken -- turn off powersave */ |
439 | u8 dtim_period; | ||
443 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 440 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
444 | driver_smps_mode; /* smps mode request */ | 441 | driver_smps_mode; /* smps mode request */ |
445 | 442 | ||
@@ -773,6 +770,10 @@ struct ieee80211_sub_if_data { | |||
773 | u32 mntr_flags; | 770 | u32 mntr_flags; |
774 | } u; | 771 | } u; |
775 | 772 | ||
773 | spinlock_t cleanup_stations_lock; | ||
774 | struct list_head cleanup_stations; | ||
775 | struct work_struct cleanup_stations_wk; | ||
776 | |||
776 | #ifdef CONFIG_MAC80211_DEBUGFS | 777 | #ifdef CONFIG_MAC80211_DEBUGFS |
777 | struct { | 778 | struct { |
778 | struct dentry *dir; | 779 | struct dentry *dir; |
@@ -1329,9 +1330,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1329 | 1330 | ||
1330 | /* scan/BSS handling */ | 1331 | /* scan/BSS handling */ |
1331 | void ieee80211_scan_work(struct work_struct *work); | 1332 | void ieee80211_scan_work(struct work_struct *work); |
1332 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 1333 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
1333 | const u8 *ssid, u8 ssid_len, | 1334 | const u8 *ssid, u8 ssid_len, |
1334 | struct ieee80211_channel *chan); | 1335 | struct ieee80211_channel *chan); |
1335 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1336 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1336 | struct cfg80211_scan_request *req); | 1337 | struct cfg80211_scan_request *req); |
1337 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1338 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
@@ -1628,6 +1629,7 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
1628 | const struct cfg80211_chan_def *chandef, | 1629 | const struct cfg80211_chan_def *chandef, |
1629 | enum ieee80211_chanctx_mode mode); | 1630 | enum ieee80211_chanctx_mode mode); |
1630 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1631 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1632 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); | ||
1631 | 1633 | ||
1632 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 1634 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
1633 | struct ieee80211_chanctx *chanctx); | 1635 | struct ieee80211_chanctx *chanctx); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 09a80b55cf5a..8be854e86cd9 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -207,17 +207,8 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) | |||
207 | 207 | ||
208 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 208 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
209 | { | 209 | { |
210 | int meshhdrlen; | 210 | if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) |
211 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
212 | |||
213 | meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; | ||
214 | |||
215 | /* FIX: what would be proper limits for MTU? | ||
216 | * This interface uses 802.3 frames. */ | ||
217 | if (new_mtu < 256 || | ||
218 | new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { | ||
219 | return -EINVAL; | 211 | return -EINVAL; |
220 | } | ||
221 | 212 | ||
222 | dev->mtu = new_mtu; | 213 | dev->mtu = new_mtu; |
223 | return 0; | 214 | return 0; |
@@ -586,11 +577,13 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
586 | 577 | ||
587 | switch (sdata->vif.type) { | 578 | switch (sdata->vif.type) { |
588 | case NL80211_IFTYPE_AP_VLAN: | 579 | case NL80211_IFTYPE_AP_VLAN: |
589 | /* no need to tell driver, but set carrier */ | 580 | /* no need to tell driver, but set carrier and chanctx */ |
590 | if (rtnl_dereference(sdata->bss->beacon)) | 581 | if (rtnl_dereference(sdata->bss->beacon)) { |
582 | ieee80211_vif_vlan_copy_chanctx(sdata); | ||
591 | netif_carrier_on(dev); | 583 | netif_carrier_on(dev); |
592 | else | 584 | } else { |
593 | netif_carrier_off(dev); | 585 | netif_carrier_off(dev); |
586 | } | ||
594 | break; | 587 | break; |
595 | case NL80211_IFTYPE_MONITOR: | 588 | case NL80211_IFTYPE_MONITOR: |
596 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | 589 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { |
@@ -839,6 +832,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
839 | switch (sdata->vif.type) { | 832 | switch (sdata->vif.type) { |
840 | case NL80211_IFTYPE_AP_VLAN: | 833 | case NL80211_IFTYPE_AP_VLAN: |
841 | list_del(&sdata->u.vlan.list); | 834 | list_del(&sdata->u.vlan.list); |
835 | rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); | ||
842 | /* no need to tell driver */ | 836 | /* no need to tell driver */ |
843 | break; | 837 | break; |
844 | case NL80211_IFTYPE_MONITOR: | 838 | case NL80211_IFTYPE_MONITOR: |
@@ -865,20 +859,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
865 | cancel_work_sync(&sdata->work); | 859 | cancel_work_sync(&sdata->work); |
866 | /* | 860 | /* |
867 | * When we get here, the interface is marked down. | 861 | * When we get here, the interface is marked down. |
868 | * Call rcu_barrier() to wait both for the RX path | 862 | * Call synchronize_rcu() to wait for the RX path |
869 | * should it be using the interface and enqueuing | 863 | * should it be using the interface and enqueuing |
870 | * frames at this very time on another CPU, and | 864 | * frames at this very time on another CPU. |
871 | * for the sta free call_rcu callbacks. | ||
872 | */ | ||
873 | rcu_barrier(); | ||
874 | |||
875 | /* | ||
876 | * free_sta_rcu() enqueues a work for the actual | ||
877 | * sta cleanup, so we need to flush it while | ||
878 | * sdata is still valid. | ||
879 | */ | 865 | */ |
880 | flush_workqueue(local->workqueue); | 866 | synchronize_rcu(); |
881 | |||
882 | skb_queue_purge(&sdata->skb_queue); | 867 | skb_queue_purge(&sdata->skb_queue); |
883 | 868 | ||
884 | /* | 869 | /* |
@@ -1498,6 +1483,15 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1498 | mutex_unlock(&local->iflist_mtx); | 1483 | mutex_unlock(&local->iflist_mtx); |
1499 | } | 1484 | } |
1500 | 1485 | ||
1486 | static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) | ||
1487 | { | ||
1488 | struct ieee80211_sub_if_data *sdata; | ||
1489 | |||
1490 | sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); | ||
1491 | |||
1492 | ieee80211_cleanup_sdata_stas(sdata); | ||
1493 | } | ||
1494 | |||
1501 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 1495 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
1502 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1496 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1503 | struct vif_params *params) | 1497 | struct vif_params *params) |
@@ -1573,6 +1567,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1573 | 1567 | ||
1574 | INIT_LIST_HEAD(&sdata->key_list); | 1568 | INIT_LIST_HEAD(&sdata->key_list); |
1575 | 1569 | ||
1570 | spin_lock_init(&sdata->cleanup_stations_lock); | ||
1571 | INIT_LIST_HEAD(&sdata->cleanup_stations); | ||
1572 | INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); | ||
1573 | |||
1576 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1574 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
1577 | struct ieee80211_supported_band *sband; | 1575 | struct ieee80211_supported_band *sband; |
1578 | sband = local->hw.wiphy->bands[i]; | 1576 | sband = local->hw.wiphy->bands[i]; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 1bf03f9ff3ba..649ad513547f 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -163,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | |||
163 | return -ENOMEM; | 163 | return -ENOMEM; |
164 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; | 164 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
165 | for (i = 0; i < RMC_BUCKETS; i++) | 165 | for (i = 0; i < RMC_BUCKETS; i++) |
166 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); | 166 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); |
167 | return 0; | 167 | return 0; |
168 | } | 168 | } |
169 | 169 | ||
@@ -177,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
177 | return; | 177 | return; |
178 | 178 | ||
179 | for (i = 0; i < RMC_BUCKETS; i++) | 179 | for (i = 0; i < RMC_BUCKETS; i++) |
180 | list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { | 180 | list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { |
181 | list_del(&p->list); | 181 | list_del(&p->list); |
182 | kmem_cache_free(rm_cache, p); | 182 | kmem_cache_free(rm_cache, p); |
183 | } | 183 | } |
@@ -210,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
210 | /* Don't care about endianness since only match matters */ | 210 | /* Don't care about endianness since only match matters */ |
211 | memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); | 211 | memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); |
212 | idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; | 212 | idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; |
213 | list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { | 213 | list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { |
214 | ++entries; | 214 | ++entries; |
215 | if (time_after(jiffies, p->exp_time) || | 215 | if (time_after(jiffies, p->exp_time) || |
216 | (entries == RMC_QUEUE_MAX_LEN)) { | 216 | (entries == RMC_QUEUE_MAX_LEN)) { |
@@ -229,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
229 | p->seqnum = seqnum; | 229 | p->seqnum = seqnum; |
230 | p->exp_time = jiffies + RMC_TIMEOUT; | 230 | p->exp_time = jiffies + RMC_TIMEOUT; |
231 | memcpy(p->sa, sa, ETH_ALEN); | 231 | memcpy(p->sa, sa, ETH_ALEN); |
232 | list_add(&p->list, &rmc->bucket[idx].list); | 232 | list_add(&p->list, &rmc->bucket[idx]); |
233 | return 0; | 233 | return 0; |
234 | } | 234 | } |
235 | 235 | ||
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7c9215fb2ac8..84c28c6101cd 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -184,7 +184,7 @@ struct rmc_entry { | |||
184 | }; | 184 | }; |
185 | 185 | ||
186 | struct mesh_rmc { | 186 | struct mesh_rmc { |
187 | struct rmc_entry bucket[RMC_BUCKETS]; | 187 | struct list_head bucket[RMC_BUCKETS]; |
188 | u32 idx_mask; | 188 | u32 idx_mask; |
189 | }; | 189 | }; |
190 | 190 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 7753a9ca98a6..a3552929a21d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1074,12 +1074,8 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1074 | if (beaconint_us > latency) { | 1074 | if (beaconint_us > latency) { |
1075 | local->ps_sdata = NULL; | 1075 | local->ps_sdata = NULL; |
1076 | } else { | 1076 | } else { |
1077 | struct ieee80211_bss *bss; | ||
1078 | int maxslp = 1; | 1077 | int maxslp = 1; |
1079 | u8 dtimper; | 1078 | u8 dtimper = found->u.mgd.dtim_period; |
1080 | |||
1081 | bss = (void *)found->u.mgd.associated->priv; | ||
1082 | dtimper = bss->dtim_period; | ||
1083 | 1079 | ||
1084 | /* If the TIM IE is invalid, pretend the value is 1 */ | 1080 | /* If the TIM IE is invalid, pretend the value is 1 */ |
1085 | if (!dtimper) | 1081 | if (!dtimper) |
@@ -1410,10 +1406,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1410 | 1406 | ||
1411 | ieee80211_led_assoc(local, 1); | 1407 | ieee80211_led_assoc(local, 1); |
1412 | 1408 | ||
1413 | if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) | 1409 | if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { |
1414 | bss_conf->dtim_period = bss->dtim_period; | 1410 | /* |
1415 | else | 1411 | * If the AP is buggy we may get here with no DTIM period |
1412 | * known, so assume it's 1 which is the only safe assumption | ||
1413 | * in that case, although if the TIM IE is broken powersave | ||
1414 | * probably just won't work at all. | ||
1415 | */ | ||
1416 | bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; | ||
1417 | } else { | ||
1416 | bss_conf->dtim_period = 0; | 1418 | bss_conf->dtim_period = 0; |
1419 | } | ||
1417 | 1420 | ||
1418 | bss_conf->assoc = 1; | 1421 | bss_conf->assoc = 1; |
1419 | 1422 | ||
@@ -1562,6 +1565,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1562 | 1565 | ||
1563 | sdata->u.mgd.timers_running = 0; | 1566 | sdata->u.mgd.timers_running = 0; |
1564 | 1567 | ||
1568 | sdata->vif.bss_conf.dtim_period = 0; | ||
1569 | |||
1565 | ifmgd->flags = 0; | 1570 | ifmgd->flags = 0; |
1566 | ieee80211_vif_release_channel(sdata); | 1571 | ieee80211_vif_release_channel(sdata); |
1567 | } | 1572 | } |
@@ -2373,11 +2378,18 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2373 | struct ieee80211_channel *channel; | 2378 | struct ieee80211_channel *channel; |
2374 | bool need_ps = false; | 2379 | bool need_ps = false; |
2375 | 2380 | ||
2376 | if (sdata->u.mgd.associated && | 2381 | if ((sdata->u.mgd.associated && |
2377 | ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) { | 2382 | ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || |
2378 | bss = (void *)sdata->u.mgd.associated->priv; | 2383 | (sdata->u.mgd.assoc_data && |
2384 | ether_addr_equal(mgmt->bssid, | ||
2385 | sdata->u.mgd.assoc_data->bss->bssid))) { | ||
2379 | /* not previously set so we may need to recalc */ | 2386 | /* not previously set so we may need to recalc */ |
2380 | need_ps = !bss->dtim_period; | 2387 | need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period; |
2388 | |||
2389 | if (elems->tim && !elems->parse_error) { | ||
2390 | struct ieee80211_tim_ie *tim_ie = elems->tim; | ||
2391 | sdata->u.mgd.dtim_period = tim_ie->dtim_period; | ||
2392 | } | ||
2381 | } | 2393 | } |
2382 | 2394 | ||
2383 | if (elems->ds_params && elems->ds_params_len == 1) | 2395 | if (elems->ds_params && elems->ds_params_len == 1) |
@@ -3896,20 +3908,41 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3896 | /* kick off associate process */ | 3908 | /* kick off associate process */ |
3897 | 3909 | ||
3898 | ifmgd->assoc_data = assoc_data; | 3910 | ifmgd->assoc_data = assoc_data; |
3911 | ifmgd->dtim_period = 0; | ||
3899 | 3912 | ||
3900 | err = ieee80211_prep_connection(sdata, req->bss, true); | 3913 | err = ieee80211_prep_connection(sdata, req->bss, true); |
3901 | if (err) | 3914 | if (err) |
3902 | goto err_clear; | 3915 | goto err_clear; |
3903 | 3916 | ||
3904 | if (!bss->dtim_period && | 3917 | if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { |
3905 | sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { | 3918 | const struct cfg80211_bss_ies *beacon_ies; |
3906 | /* | 3919 | |
3907 | * Wait up to one beacon interval ... | 3920 | rcu_read_lock(); |
3908 | * should this be more if we miss one? | 3921 | beacon_ies = rcu_dereference(req->bss->beacon_ies); |
3909 | */ | 3922 | if (!beacon_ies) { |
3910 | sdata_info(sdata, "waiting for beacon from %pM\n", | 3923 | /* |
3911 | ifmgd->bssid); | 3924 | * Wait up to one beacon interval ... |
3912 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); | 3925 | * should this be more if we miss one? |
3926 | */ | ||
3927 | sdata_info(sdata, "waiting for beacon from %pM\n", | ||
3928 | ifmgd->bssid); | ||
3929 | assoc_data->timeout = | ||
3930 | TU_TO_EXP_TIME(req->bss->beacon_interval); | ||
3931 | } else { | ||
3932 | const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, | ||
3933 | beacon_ies->data, | ||
3934 | beacon_ies->len); | ||
3935 | if (tim_ie && tim_ie[1] >= | ||
3936 | sizeof(struct ieee80211_tim_ie)) { | ||
3937 | const struct ieee80211_tim_ie *tim; | ||
3938 | tim = (void *)(tim_ie + 2); | ||
3939 | ifmgd->dtim_period = tim->dtim_period; | ||
3940 | } | ||
3941 | assoc_data->have_beacon = true; | ||
3942 | assoc_data->sent_assoc = false; | ||
3943 | assoc_data->timeout = jiffies; | ||
3944 | } | ||
3945 | rcu_read_unlock(); | ||
3913 | } else { | 3946 | } else { |
3914 | assoc_data->have_beacon = true; | 3947 | assoc_data->have_beacon = true; |
3915 | assoc_data->sent_assoc = false; | 3948 | assoc_data->sent_assoc = false; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8ed83dcc149f..d59fc6818b1c 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -113,18 +113,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
113 | bss->valid_data |= IEEE80211_BSS_VALID_ERP; | 113 | bss->valid_data |= IEEE80211_BSS_VALID_ERP; |
114 | } | 114 | } |
115 | 115 | ||
116 | if (elems->tim && (!elems->parse_error || | ||
117 | !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) { | ||
118 | struct ieee80211_tim_ie *tim_ie = elems->tim; | ||
119 | bss->dtim_period = tim_ie->dtim_period; | ||
120 | if (!elems->parse_error) | ||
121 | bss->valid_data |= IEEE80211_BSS_VALID_DTIM; | ||
122 | } | ||
123 | |||
124 | /* If the beacon had no TIM IE, or it was invalid, use 1 */ | ||
125 | if (beacon && !bss->dtim_period) | ||
126 | bss->dtim_period = 1; | ||
127 | |||
128 | /* replace old supported rates if we get new values */ | 116 | /* replace old supported rates if we get new values */ |
129 | if (!elems->parse_error || | 117 | if (!elems->parse_error || |
130 | !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) { | 118 | !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) { |
@@ -832,9 +820,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
832 | return res; | 820 | return res; |
833 | } | 821 | } |
834 | 822 | ||
835 | int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | 823 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
836 | const u8 *ssid, u8 ssid_len, | 824 | const u8 *ssid, u8 ssid_len, |
837 | struct ieee80211_channel *chan) | 825 | struct ieee80211_channel *chan) |
838 | { | 826 | { |
839 | struct ieee80211_local *local = sdata->local; | 827 | struct ieee80211_local *local = sdata->local; |
840 | int ret = -EBUSY; | 828 | int ret = -EBUSY; |
@@ -848,22 +836,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
848 | 836 | ||
849 | /* fill internal scan request */ | 837 | /* fill internal scan request */ |
850 | if (!chan) { | 838 | if (!chan) { |
851 | int i, nchan = 0; | 839 | int i, max_n; |
840 | int n_ch = 0; | ||
852 | 841 | ||
853 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 842 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
854 | if (!local->hw.wiphy->bands[band]) | 843 | if (!local->hw.wiphy->bands[band]) |
855 | continue; | 844 | continue; |
856 | for (i = 0; | 845 | |
857 | i < local->hw.wiphy->bands[band]->n_channels; | 846 | max_n = local->hw.wiphy->bands[band]->n_channels; |
858 | i++) { | 847 | for (i = 0; i < max_n; i++) { |
859 | local->int_scan_req->channels[nchan] = | 848 | struct ieee80211_channel *tmp_ch = |
860 | &local->hw.wiphy->bands[band]->channels[i]; | 849 | &local->hw.wiphy->bands[band]->channels[i]; |
861 | nchan++; | 850 | |
851 | if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | | ||
852 | IEEE80211_CHAN_DISABLED)) | ||
853 | continue; | ||
854 | |||
855 | local->int_scan_req->channels[n_ch] = tmp_ch; | ||
856 | n_ch++; | ||
862 | } | 857 | } |
863 | } | 858 | } |
864 | 859 | ||
865 | local->int_scan_req->n_channels = nchan; | 860 | if (WARN_ON_ONCE(n_ch == 0)) |
861 | goto unlock; | ||
862 | |||
863 | local->int_scan_req->n_channels = n_ch; | ||
866 | } else { | 864 | } else { |
865 | if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | | ||
866 | IEEE80211_CHAN_DISABLED))) | ||
867 | goto unlock; | ||
868 | |||
867 | local->int_scan_req->channels[0] = chan; | 869 | local->int_scan_req->channels[0] = chan; |
868 | local->int_scan_req->n_channels = 1; | 870 | local->int_scan_req->n_channels = 1; |
869 | } | 871 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f3e502502fee..ca9fde198188 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -91,9 +91,8 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
91 | return -ENOENT; | 91 | return -ENOENT; |
92 | } | 92 | } |
93 | 93 | ||
94 | static void free_sta_work(struct work_struct *wk) | 94 | static void cleanup_single_sta(struct sta_info *sta) |
95 | { | 95 | { |
96 | struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); | ||
97 | int ac, i; | 96 | int ac, i; |
98 | struct tid_ampdu_tx *tid_tx; | 97 | struct tid_ampdu_tx *tid_tx; |
99 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 98 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
@@ -153,11 +152,35 @@ static void free_sta_work(struct work_struct *wk) | |||
153 | sta_info_free(local, sta); | 152 | sta_info_free(local, sta); |
154 | } | 153 | } |
155 | 154 | ||
155 | void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) | ||
156 | { | ||
157 | struct sta_info *sta; | ||
158 | |||
159 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
160 | while (!list_empty(&sdata->cleanup_stations)) { | ||
161 | sta = list_first_entry(&sdata->cleanup_stations, | ||
162 | struct sta_info, list); | ||
163 | list_del(&sta->list); | ||
164 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
165 | |||
166 | cleanup_single_sta(sta); | ||
167 | |||
168 | spin_lock_bh(&sdata->cleanup_stations_lock); | ||
169 | } | ||
170 | |||
171 | spin_unlock_bh(&sdata->cleanup_stations_lock); | ||
172 | } | ||
173 | |||
156 | static void free_sta_rcu(struct rcu_head *h) | 174 | static void free_sta_rcu(struct rcu_head *h) |
157 | { | 175 | { |
158 | struct sta_info *sta = container_of(h, struct sta_info, rcu_head); | 176 | struct sta_info *sta = container_of(h, struct sta_info, rcu_head); |
177 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
159 | 178 | ||
160 | ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); | 179 | spin_lock(&sdata->cleanup_stations_lock); |
180 | list_add_tail(&sta->list, &sdata->cleanup_stations); | ||
181 | spin_unlock(&sdata->cleanup_stations_lock); | ||
182 | |||
183 | ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); | ||
161 | } | 184 | } |
162 | 185 | ||
163 | /* protected by RCU */ | 186 | /* protected by RCU */ |
@@ -310,7 +333,6 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
310 | 333 | ||
311 | spin_lock_init(&sta->lock); | 334 | spin_lock_init(&sta->lock); |
312 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 335 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); |
313 | INIT_WORK(&sta->free_sta_wk, free_sta_work); | ||
314 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 336 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
315 | mutex_init(&sta->ampdu_mlme.mtx); | 337 | mutex_init(&sta->ampdu_mlme.mtx); |
316 | 338 | ||
@@ -862,7 +884,7 @@ void sta_info_init(struct ieee80211_local *local) | |||
862 | 884 | ||
863 | void sta_info_stop(struct ieee80211_local *local) | 885 | void sta_info_stop(struct ieee80211_local *local) |
864 | { | 886 | { |
865 | del_timer(&local->sta_cleanup); | 887 | del_timer_sync(&local->sta_cleanup); |
866 | sta_info_flush(local, NULL); | 888 | sta_info_flush(local, NULL); |
867 | } | 889 | } |
868 | 890 | ||
@@ -891,6 +913,20 @@ int sta_info_flush(struct ieee80211_local *local, | |||
891 | } | 913 | } |
892 | mutex_unlock(&local->sta_mtx); | 914 | mutex_unlock(&local->sta_mtx); |
893 | 915 | ||
916 | rcu_barrier(); | ||
917 | |||
918 | if (sdata) { | ||
919 | ieee80211_cleanup_sdata_stas(sdata); | ||
920 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
921 | } else { | ||
922 | mutex_lock(&local->iflist_mtx); | ||
923 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
924 | ieee80211_cleanup_sdata_stas(sdata); | ||
925 | cancel_work_sync(&sdata->cleanup_stations_wk); | ||
926 | } | ||
927 | mutex_unlock(&local->iflist_mtx); | ||
928 | } | ||
929 | |||
894 | return ret; | 930 | return ret; |
895 | } | 931 | } |
896 | 932 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 1489bca9ea97..37c1889afd3a 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -299,7 +299,6 @@ struct sta_info { | |||
299 | spinlock_t lock; | 299 | spinlock_t lock; |
300 | 300 | ||
301 | struct work_struct drv_unblock_wk; | 301 | struct work_struct drv_unblock_wk; |
302 | struct work_struct free_sta_wk; | ||
303 | 302 | ||
304 | u16 listen_interval; | 303 | u16 listen_interval; |
305 | 304 | ||
@@ -563,4 +562,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); | |||
563 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); | 562 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); |
564 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); | 563 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); |
565 | 564 | ||
565 | void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); | ||
566 | |||
566 | #endif /* STA_INFO_H */ | 567 | #endif /* STA_INFO_H */ |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 1915ffe598e3..507b5e84fbdb 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -555,7 +555,7 @@ EXPORT_SYMBOL_GPL(rpc_clone_client); | |||
555 | * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth | 555 | * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth |
556 | * | 556 | * |
557 | * @clnt: RPC client whose parameters are copied | 557 | * @clnt: RPC client whose parameters are copied |
558 | * @auth: security flavor for new client | 558 | * @flavor: security flavor for new client |
559 | * | 559 | * |
560 | * Returns a fresh RPC client or an ERR_PTR. | 560 | * Returns a fresh RPC client or an ERR_PTR. |
561 | */ | 561 | */ |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index b4133bd13915..bfa31714581f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -972,8 +972,7 @@ static void rpc_async_release(struct work_struct *work) | |||
972 | 972 | ||
973 | static void rpc_release_resources_task(struct rpc_task *task) | 973 | static void rpc_release_resources_task(struct rpc_task *task) |
974 | { | 974 | { |
975 | if (task->tk_rqstp) | 975 | xprt_release(task); |
976 | xprt_release(task); | ||
977 | if (task->tk_msg.rpc_cred) { | 976 | if (task->tk_msg.rpc_cred) { |
978 | put_rpccred(task->tk_msg.rpc_cred); | 977 | put_rpccred(task->tk_msg.rpc_cred); |
979 | task->tk_msg.rpc_cred = NULL; | 978 | task->tk_msg.rpc_cred = NULL; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index bd462a532acf..33811db8788a 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1136,10 +1136,18 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) | |||
1136 | void xprt_release(struct rpc_task *task) | 1136 | void xprt_release(struct rpc_task *task) |
1137 | { | 1137 | { |
1138 | struct rpc_xprt *xprt; | 1138 | struct rpc_xprt *xprt; |
1139 | struct rpc_rqst *req; | 1139 | struct rpc_rqst *req = task->tk_rqstp; |
1140 | 1140 | ||
1141 | if (!(req = task->tk_rqstp)) | 1141 | if (req == NULL) { |
1142 | if (task->tk_client) { | ||
1143 | rcu_read_lock(); | ||
1144 | xprt = rcu_dereference(task->tk_client->cl_xprt); | ||
1145 | if (xprt->snd_task == task) | ||
1146 | xprt_release_write(xprt, task); | ||
1147 | rcu_read_unlock(); | ||
1148 | } | ||
1142 | return; | 1149 | return; |
1150 | } | ||
1143 | 1151 | ||
1144 | xprt = req->rq_xprt; | 1152 | xprt = req->rq_xprt; |
1145 | if (task->tk_ops->rpc_count_stats != NULL) | 1153 | if (task->tk_ops->rpc_count_stats != NULL) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 14d990400354..b677eab55b68 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -866,8 +866,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
866 | /* allow mac80211 to determine the timeout */ | 866 | /* allow mac80211 to determine the timeout */ |
867 | wdev->ps_timeout = -1; | 867 | wdev->ps_timeout = -1; |
868 | 868 | ||
869 | if (!dev->ethtool_ops) | 869 | netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops); |
870 | dev->ethtool_ops = &cfg80211_ethtool_ops; | ||
871 | 870 | ||
872 | if ((wdev->iftype == NL80211_IFTYPE_STATION || | 871 | if ((wdev->iftype == NL80211_IFTYPE_STATION || |
873 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || | 872 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 19ecc8de9e6b..d794abcc4b3b 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -215,7 +215,9 @@ static void devcgroup_css_free(struct cgroup *cgroup) | |||
215 | struct dev_cgroup *dev_cgroup; | 215 | struct dev_cgroup *dev_cgroup; |
216 | 216 | ||
217 | dev_cgroup = cgroup_to_devcgroup(cgroup); | 217 | dev_cgroup = cgroup_to_devcgroup(cgroup); |
218 | mutex_lock(&devcgroup_mutex); | ||
218 | dev_exception_clean(dev_cgroup); | 219 | dev_exception_clean(dev_cgroup); |
220 | mutex_unlock(&devcgroup_mutex); | ||
219 | kfree(dev_cgroup); | 221 | kfree(dev_cgroup); |
220 | } | 222 | } |
221 | 223 | ||
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index dfb26918699c..7dd538ef5b83 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c | |||
@@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, | |||
205 | rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, | 205 | rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, |
206 | &xattr_data, | 206 | &xattr_data, |
207 | sizeof(xattr_data), 0); | 207 | sizeof(xattr_data), 0); |
208 | } | 208 | } else if (rc == -ENODATA && inode->i_op->removexattr) { |
209 | else if (rc == -ENODATA) | ||
210 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); | 209 | rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); |
210 | } | ||
211 | return rc; | 211 | return rc; |
212 | } | 212 | } |
213 | 213 | ||
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 3d822328d383..64d534710b51 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
@@ -286,12 +286,14 @@ static int loopback_trigger(struct snd_pcm_substream *substream, int cmd) | |||
286 | loopback_active_notify(dpcm); | 286 | loopback_active_notify(dpcm); |
287 | break; | 287 | break; |
288 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 288 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
289 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
289 | spin_lock(&cable->lock); | 290 | spin_lock(&cable->lock); |
290 | cable->pause |= stream; | 291 | cable->pause |= stream; |
291 | loopback_timer_stop(dpcm); | 292 | loopback_timer_stop(dpcm); |
292 | spin_unlock(&cable->lock); | 293 | spin_unlock(&cable->lock); |
293 | break; | 294 | break; |
294 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 295 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
296 | case SNDRV_PCM_TRIGGER_RESUME: | ||
295 | spin_lock(&cable->lock); | 297 | spin_lock(&cable->lock); |
296 | dpcm->last_jiffies = jiffies; | 298 | dpcm->last_jiffies = jiffies; |
297 | cable->pause &= ~stream; | 299 | cable->pause &= ~stream; |
@@ -563,7 +565,8 @@ static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream) | |||
563 | static struct snd_pcm_hardware loopback_pcm_hardware = | 565 | static struct snd_pcm_hardware loopback_pcm_hardware = |
564 | { | 566 | { |
565 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | | 567 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | |
566 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), | 568 | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | |
569 | SNDRV_PCM_INFO_RESUME), | ||
567 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | | 570 | .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | |
568 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | | 571 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | |
569 | SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), | 572 | SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE), |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 3d8df7c6a3b9..d9e37ffdb048 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -656,29 +656,43 @@ static char *driver_short_names[] = { | |||
656 | #define get_azx_dev(substream) (substream->runtime->private_data) | 656 | #define get_azx_dev(substream) (substream->runtime->private_data) |
657 | 657 | ||
658 | #ifdef CONFIG_X86 | 658 | #ifdef CONFIG_X86 |
659 | static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on) | 659 | static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on) |
660 | { | 660 | { |
661 | int pages; | ||
662 | |||
661 | if (azx_snoop(chip)) | 663 | if (azx_snoop(chip)) |
662 | return; | 664 | return; |
663 | if (addr && size) { | 665 | if (!dmab || !dmab->area || !dmab->bytes) |
664 | int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 666 | return; |
667 | |||
668 | #ifdef CONFIG_SND_DMA_SGBUF | ||
669 | if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { | ||
670 | struct snd_sg_buf *sgbuf = dmab->private_data; | ||
665 | if (on) | 671 | if (on) |
666 | set_memory_wc((unsigned long)addr, pages); | 672 | set_pages_array_wc(sgbuf->page_table, sgbuf->pages); |
667 | else | 673 | else |
668 | set_memory_wb((unsigned long)addr, pages); | 674 | set_pages_array_wb(sgbuf->page_table, sgbuf->pages); |
675 | return; | ||
669 | } | 676 | } |
677 | #endif | ||
678 | |||
679 | pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
680 | if (on) | ||
681 | set_memory_wc((unsigned long)dmab->area, pages); | ||
682 | else | ||
683 | set_memory_wb((unsigned long)dmab->area, pages); | ||
670 | } | 684 | } |
671 | 685 | ||
672 | static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, | 686 | static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, |
673 | bool on) | 687 | bool on) |
674 | { | 688 | { |
675 | __mark_pages_wc(chip, buf->area, buf->bytes, on); | 689 | __mark_pages_wc(chip, buf, on); |
676 | } | 690 | } |
677 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, | 691 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, |
678 | struct snd_pcm_runtime *runtime, bool on) | 692 | struct snd_pcm_substream *substream, bool on) |
679 | { | 693 | { |
680 | if (azx_dev->wc_marked != on) { | 694 | if (azx_dev->wc_marked != on) { |
681 | __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on); | 695 | __mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on); |
682 | azx_dev->wc_marked = on; | 696 | azx_dev->wc_marked = on; |
683 | } | 697 | } |
684 | } | 698 | } |
@@ -689,7 +703,7 @@ static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf, | |||
689 | { | 703 | { |
690 | } | 704 | } |
691 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, | 705 | static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev, |
692 | struct snd_pcm_runtime *runtime, bool on) | 706 | struct snd_pcm_substream *substream, bool on) |
693 | { | 707 | { |
694 | } | 708 | } |
695 | #endif | 709 | #endif |
@@ -1975,11 +1989,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1975 | { | 1989 | { |
1976 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 1990 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
1977 | struct azx *chip = apcm->chip; | 1991 | struct azx *chip = apcm->chip; |
1978 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
1979 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1992 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1980 | int ret; | 1993 | int ret; |
1981 | 1994 | ||
1982 | mark_runtime_wc(chip, azx_dev, runtime, false); | 1995 | mark_runtime_wc(chip, azx_dev, substream, false); |
1983 | azx_dev->bufsize = 0; | 1996 | azx_dev->bufsize = 0; |
1984 | azx_dev->period_bytes = 0; | 1997 | azx_dev->period_bytes = 0; |
1985 | azx_dev->format_val = 0; | 1998 | azx_dev->format_val = 0; |
@@ -1987,7 +2000,7 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
1987 | params_buffer_bytes(hw_params)); | 2000 | params_buffer_bytes(hw_params)); |
1988 | if (ret < 0) | 2001 | if (ret < 0) |
1989 | return ret; | 2002 | return ret; |
1990 | mark_runtime_wc(chip, azx_dev, runtime, true); | 2003 | mark_runtime_wc(chip, azx_dev, substream, true); |
1991 | return ret; | 2004 | return ret; |
1992 | } | 2005 | } |
1993 | 2006 | ||
@@ -1996,7 +2009,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
1996 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); | 2009 | struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
1997 | struct azx_dev *azx_dev = get_azx_dev(substream); | 2010 | struct azx_dev *azx_dev = get_azx_dev(substream); |
1998 | struct azx *chip = apcm->chip; | 2011 | struct azx *chip = apcm->chip; |
1999 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2000 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 2012 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
2001 | 2013 | ||
2002 | /* reset BDL address */ | 2014 | /* reset BDL address */ |
@@ -2009,7 +2021,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream) | |||
2009 | 2021 | ||
2010 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); | 2022 | snd_hda_codec_cleanup(apcm->codec, hinfo, substream); |
2011 | 2023 | ||
2012 | mark_runtime_wc(chip, azx_dev, runtime, false); | 2024 | mark_runtime_wc(chip, azx_dev, substream, false); |
2013 | return snd_pcm_lib_free_pages(substream); | 2025 | return snd_pcm_lib_free_pages(substream); |
2014 | } | 2026 | } |
2015 | 2027 | ||
@@ -3624,13 +3636,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
3624 | /* 5 Series/3400 */ | 3636 | /* 5 Series/3400 */ |
3625 | { PCI_DEVICE(0x8086, 0x3b56), | 3637 | { PCI_DEVICE(0x8086, 0x3b56), |
3626 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, | 3638 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH }, |
3627 | /* SCH */ | 3639 | /* Poulsbo */ |
3628 | { PCI_DEVICE(0x8086, 0x811b), | 3640 | { PCI_DEVICE(0x8086, 0x811b), |
3629 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3641 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
3630 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */ | 3642 | /* Oaktrail */ |
3631 | { PCI_DEVICE(0x8086, 0x080a), | 3643 | { PCI_DEVICE(0x8086, 0x080a), |
3632 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3644 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, |
3633 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ | ||
3634 | /* ICH */ | 3645 | /* ICH */ |
3635 | { PCI_DEVICE(0x8086, 0x2668), | 3646 | { PCI_DEVICE(0x8086, 0x2668), |
3636 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | | 3647 | .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC | |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 1b3b4ee3e8a7..85236da79046 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -714,9 +714,10 @@ static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | |||
714 | 714 | ||
715 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 715 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
716 | hda_nid_t pin_nid, bool non_pcm, int ca, | 716 | hda_nid_t pin_nid, bool non_pcm, int ca, |
717 | int channels, unsigned char *map) | 717 | int channels, unsigned char *map, |
718 | bool chmap_set) | ||
718 | { | 719 | { |
719 | if (!non_pcm && map) { | 720 | if (!non_pcm && chmap_set) { |
720 | hdmi_manual_setup_channel_mapping(codec, pin_nid, | 721 | hdmi_manual_setup_channel_mapping(codec, pin_nid, |
721 | channels, map); | 722 | channels, map); |
722 | } else { | 723 | } else { |
@@ -905,7 +906,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
905 | pin_nid, | 906 | pin_nid, |
906 | channels); | 907 | channels); |
907 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | 908 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
908 | channels, per_pin->chmap); | 909 | channels, per_pin->chmap, |
910 | per_pin->chmap_set); | ||
909 | hdmi_stop_infoframe_trans(codec, pin_nid); | 911 | hdmi_stop_infoframe_trans(codec, pin_nid); |
910 | hdmi_fill_audio_infoframe(codec, pin_nid, | 912 | hdmi_fill_audio_infoframe(codec, pin_nid, |
911 | ai.bytes, sizeof(ai)); | 913 | ai.bytes, sizeof(ai)); |
@@ -915,7 +917,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
915 | * accordingly */ | 917 | * accordingly */ |
916 | if (per_pin->non_pcm != non_pcm) | 918 | if (per_pin->non_pcm != non_pcm) |
917 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | 919 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
918 | channels, per_pin->chmap); | 920 | channels, per_pin->chmap, |
921 | per_pin->chmap_set); | ||
919 | } | 922 | } |
920 | 923 | ||
921 | per_pin->non_pcm = non_pcm; | 924 | per_pin->non_pcm = non_pcm; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index dc75607fc05b..de512c52fa96 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2363,6 +2363,7 @@ static const struct hda_model_fixup alc268_fixup_models[] = { | |||
2363 | }; | 2363 | }; |
2364 | 2364 | ||
2365 | static const struct snd_pci_quirk alc268_fixup_tbl[] = { | 2365 | static const struct snd_pci_quirk alc268_fixup_tbl[] = { |
2366 | SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC), | ||
2366 | /* below is codec SSID since multiple Toshiba laptops have the | 2367 | /* below is codec SSID since multiple Toshiba laptops have the |
2367 | * same PCI SSID 1179:ff00 | 2368 | * same PCI SSID 1179:ff00 |
2368 | */ | 2369 | */ |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1d8bb5917594..ef62c435848e 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -685,7 +685,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream, | |||
685 | } | 685 | } |
686 | sr_val = i; | 686 | sr_val = i; |
687 | 687 | ||
688 | lrclk = snd_soc_params_to_bclk(params) / params_rate(params); | 688 | lrclk = rates[bclk] / params_rate(params); |
689 | 689 | ||
690 | arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", | 690 | arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n", |
691 | rates[bclk], rates[bclk] / lrclk); | 691 | rates[bclk], rates[bclk] / lrclk); |
@@ -1082,6 +1082,9 @@ int arizona_init_fll(struct arizona *arizona, int id, int base, int lock_irq, | |||
1082 | id, ret); | 1082 | id, ret); |
1083 | } | 1083 | } |
1084 | 1084 | ||
1085 | regmap_update_bits(arizona->regmap, fll->base + 1, | ||
1086 | ARIZONA_FLL1_FREERUN, 0); | ||
1087 | |||
1085 | return 0; | 1088 | return 0; |
1086 | } | 1089 | } |
1087 | EXPORT_SYMBOL_GPL(arizona_init_fll); | 1090 | EXPORT_SYMBOL_GPL(arizona_init_fll); |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index e6cefe1ac677..d8c65f574658 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -1019,8 +1019,6 @@ static const char *wm2200_mixer_texts[] = { | |||
1019 | "EQR", | 1019 | "EQR", |
1020 | "LHPF1", | 1020 | "LHPF1", |
1021 | "LHPF2", | 1021 | "LHPF2", |
1022 | "LHPF3", | ||
1023 | "LHPF4", | ||
1024 | "DSP1.1", | 1022 | "DSP1.1", |
1025 | "DSP1.2", | 1023 | "DSP1.2", |
1026 | "DSP1.3", | 1024 | "DSP1.3", |
@@ -1053,7 +1051,6 @@ static int wm2200_mixer_values[] = { | |||
1053 | 0x25, | 1051 | 0x25, |
1054 | 0x50, /* EQ */ | 1052 | 0x50, /* EQ */ |
1055 | 0x51, | 1053 | 0x51, |
1056 | 0x52, | ||
1057 | 0x60, /* LHPF1 */ | 1054 | 0x60, /* LHPF1 */ |
1058 | 0x61, /* LHPF2 */ | 1055 | 0x61, /* LHPF2 */ |
1059 | 0x68, /* DSP1 */ | 1056 | 0x68, /* DSP1 */ |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 7a9048dad1cd..1440b3f9b7bb 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -896,8 +896,7 @@ static const unsigned int wm5102_aec_loopback_values[] = { | |||
896 | 896 | ||
897 | static const struct soc_enum wm5102_aec_loopback = | 897 | static const struct soc_enum wm5102_aec_loopback = |
898 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | 898 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, |
899 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | 899 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, |
900 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
901 | ARRAY_SIZE(wm5102_aec_loopback_texts), | 900 | ARRAY_SIZE(wm5102_aec_loopback_texts), |
902 | wm5102_aec_loopback_texts, | 901 | wm5102_aec_loopback_texts, |
903 | wm5102_aec_loopback_values); | 902 | wm5102_aec_loopback_values); |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index ae80c8c28536..7a090968c4f7 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -344,8 +344,7 @@ static const unsigned int wm5110_aec_loopback_values[] = { | |||
344 | 344 | ||
345 | static const struct soc_enum wm5110_aec_loopback = | 345 | static const struct soc_enum wm5110_aec_loopback = |
346 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | 346 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, |
347 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | 347 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf, |
348 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
349 | ARRAY_SIZE(wm5110_aec_loopback_texts), | 348 | ARRAY_SIZE(wm5110_aec_loopback_texts), |
350 | wm5110_aec_loopback_texts, | 349 | wm5110_aec_loopback_texts, |
351 | wm5110_aec_loopback_values); | 350 | wm5110_aec_loopback_values); |
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 7b198c38f3ef..b6b654837585 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -324,7 +324,7 @@ static int wm_adsp_load(struct wm_adsp *dsp) | |||
324 | 324 | ||
325 | if (reg) { | 325 | if (reg) { |
326 | buf = kmemdup(region->data, le32_to_cpu(region->len), | 326 | buf = kmemdup(region->data, le32_to_cpu(region->len), |
327 | GFP_KERNEL); | 327 | GFP_KERNEL | GFP_DMA); |
328 | if (!buf) { | 328 | if (!buf) { |
329 | adsp_err(dsp, "Out of memory\n"); | 329 | adsp_err(dsp, "Out of memory\n"); |
330 | return -ENOMEM; | 330 | return -ENOMEM; |
@@ -396,7 +396,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
396 | hdr = (void*)&firmware->data[0]; | 396 | hdr = (void*)&firmware->data[0]; |
397 | if (memcmp(hdr->magic, "WMDR", 4) != 0) { | 397 | if (memcmp(hdr->magic, "WMDR", 4) != 0) { |
398 | adsp_err(dsp, "%s: invalid magic\n", file); | 398 | adsp_err(dsp, "%s: invalid magic\n", file); |
399 | return -EINVAL; | 399 | goto out_fw; |
400 | } | 400 | } |
401 | 401 | ||
402 | adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, | 402 | adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, |
@@ -439,7 +439,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp) | |||
439 | 439 | ||
440 | if (reg) { | 440 | if (reg) { |
441 | buf = kmemdup(blk->data, le32_to_cpu(blk->len), | 441 | buf = kmemdup(blk->data, le32_to_cpu(blk->len), |
442 | GFP_KERNEL); | 442 | GFP_KERNEL | GFP_DMA); |
443 | if (!buf) { | 443 | if (!buf) { |
444 | adsp_err(dsp, "Out of memory\n"); | 444 | adsp_err(dsp, "Out of memory\n"); |
445 | return -ENOMEM; | 445 | return -ENOMEM; |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3b98159d9645..a210c8d7b4bc 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -108,18 +108,13 @@ if SND_IMX_SOC | |||
108 | config SND_SOC_IMX_SSI | 108 | config SND_SOC_IMX_SSI |
109 | tristate | 109 | tristate |
110 | 110 | ||
111 | config SND_SOC_IMX_PCM | ||
112 | tristate | ||
113 | |||
114 | config SND_SOC_IMX_PCM_FIQ | 111 | config SND_SOC_IMX_PCM_FIQ |
115 | bool | 112 | tristate |
116 | select FIQ | 113 | select FIQ |
117 | select SND_SOC_IMX_PCM | ||
118 | 114 | ||
119 | config SND_SOC_IMX_PCM_DMA | 115 | config SND_SOC_IMX_PCM_DMA |
120 | bool | 116 | tristate |
121 | select SND_SOC_DMAENGINE_PCM | 117 | select SND_SOC_DMAENGINE_PCM |
122 | select SND_SOC_IMX_PCM | ||
123 | 118 | ||
124 | config SND_SOC_IMX_AUDMUX | 119 | config SND_SOC_IMX_AUDMUX |
125 | tristate | 120 | tristate |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index afd34794db53..ec1457915d7c 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -41,7 +41,10 @@ endif | |||
41 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o | 41 | obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o |
42 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o | 42 | obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o |
43 | 43 | ||
44 | obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o | 44 | obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += snd-soc-imx-pcm-fiq.o |
45 | snd-soc-imx-pcm-fiq-y := imx-pcm-fiq.o imx-pcm.o | ||
46 | obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += snd-soc-imx-pcm-dma.o | ||
47 | snd-soc-imx-pcm-dma-y := imx-pcm-dma.o imx-pcm.o | ||
45 | 48 | ||
46 | # i.MX Machine Support | 49 | # i.MX Machine Support |
47 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o | 50 | snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o |
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c index d5cd9eff3b48..0c9f188ddc68 100644 --- a/sound/soc/fsl/imx-pcm.c +++ b/sound/soc/fsl/imx-pcm.c | |||
@@ -31,7 +31,6 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, | |||
31 | runtime->dma_bytes); | 31 | runtime->dma_bytes); |
32 | return ret; | 32 | return ret; |
33 | } | 33 | } |
34 | EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap); | ||
35 | 34 | ||
36 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | 35 | static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) |
37 | { | 36 | { |
@@ -80,7 +79,6 @@ int imx_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
80 | out: | 79 | out: |
81 | return ret; | 80 | return ret; |
82 | } | 81 | } |
83 | EXPORT_SYMBOL_GPL(imx_pcm_new); | ||
84 | 82 | ||
85 | void imx_pcm_free(struct snd_pcm *pcm) | 83 | void imx_pcm_free(struct snd_pcm *pcm) |
86 | { | 84 | { |
@@ -102,7 +100,6 @@ void imx_pcm_free(struct snd_pcm *pcm) | |||
102 | buf->area = NULL; | 100 | buf->area = NULL; |
103 | } | 101 | } |
104 | } | 102 | } |
105 | EXPORT_SYMBOL_GPL(imx_pcm_free); | ||
106 | 103 | ||
107 | MODULE_DESCRIPTION("Freescale i.MX PCM driver"); | 104 | MODULE_DESCRIPTION("Freescale i.MX PCM driver"); |
108 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | 105 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 1e36bc81e5af..258acadb9e7d 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -1023,7 +1023,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
1023 | 1023 | ||
1024 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 1024 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
1025 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | 1025 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { |
1026 | ret = regulator_allow_bypass(w->regulator, true); | 1026 | ret = regulator_allow_bypass(w->regulator, false); |
1027 | if (ret != 0) | 1027 | if (ret != 0) |
1028 | dev_warn(w->dapm->dev, | 1028 | dev_warn(w->dapm->dev, |
1029 | "ASoC: Failed to bypass %s: %d\n", | 1029 | "ASoC: Failed to bypass %s: %d\n", |
@@ -1033,7 +1033,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w, | |||
1033 | return regulator_enable(w->regulator); | 1033 | return regulator_enable(w->regulator); |
1034 | } else { | 1034 | } else { |
1035 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | 1035 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { |
1036 | ret = regulator_allow_bypass(w->regulator, false); | 1036 | ret = regulator_allow_bypass(w->regulator, true); |
1037 | if (ret != 0) | 1037 | if (ret != 0) |
1038 | dev_warn(w->dapm->dev, | 1038 | dev_warn(w->dapm->dev, |
1039 | "ASoC: Failed to unbypass %s: %d\n", | 1039 | "ASoC: Failed to unbypass %s: %d\n", |
@@ -3039,6 +3039,14 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, | |||
3039 | w->name, ret); | 3039 | w->name, ret); |
3040 | return NULL; | 3040 | return NULL; |
3041 | } | 3041 | } |
3042 | |||
3043 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | ||
3044 | ret = regulator_allow_bypass(w->regulator, true); | ||
3045 | if (ret != 0) | ||
3046 | dev_warn(w->dapm->dev, | ||
3047 | "ASoC: Failed to unbypass %s: %d\n", | ||
3048 | w->name, ret); | ||
3049 | } | ||
3042 | break; | 3050 | break; |
3043 | case snd_soc_dapm_clock_supply: | 3051 | case snd_soc_dapm_clock_supply: |
3044 | #ifdef CONFIG_CLKDEV_LOOKUP | 3052 | #ifdef CONFIG_CLKDEV_LOOKUP |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ed4d89c8b52a..e90daf8cdaa8 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -1331,16 +1331,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
1331 | } | 1331 | } |
1332 | channels = (hdr->bLength - 7) / csize - 1; | 1332 | channels = (hdr->bLength - 7) / csize - 1; |
1333 | bmaControls = hdr->bmaControls; | 1333 | bmaControls = hdr->bmaControls; |
1334 | if (hdr->bLength < 7 + csize) { | ||
1335 | snd_printk(KERN_ERR "usbaudio: unit %u: " | ||
1336 | "invalid UAC_FEATURE_UNIT descriptor\n", | ||
1337 | unitid); | ||
1338 | return -EINVAL; | ||
1339 | } | ||
1334 | } else { | 1340 | } else { |
1335 | struct uac2_feature_unit_descriptor *ftr = _ftr; | 1341 | struct uac2_feature_unit_descriptor *ftr = _ftr; |
1336 | csize = 4; | 1342 | csize = 4; |
1337 | channels = (hdr->bLength - 6) / 4 - 1; | 1343 | channels = (hdr->bLength - 6) / 4 - 1; |
1338 | bmaControls = ftr->bmaControls; | 1344 | bmaControls = ftr->bmaControls; |
1339 | } | 1345 | if (hdr->bLength < 6 + csize) { |
1340 | 1346 | snd_printk(KERN_ERR "usbaudio: unit %u: " | |
1341 | if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { | 1347 | "invalid UAC_FEATURE_UNIT descriptor\n", |
1342 | snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); | 1348 | unitid); |
1343 | return -EINVAL; | 1349 | return -EINVAL; |
1350 | } | ||
1344 | } | 1351 | } |
1345 | 1352 | ||
1346 | /* parse the source unit */ | 1353 | /* parse the source unit */ |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 64d25a7a4d59..820580a6dfc3 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
@@ -1750,7 +1750,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1750 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | 1750 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { |
1751 | /* .vendor_name = "Roland", */ | 1751 | /* .vendor_name = "Roland", */ |
1752 | /* .product_name = "A-PRO", */ | 1752 | /* .product_name = "A-PRO", */ |
1753 | .ifnum = 1, | 1753 | .ifnum = 0, |
1754 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | 1754 | .type = QUIRK_MIDI_FIXED_ENDPOINT, |
1755 | .data = & (const struct snd_usb_midi_endpoint_info) { | 1755 | .data = & (const struct snd_usb_midi_endpoint_info) { |
1756 | .out_cables = 0x0003, | 1756 | .out_cables = 0x0003, |
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 80db3f4bcf7a..39d41068484f 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
@@ -11,11 +11,21 @@ lib/rbtree.c | |||
11 | include/linux/swab.h | 11 | include/linux/swab.h |
12 | arch/*/include/asm/unistd*.h | 12 | arch/*/include/asm/unistd*.h |
13 | arch/*/include/asm/perf_regs.h | 13 | arch/*/include/asm/perf_regs.h |
14 | arch/*/include/uapi/asm/unistd*.h | ||
15 | arch/*/include/uapi/asm/perf_regs.h | ||
14 | arch/*/lib/memcpy*.S | 16 | arch/*/lib/memcpy*.S |
15 | arch/*/lib/memset*.S | 17 | arch/*/lib/memset*.S |
16 | include/linux/poison.h | 18 | include/linux/poison.h |
17 | include/linux/magic.h | 19 | include/linux/magic.h |
18 | include/linux/hw_breakpoint.h | 20 | include/linux/hw_breakpoint.h |
21 | include/linux/rbtree_augmented.h | ||
22 | include/uapi/linux/perf_event.h | ||
23 | include/uapi/linux/const.h | ||
24 | include/uapi/linux/swab.h | ||
25 | include/uapi/linux/hw_breakpoint.h | ||
19 | arch/x86/include/asm/svm.h | 26 | arch/x86/include/asm/svm.h |
20 | arch/x86/include/asm/vmx.h | 27 | arch/x86/include/asm/vmx.h |
21 | arch/x86/include/asm/kvm_host.h | 28 | arch/x86/include/asm/kvm_host.h |
29 | arch/x86/include/uapi/asm/svm.h | ||
30 | arch/x86/include/uapi/asm/vmx.h | ||
31 | arch/x86/include/uapi/asm/kvm.h | ||
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 891bc77bdb2c..8ab05e543ef4 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -58,7 +58,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ | |||
58 | -e s/arm.*/arm/ -e s/sa110/arm/ \ | 58 | -e s/arm.*/arm/ -e s/sa110/arm/ \ |
59 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ | 59 | -e s/s390x/s390/ -e s/parisc64/parisc/ \ |
60 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ | 60 | -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ |
61 | -e s/sh[234].*/sh/ ) | 61 | -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ ) |
62 | NO_PERF_REGS := 1 | 62 | NO_PERF_REGS := 1 |
63 | 63 | ||
64 | CC = $(CROSS_COMPILE)gcc | 64 | CC = $(CROSS_COMPILE)gcc |